tid = $term->tid; $this->name = $term->name; $this->depth = $term->depth; $this->sequence = $term->sequence; } } /** * Determines if new child is an immediate descendant or not. * * This function is completely dependent on the structure of the array returned * by taxonomy_get_tree(). Each element in the array knows it's depth in the tree * and the array is a preorder iteration of the logical tree structure. Therefore, * if the parameter is more than one level deeper than $this, it should be passed * to the last child of $this. */ function add_child(&$child) { if ($child->depth - $this->depth == 1) { $this->children[] = $child; } else { $last_child =&$this->children[count($this->children)-1]; $last_child->add_child($child); } } } /****************************************************************************** * Drupal Hooks * ******************************************************************************/ /** * Implementation of hook_menu(). */ function uc_catalog_menu($may_cache) { global $user; $items = array(); if ($may_cache) { $items[] = array('path' => 'catalog', 'access' => user_access('view catalog'), 'title' => variable_get('uc_catalog_name', t('Catalog')), 'callback' => 'theme', 'callback arguments' => array('uc_catalog_browse'), 'type' => MENU_SUGGESTED_ITEM, ); $items[] = array('path' => 'admin/store/settings/catalog', 'access' => user_access('administer catalog'), 'title' => t('Catalog settings'), 'description' => t('Configure the catalog settings.'), 'callback' => 'uc_catalog_settings_overview', 'type' => MENU_NORMAL_ITEM, ); $items[] = array('path' => 'admin/store/settings/catalog/overview', 'access' => user_access('administer catalog'), 'title' => t('Overview'), 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[] = array('path' => 'admin/store/settings/catalog/edit', 'access' => user_access('administer catalog'), 'title' => t('Edit'), 'callback' => 'uc_catalog_admin_settings', 'weight' => -5, 'type' => MENU_LOCAL_TASK, ); $items[] = array('path' => 'admin/store/settings/catalog/edit/catalog', 'access' => user_access('administer catalog'), 'title' => t('Catalog'), 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[] = array('path' => 'admin/store/settings/catalog/edit/grid', 'access' => user_access('administer catalog'), 'title' => t('Grid'), 'callback' => 'drupal_get_form', 'callback arguments' => array('uc_catalog_grid_admin_form'), 'weight' => -5, 'type' => MENU_LOCAL_TASK, ); $items[] = array('path' => 'admin/store/products/orphans', 'title' => t('Find orphaned products'), 'access' => user_access('administer catalog'), 'callback' => 'uc_catalog_orphaned_products', 'description' => t('Find products that have not been categorized.'), 'type' => MENU_NORMAL_ITEM, 'weight' => -4 ); if (module_exists('ubrowser')) { $items[] = array('path' => 'admin/store/products/categories', 'access' => user_access('administer catalog'), 'title' => t('Move products'), 'callback' => 'drupal_get_form', 'callback arguments' => 'uc_catalog_set_category_form', 'type' => MENU_NORMAL_ITEM, 'weight' => -6, ); } } return $items; } /** * Implementation of hook_perm(). */ function uc_catalog_perm() { return array('view catalog', 'administer catalog'); } /** * Implementation of hook_enable(). * * Add imagecache preset "uc_category". */ function uc_catalog_enable() { if (module_exists('imagecache')) { $result = db_query("SELECT presetid FROM {imagecache_preset} WHERE presetname = 'uc_category'"); if (!db_fetch_object($result)) { $id = db_next_id('{imagecache_preset}_presetid'); db_query("INSERT INTO {imagecache_preset} (presetid, presetname) VALUES (%d, 'uc_category')", $id); db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $id, 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:2:"96";s:6:"height";s:2:"96";}'); cache_clear_all('imagecache:presets', 'cache'); } } } /** * Implementation of hook_nodeapi(). */ function uc_catalog_nodeapi(&$node, $op, $a3 = null, $a4 = null) { static $parents = array(); if (in_array($node->type, module_invoke_all('product_types'))) { switch ($op) { case 'view': if ($a4 == true && variable_get('uc_catalog_breadcrumb', true)) { $crumbs = array(); if (variable_get('site_frontpage', 'node') != 'catalog') { $crumbs[] = l(t('Home'), ''); } $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, variable_get('uc_catalog_vid', 0)); if (count($terms)) { $crumbs[] = l(variable_get('uc_catalog_name', t('Catalog')), variable_get('uc_catalog_url','catalog')); $used_tids = array(); foreach ($terms as $term) { if (!isset($parents[$term->tid])) { $parents[$term->tid] = taxonomy_get_parents_all($term->tid); } //drupal_set_message('
'. print_r($parents[$term->tid], true) .''); foreach (array_reverse($parents[$term->tid]) as $parent) { if (!in_array($parent->tid, $used_tids)) { $crumbs[] = l($parent->name, uc_catalog_path($parent)); $used_tids[] = $parent->tid; } } } } drupal_set_breadcrumb($crumbs); } break; } } } /** * Implementation of hook_taxonomy(). */ function uc_catalog_taxonomy($op, $type, $object = null) { switch ($type) { case 'vocabulary': if ($object['vid'] == variable_get('uc_catalog_vid', 0)) { switch ($op) { case 'delete': variable_del('uc_catalog_vid'); variable_del('uc_catalog_name'); variable_del('uc_catalog_description'); break; case 'update': variable_set('uc_catalog_name', check_plain($object['name'])); variable_set('uc_catalog_description', filter_xss_admin($object['description'])); break; } } break; case 'term': switch ($op) { case 'insert': if (module_exists('pathauto')) { $category = (object) $object; if ($category->name) { $count = _uc_catalog_pathauto_alias($category, $op); } } $field_name = 'image'; if ($file = file_check_upload($field_name)) { $file->filepath = str_replace('\\', '/', $file->filepath); $image_path = file_create_path(); $file = file_save_upload($field_name, $image_path .'/'. $file->filename); if ($file) { if (image_get_info($file->filepath)) { db_query("INSERT INTO {uc_catalog_images} (fid, tid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", db_next_id('{files}_fid'), $object['tid'], $file->filename, $file->filepath, $file->filemime, $file->filesize ); } else { form_set_error($field_name, t('Uploaded file is not a valid image')); file_delete($file->filepath); } } } break; case 'update': if (module_exists('pathauto')) { $category = (object) $object; if ($category->name) { $count = _uc_catalog_pathauto_alias($category, $op); } } $field_name = 'image'; if ($object['remove']) { db_query("DELETE FROM {uc_catalog_images} WHERE tid = %d", $object['tid']); } else if ($file = file_check_upload($field_name)) { $file->filepath = str_replace('\\', '/', $file->filepath); $file = file_save_upload($field_name, file_create_path() .'/'. $file->filename); if ($file) { if (image_get_info($file->filepath)) { db_query("DELETE FROM {uc_catalog_images} WHERE tid = %d", $object['tid']); db_query("INSERT INTO {uc_catalog_images} (fid, tid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", db_next_id('{files}_fid'), $object['tid'], $file->filename, $file->filepath, $file->filemime, $file->filesize ); } else { form_set_error($field_name, t('Uploaded file is not a valid image')); file_delete($file->filepath); } } } break; case 'delete': $category = (object) $object; if ($file = db_fetch_object(db_query("SELECT fid, filepath FROM {uc_catalog_images} WHERE tid = %d", $category->tid))) { file_delete($file->filepath); db_query("DELETE FROM {uc_catalog_images} WHERE fid = %d", $file->fid); } path_set_alias(uc_catalog_path($category)); break; } break; } } /** * Add an image field to the catalog's taxonomy term form. */ function uc_catalog_form_alter($form_id, &$form) { if ($form_id == 'taxonomy_form_term' && $form['vid']['#value'] == variable_get('uc_catalog_vid', 0)) { $form['#attributes'] = array("enctype" => "multipart/form-data"); $form['name']['#weight'] = -1; $form['image']['#weight'] = 0; $form['image']['image'] = array('#type' => 'file', '#title' => t('Image'), '#weight' => 0, ); $image = uc_catalog_image_load($form['tid']['#value']); if ($image) { if (module_exists('imagecache')) { $image_display = theme('imagecache', 'uc_category', $image->filepath); } else { $image_display = theme('image', $image->filename, t('Term image')); $form['image']['image']['#description'] = t('The image will not be resized. Consider installing Image cache.', array('@url' => url('http://drupal.org/project/imagecache'))); } $form['image']['remove'] = array('#type' => 'checkbox', '#title' => t('Remove category image: !image', array('!image' => $image_display)), '#weight' => 1, ); } $form['description']['#description'] = t('A description of the term. Displayed to customers at the top of catalog pages.'); } } /** * Implementation of hook_link_alter(). * * Rewrite taxonomy term links to point to the catalog. */ function uc_catalog_link_alter(&$node, &$links) { // Link back to the catalog and not the taxonomy term page foreach ($links AS $module => $link) { if (strstr($module, 'taxonomy_term')) { $tid = explode('_', $module); $tid = $tid[2]; $term = taxonomy_get_term($tid); if ($term->vid == variable_get('uc_catalog_vid', 0)) { $links[$module]['href'] = uc_catalog_path($term); } } } } /** * Displays a menu for navigating the "Product Catalog" */ function uc_catalog_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': $blocks[0] = array( 'info' => variable_get('uc_catalog_name', t('Catalog')), 'status' => 1, ); return $blocks; case 'view': $block = array(); if (user_access('view catalog')) { switch ($delta) { case 0: // Get the vocabulary tree information. $vid = variable_get('uc_catalog_vid', 0); $tree = taxonomy_get_tree($vid); // Then convert it into an actual tree structure. $seq = 0; $menu_tree = new uc_treeNode(); $level = array(); $curr_depth = -1; foreach ($tree as $knot) { $seq++; $knot->sequence = $seq; $knothole = new uc_treeNode($knot); // Begin at the root of the tree and find the proper place. $menu_tree->add_child($knothole); } // Now, create a structured menu, separate from Drupal's menu. $content .= theme("uc_catalog_block_start"); foreach ($menu_tree->children as $branch) { list($inpath, $html) = _uc_catalog_navigation($branch); $content .= $html; } $content .= theme("uc_catalog_block_end"); $subject = variable_get('uc_catalog_name', t('Catalog')); if (variable_get('uc_catalog_block_title', true)) { $subject = l($subject, 'catalog'); } $block = array('subject' => $subject, 'content' => $content); break; } } return $block; } } /** * Theme the beginning of the catalog block. * * @ingroup themeable * @see theme_uc_catalog_item * @see theme_uc_catalog_block_end */ function theme_uc_catalog_block_start() { return ' '; } /****************************************************************************** * Module Hooks * ******************************************************************************/ function uc_catalog_pathauto($op) { switch ($op) { case 'settings': $settings = array(); $settings['module'] = 'uc_catalog'; $settings['token_type'] = 'taxonomy'; $settings['groupheader'] = t('Catalog path settings'); $settings['patterndescr'] = t('Pattern for catalog pages'); $settings['patterndefault'] = t('catalog/[catpath-raw]'); $patterns = token_get_list('taxonomy'); foreach ($patterns as $type => $pattern_set) { if ($type != 'global') { foreach ($pattern_set as $pattern => $description) { $settings['placeholders']['['. $pattern .']'] = $description; } } } $settings['supportsfeeds'] = '0/feed'; $settings['bulkname'] = t('Bulk generate aliases for catalog pages that are not aliased'); $settings['bulkdescr'] = t('Generate aliases for all existing catalog pages which do not already have aliases. Note: Bulk Update may not complete on large or slow sites. See the README.txt for more information.'); return (object) $settings; } } /** * Generate aliases for all categories without aliases * */ function uc_catalog_pathauto_bulkupdate() { $catalog_vid = variable_get('uc_catalog_vid', 0); $query = "SELECT tid, vid, name, src, dst FROM {term_data} LEFT JOIN {url_alias} ON src LIKE CONCAT('catalog/', CAST(tid AS CHAR)) WHERE src IS NULL AND vid = %d"; $result = db_query_range($query, $catalog_vid, 0, variable_get('pathauto_max_bulk_update', 50)); $count = 0; $placeholders = array(); while ($category = db_fetch_object($result)) { $count = _uc_catalog_pathauto_alias($category, 'bulkupdate') + $count; } drupal_set_message(format_plural($count, "Bulk generation of terms completed, @count alias generated.", "Bulk generation of terms completed, @count aliases generated.")); } /** * * Function to create aliases for taxonomy objects * * @param object $category a taxonomy object * */ function _uc_catalog_pathauto_alias($category, $op) { _pathauto_include(); $count = 0; $placeholders = pathauto_get_placeholders('taxonomy', $category); $src = uc_catalog_path($category); if ($alias = pathauto_create_alias('uc_catalog', $op, $placeholders, $src, $category->vid)) { $count++; } return $count; } function uc_catalog_path_alias_types() { return array('catalog/' => t('catalog pages')); } /****************************************************************************** * Übercart Hooks * ******************************************************************************/ /** * Implementation of Übercart's hook_store_status(). * * Provide status information about the "Product Catalog" and products not listed in the catalog. */ function uc_catalog_store_status() { $statuses = array(); $cat_id = variable_get('uc_catalog_vid', 0); $catalog = taxonomy_get_vocabulary($cat_id); if ($catalog) { $statuses[] = array('status' => 'ok', 'title' => t('Catalog vocabulary'), 'desc' => t('Vocabulary !name has been identified as the !uber catalog.', array('!name' => l($catalog->name, 'admin/content/taxonomy/'. $catalog->vid), '!uber' => 'Übercart')) ); $excluded = 0; $result = db_query("SELECT DISTINCT * FROM {node} AS n LEFT JOIN {term_node} AS tn ON n.nid = tn.nid LEFT JOIN {vocabulary_node_types} AS vnt ON n.type = vnt.type WHERE n.type != 'image' AND tn.tid IS NULL AND vnt.vid = %d", $cat_id); $excluded = db_num_rows($result); if ($excluded) { $description = format_plural($excluded, 'There is @count product not listed in the catalog.', 'There are @count products not listed in the catalog.') . t(' Products are listed by assigning a category from the Product Catalog vocabulary to them.', array('!cat_url' => url('admin/content/taxonomy/'. $catalog->vid))); $terms = db_result(db_query("SELECT COUNT(*) FROM {term_data} WHERE vid = %d", $catalog->vid)); if ($terms) { $description .= ' '. l(t('Find orphaned products here.'), 'admin/store/products/orphans'); } else { $description .= ' '. l(t('Add terms for the products to inhabit.'), 'admin/content/taxonomy/'. $catalog->vid .'/add/term'); } $statuses[] = array( 'status' => 'warning', 'title' => t('Unlisted products'), 'desc' => $description, ); } } else { $statuses[] = array('status' => 'error', 'title' => t('Catalog vocabulary'), 'desc' => t('No vocabulary has been recognized as the Ubercart catalog. Choose one on this page or click here to create one first.', array('!admin_catalog' => url('admin/store/settings/catalog'), '!admin_vocab' => url('admin/content/taxonomy'))), ); } return $statuses; } /** * Implementation of Übercart's hook_product_class. * * Add and remove product node types to the catalog vocabulary as they are * created and deleted. */ function uc_catalog_product_class($type, $op) { $vid = variable_get('uc_catalog_vid', 0); switch ($op) { case 'insert': if ($vid) { db_query("INSERT INTO {vocabulary_node_types} (vid, type) VALUES (%d, '%s')", $vid, $type); } break; case 'delete': if ($vid) { db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d AND type = '%s'", $vid, $type); } break; } } /****************************************************************************** * Menu Callbacks * ******************************************************************************/ /** * Display an overview of all catalog settings. */ function uc_catalog_settings_overview() { $sections = array(); $sections[] = array( 'edit' => 'admin/store/settings/catalog/edit', 'title' => t('Catalog settings'), 'items' => array( t('The catalog vocabulary id is !vid.', array('!vid' => variable_get('uc_catalog_vid', 0))), t('The base URL pointing to the catalog is !url.', array('!url' => 'catalog')), variable_get('uc_catalog_breadcrumb', true) ? t('The catalog breadcrumb will be shown.') : t('The catalog breadcrumb will not be shown.'), variable_get('uc_catalog_breadcrumb_nodecount', false) ? t('The number of nodes in a category will be shown in the catalog breadcrumb.') : t('The number of nodes in a category will not be shown in the catalog breadcrumb.'), format_plural(variable_get('uc_catalog_category_columns', 3), 'Subcategories will be displayed in @count column.', 'Subcategories will be displayed in @count columns.'), ), ); $sections[] = array( 'edit' => 'admin/store/settings/catalog/edit/grid', 'title' => t('Products grid settings'), 'items' => array( variable_get('uc_catalog_grid_display', false) ? t('The catalog will be displayed on a grid.') : t('The catalog will be displayed on a table list.'), format_plural(variable_get('uc_catalog_grid_display_width', 3), 'The grid will be displayed in @count column.', 'The grid will be displayed in @count columns.'), variable_get('uc_catalog_grid_display_title', true) ? t('Every cell on the grid will display the Product Title.') : t('Cells on the grid will not display Product Titles.'), variable_get('uc_catalog_grid_display_model', true) ? t('Every cell on the grid will display the Product SKU.') : t('Cells on the grid will not display Product SKU.'), variable_get('uc_catalog_grid_display_sell_price', true) ? t('Every cell on the grid will display the Product Selling Price.') : t('Cells on the grid will not display Product Selling Prices.'), variable_get('uc_catalog_grid_display_add_to_cart', true) ? t('Every cell on the grid will display the Add to Cart button.') : t('Cells on the grid will not display Add to Cart buttons.'), variable_get('uc_catalog_grid_display_attributes', true) ? t('Every cell on the grid will display Product Attibutes.') : t('Cells on the grid will not display Product Attibutes.'), ), ); $sections[] = array( 'edit' => 'admin/store/settings/catalog/edit/blocks', 'title' => t('Catalog block settings'), 'items' => array( variable_get('uc_catalog_block_nodecount', true) ? t('The number of nodes in a category will be shown in the catalog block.') : t('The number of nodes in a category will not be shown in the catalog block.'), variable_get('uc_catalog_show_subcategories', true) ? t('Subcategories with no products to display will be shown on category pages.') : t('Subcategories with no products to display will not be shown on category pages.'), variable_get('uc_catalog_expand_categories', false) ? t('Categories in the catalog block will always be expanded.') : t('Categories in the catalog block will be expanded only when selected.'), ), ); $output = theme('uc_settings_overview', $sections); return $output; } /** * Determines if the "Product Catalog" vocabulary has been set up. * * @see uc_catalog_admin_form */ function uc_catalog_admin_settings() { $output = ''; $vid = variable_get('uc_catalog_vid', null); if ($vid) { $catalog = taxonomy_get_vocabulary($vid); $output .= t('Vocabulary %name is set as the product catalog. ', array('%name' => $catalog->name)); //$output .= l(t('Build a term hierarchy for products there.'), 'admin/content/taxonomy/'. $vid .'/add/term'); //drupal_set_message($output); $output .= l(t('View the catalog here.'), 'admin/content/taxonomy/'. $vid); } $output .= drupal_get_form('uc_catalog_admin_form'); return $output; } /** * Determines if the "Product Catalog" vocabulary has been set up. * * @see uc_catalog_admin_form */ function uc_catalog_grid_admin_settings() { $output = ''; $output .= drupal_get_form('uc_catalog_grid_admin_form'); return $output; } /** * Determines if the "Product Catalog" vocabulary has been set up. * * @see uc_catalog_admin_form */ function uc_catalog_blocks_admin_settings() { $output = ''; $output .= drupal_get_form('uc_catalog_blocks_admin_form'); return $output; } /** * Form to change the category of many nodes at once. * * @ingroup forms * @see uc_catalog_set_category_form_submit */ function uc_catalog_set_category_form() { drupal_add_css(drupal_get_path('module', 'uc_catalog') .'/uc_catalog.css'); drupal_add_css(drupal_get_path('module', 'uc_product') .'/uc_product.css'); $settings = array( 'div' => '#category-selector', 'vid' => variable_get('uc_catalog_vid', 0), 'filter' => implode(',', module_invoke_all('product_types')), 'search' => 'true', 'nids' => 'true', 'nodesg' => 'product', 'nodepl' => 'products', 'multi' => 'true', 'close' => 'false', 'select' => 'buffer_products("'. file_create_url('') .'")', ); $form['selector'] = array('#type' => 'markup', '#value' => ubrowser($settings, 'category-selector'), ); $form['buffer'] = uc_product_buffer_form(func_get_args()); $form['buffer']['#prefix'] = '
'; if (variable_get('uc_catalog_grid_display_title', TRUE)) { $product_table .= ''. $titlelink .''; } if (variable_get('uc_catalog_grid_display_model', TRUE)) { $product_table .= ''. $product->model .''; } $product_table .= ''. $imagelink .''; if (variable_get('uc_catalog_grid_display_sell_price', TRUE)) { $product_table .= ''. uc_currency_format($product->sell_price) .''; } if (variable_get('uc_catalog_grid_display_add_to_cart', TRUE)) { if (variable_get('uc_catalog_grid_display_attributes', TRUE)) { $product_table .= theme('uc_product_add_to_cart', $product); } else { $product_table .= drupal_get_form('uc_catalog_buy_it_now_form_'. $product->nid, $product); } } $product_table .= ' | '; $count++; } $product_table .= "
'. print_r($breadcrumbs, true) .''; return $breadcrumbs; } else { return null; } } /** * Display links to all products that have not been categorized. */ function uc_catalog_orphaned_products() { $output = '
'. t('Orphaned products are products that you have created but not yet assigned to a category in your product catalog. All such products will appear as links below that you can follow to edit the product listings to assign them to categories.') .'
'; $query = "SELECT DISTINCT n.nid, n.title FROM {node} AS n LEFT JOIN {term_node} AS tn ON n.nid = tn.nid LEFT JOIN {vocabulary_node_types} AS vnt ON n.type = vnt.type WHERE n.type != 'image' AND tn.tid IS NULL AND vnt.vid = %d"; $vid = variable_get('uc_catalog_vid', 0); $result = db_query($query, $vid); $rows = array(); while ($node = db_fetch_object($result)) { $rows[] = l($node->title, 'node/'. $node->nid .'/edit', array(), 'destination=admin/store/products/orphans'); } if (count($rows) > 0) { $output .= theme('item_list', $rows); } else { $output .= ''. t('All products are currently listed in the catalog.') .'
'; } return $output; } /** * Emulates Drupal's menu system, but based soley on the structure of "Product Catalog". * * @param $branch * A treeNode object. Determines if the URL points to itself, * or possibly one of it's children, if present. * * If the URL points to itself or one of its products, it displays its name, and * expands to show its children, otherwise displays a link and a count of the products in it. * If the URL points to one of it's children, it still displays a link and product count, * but must still be expanded. * Otherwise, it is collapsed and a link. * @return * An array whose first element is true if the treeNode is in hierarchy of the URL path. * The second element is the HTML of the list item of itself and it's children. */ function _uc_catalog_navigation($branch) { static $terms; static $breadcrumb; static $types; if (empty($types)) { $types = module_invoke_all('product_types'); } $branch_path = uc_catalog_path($branch); if (!isset($breadcrumb)) { $breadcrumb = drupal_get_breadcrumb(); } $vid = variable_get('uc_catalog_vid', 0); if ($_GET['q'] == $branch_path) { // The URL points to this term. $here = true; } else { $here = false; } if (!isset($terms)) { $terms = taxonomy_node_get_terms_by_vocabulary(arg(1), $vid); } // Determine whether to expand menu item. if ((arg(0) == 'node' && array_key_exists($branch->tid, $terms))) { $inpath = false; foreach ($breadcrumb as $link) { if (strpos($link, drupal_get_path_alias($branch_path)) !== false) { $inpath = true; } } } else { $inpath = $here; } $num = 0; foreach ($types as $type) { $num += taxonomy_term_count_nodes($branch->tid, $type); } // Checks to see if node counts are desired in navigation $num_text = ''; if (variable_get('uc_catalog_block_nodecount',TRUE)) { $num_text = ' ('. $num .')'; } if (!$num) { // No nodes in category or descendants. Not in path and display nothing. return array(false, ''); } $expand = variable_get('uc_catalog_expand_categories', false); $link = l($branch->name . $num_text, $branch_path); $active_link = l($branch->name .$num_text, $branch_path, array('class' => 'active')); if ($expand || count($branch->children)) { $lis = array(); foreach ($branch->children as $twig) { // Expand if children are in the menu path. Capture their output. list($child_in_path, $lis[]) = _uc_catalog_navigation($twig); if ($child_in_path) { $inpath = $child_in_path; } } } $output = theme("uc_catalog_item", $here, $active_link, $lis, $expand, $inpath, $link, count($branch->children)); // Tell parent category your status, and pass on output. return array($inpath, $output); } /** * Display a formatted link in the catalog block. * * @ingroup themeable * @see theme_uc_catalog_block_start * @see theme_uc_catalog_block_end */ function theme_uc_catalog_item($here, $active_link = '', $lis, $expand, $inpath, $link, $count_children ) { $output=''; if ($expand || $count_children) { if ($here) { $output = '