power_menu.module in Power Menu 6
Same filename and directory in other branches
This module provides some additional menu features. The features are not actually new, but are part of other modules. it's though very cumbersome to creating a new menu item, because one has to go to all the different places to configure these settings
File
power_menu.moduleView source
<?php
/**
* @file
* This module provides some additional menu features. The features are not actually new, but are part of other modules.
* it's though very cumbersome to creating a new menu item, because one has to go to all the different places to configure
* these settings
*/
/**
* implementation of hook_menu().
*/
function power_menu_menu() {
$items['admin/settings/power_menu'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array(
'power_menu_admin_form',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'power_menu.admin.inc',
'title' => 'Power Menu settings',
);
return $items;
}
/**
* implementation of hook_form_ID_alter().
*
* We are going to alter the form for editing a menu item and are going to add
* some additional fields:
*
* alias: allows us to automatically add an alias for a menu item.
*
* taxonomy_create: If we have connected the navigation with a taxonomy vocab
* we can create new taxonomy terms from the menu
*
* taxonomy_link: or just connect menu items with a taxonomy term, which is needed
* to ensure that the menu item can be set to active at the right place.
*
* nodetype: also we can choose to connect a menu item with a nodetype which is needed
* to ensure that the mneu item can bet set to active when a certain node type is
* being displayed.
*
* @param array $form
* @param array $form_state
*/
function power_menu_form_menu_edit_item_alter(&$form, &$form_state) {
module_load_include('inc', 'power_menu', 'power_menu.forms');
_power_menu_form_alter($form, $form_state);
}
/**
* implementation of hook_form_ID_alter().
*
* we are going to alter the form so that a user can set default properties
* default properties are used incase no properties are found on menu items
* @param $form
* @param $form_state
*/
function power_menu_form_menu_overview_form_alter(&$form, &$form_state) {
module_load_include('inc', 'power_menu', 'power_menu.forms');
_power_menu_form_overview_alter($form, $form_state);
}
/**
* Callback function when menu_edit_item form is being submitted
* @param array $form
* @param array $form_state
*/
function power_menu_form_menu_edit_item_submit($form, &$form_state) {
module_load_include('inc', 'power_menu', 'power_menu.forms');
_power_menu_form_menu_edit_item_submit($form, $form_state);
}
/**
* It's possible for the user to write a path like news/[tid]
* [tid] is like a token, that will be replaced by the either newly created term id ($tid)
* or the linked term id.
*
* @param int $tid
* @param int $mlid
* @param String $link_path
*/
function _power_menu_replace_tid_in_path($tid, $mlid, $link_path) {
$ar = array(
'mlid' => $mlid,
'link_path' => str_replace("[tid]", $tid, $link_path),
);
drupal_write_record('menu_links', $ar, array(
'mlid',
));
}
/**
* implementation of hook_nodeapi().
*
* @param stdClass $node
* @param string $op
* @param $a3
* @param boolean $page
*/
function power_menu_nodeapi(&$node, $op, $a3 = NULL, $page = FALSE) {
if ($op == 'view' && $page == TRUE) {
$item = power_menu_node_location($node);
if ($item) {
menu_set_item(NULL, $item);
$breadcrumbs = power_menu_get_breadcrumbs();
if (variable_get('power_menu_breadcrumb_title', FALSE)) {
$breadcrumbs[] = $node->title;
}
drupal_set_breadcrumb($breadcrumbs);
}
}
}
/**
* implementation of hook_ctools_render_alter().
*
* When we use CTools Pagemanager, hook_nodeapi (view) is not being called, because ctools alters the
* hook_menu and redirects the page callback to it's own function in node_view.inc Well, power_menu
* never knows that a node is actually being displayed -> so we alter the ctools_render function and
* start the normal power_menu_nodeapi procedure
*
* @param array $info
* @param boolean $page
* @param array $args
* @param array $contexts
* @param array $task
* @param unknown_type $subtask
*/
function power_menu_ctools_render_alter($info, $page, $args, $contexts, $task, $subtask) {
if (!empty($task['admin path']) && $task['admin path'] == 'node/%node' && $page) {
power_menu_nodeapi($contexts['argument_nid_1']->data, 'view', NULL, $page);
}
}
/**
* implementation of hook_link().
*
* here we are going to invoke hook_power_menu_href
* a possible implementation of it, could look as followed:
*
* function rapsli_power_menu_href($menu_item) {
* $ar_active = array('my_path' => 'my_path/*');
* foreach ($ar_active as $key => $pattern) {
* if (drupal_match_path($menu_item['href'], $pattern)) {
* return $key;
* }
* }
* }
*
*/
function power_menu_link($type) {
$item = menu_get_item();
$result = module_invoke_all('power_menu_href', $item);
$href = array_pop($result);
if (!empty($href)) {
$item['href'] = $href;
menu_set_item(NULL, $item);
$breadcrumbs = power_menu_get_breadcrumbs();
if (variable_get('power_menu_breadcrumb_title', FALSE)) {
$breadcrumbs[] = $node->title;
}
drupal_set_breadcrumb($breadcrumbs);
}
}
/**
* We are trying to figure out which of the blocks is currently active. We need this incase we display multiple
* menu blocks on the page, that are linked to the same term id, but have a different path. For example:
*
* Menu Block 1
* - Item 1 -> neuigkeiten/1 (and is linked to tid 1)
* - Item 2 -> neuigkeiten/2 (and is linked to tid 2)
*
* Menu Block 2
* - Ding 1 -> news/1 (and is linked to tid 1)
* - Ding 2 -> news/2 (and is linked to tid 2)
*
* If we are now looking at node/4 (which has tid 2) we go into our power_menu table to see which path we have to
* set active, but there are two paths with a relation to tid 2. We don't know which to take, that's why we have
* to figure out, which menu-block is currently active on the page we are looking at.
* If both are active... well, screw you. Only one is going to be active.
*/
function _power_menu_get_active_menu_block() {
while ($block = db_fetch_object($result)) {
// Match path if necessary
if ($block->pages) {
if ($block->visibility < 2) {
$path = drupal_get_path_alias($_GET['q']);
// Compare with the internal and path alias (if any).
$page_match = drupal_match_path($path, $block->pages);
if ($path != $_GET['q']) {
$page_match = $page_match || drupal_match_path($_GET['q'], $block->pages);
}
// When $block->visibility has a value of 0, the block is displayed on
// all pages except those listed in $block->pages. When set to 1, it
// is displayed only on those pages listed in $block->pages.
$page_match = !($block->visibility xor $page_match);
}
else {
$page_match = drupal_eval($block->pages);
}
}
else {
$page_match = TRUE;
}
}
}
/**
* Return all menus that are used for power menu
*/
function power_menu_get_pm_menus() {
return variable_get('power_menu_menu', array());
}
function power_menu_get_navigation_taxonomy() {
return variable_get('power_menu_taxonomy_navigation', '');
}
/**
* Get the menu which is defined as the power menu
*/
function power_menu_get_menu() {
global $user, $language;
$menus = array_filter(variable_get('power_menu_menu', array()));
if (empty($menus)) {
drupal_set_message(t("You have not chosen any power menu. Please visit the power menu settings"));
return NULL;
}
$rids = array_keys($user->roles);
$current_theme = variable_get('theme_default', 'none');
$args[] = $current_theme;
$args = array_merge($args, $menus);
$args = array_merge($args, $rids);
$result = db_query("SELECT b.* FROM {blocks} as b LEFT JOIN {blocks_roles} AS r ON b.delta = r.delta\n WHERE b.module='menu'\n AND theme='%s' AND b.delta IN (" . db_placeholders($menus, 'varchar') . ")\n AND (r.rid IN (" . db_placeholders($rids, 'int') . ") OR r.rid IS NULL) ", $args);
while ($block = db_fetch_object($result)) {
if (module_exists('i18nblocks')) {
$i18n_block = i18nblocks_load($block->module, $block->delta);
if ($i18n_block->language != $language->language && $i18n_block->language != '') {
continue;
}
}
// Match path if necessary
if ($block->pages) {
if ($block->visibility < 2) {
$path = drupal_get_path_alias($_GET['q']);
// Compare with the internal and path alias (if any).
$page_match = drupal_match_path($path, $block->pages);
if ($path != $_GET['q']) {
$page_match = $page_match || drupal_match_path($_GET['q'], $block->pages);
}
// When $block->visibility has a value of 0, the block is displayed on
// all pages except those listed in $block->pages. When set to 1, it
// is displayed only on those pages listed in $block->pages.
$page_match = !($block->visibility xor $page_match);
if ($page_match) {
return $block->delta;
}
}
else {
$page_match = drupal_eval($block->pages);
if ($page_match) {
return $block->delta;
}
}
}
else {
return $block->delta;
}
}
}
/**
* Determine the menu location of a node.
*
* Inspired by _menu_get_active_trail().
*/
function power_menu_node_location($node) {
// This should only fire if the menu isn't already active.
$item = menu_get_item();
$current_power_menu = power_menu_get_menu();
// incase the node is directly somewhere in the navigation we don't need all the checking
// and just use the core handling to decide which menu item to mark active
$mlid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE menu_name='%s' AND link_path='%s'", array(
$current_power_menu,
"node/{$node->nid}",
)));
if ($mlid > 0) {
return NULL;
}
// check if this nodetype is assigned to some menu path
if (($href = db_result(db_query("SELECT path FROM {power_menu} WHERE nodetype='%s' AND menu_name = '%s'", array(
$node->type,
$current_power_menu,
)))) != '') {
$item['href'] = $href;
return $item;
}
// we are going to check if there are certain taxonomy terms that should active a menu item
$ar_tid = array();
if (!empty($node->taxonomy)) {
$href = _power_menu_get_node_location_taxonomy($node, $current_power_menu);
if ($href) {
$item['href'] = $href;
}
return $item;
}
return NULL;
}
/**
*
* @param $node
* @param $current_menu
*/
function _power_menu_get_node_location_taxonomy($node, $current_power_menu) {
// We are going to reorder the term tree so that we know if a given term
// is a leaf or not.
if ($cache = cache_get('power_menu_taxonomy') && !empty($cache->data)) {
$leaf_tree = $cache->data;
}
else {
$tree = taxonomy_get_tree(variable_get('power_menu_taxonomy_navigation', ''));
$leaf_tree = array();
foreach ($tree as $el) {
$has_parent = FALSE;
for ($i = 1; $i < count($tree); $i++) {
if (in_array($el->tid, $tree[$i]->parents)) {
$has_parent = TRUE;
break;
}
}
if ($has_parent) {
$leaf_tree[$el->tid] = FALSE;
}
else {
$leaf_tree[$el->tid] = TRUE;
}
}
cache_set('power_menu_taxonomy', $leaf_tree, 'cache', time() + 60 * 60);
}
$counter = 0;
$tid = 0;
foreach ($node->taxonomy as $taxo) {
if (!is_array($taxo)) {
//we have all terms in a flat structure
if (!isset($taxo->vid)) {
//incase we don't have the whole term structure
$taxo = taxonomy_get_term($taxo);
}
if ($taxo->vid == variable_get('power_menu_taxonomy_navigation', '')) {
if ($leaf_tree[$taxo->tid] || $counter == 0) {
//incase a node is not in the leave
$tid = $taxo->tid;
$counter++;
}
}
}
elseif (is_array($node->taxonomy[power_menu_get_navigation_taxonomy()])) {
// our terms are grouped by vid and have a different structure
foreach ($node->taxonomy[power_menu_get_navigation_taxonomy()] as $tid) {
if ($leaf_tree[$taxo->tid] || $counter == 0) {
//incase a node is not in the leave
$tid = $taxo->tid;
$counter++;
}
}
}
}
if ($tid == 0) {
return NULL;
}
return db_result(db_query("SELECT path FROM {power_menu} WHERE tid=%d AND menu_name='%s'", array(
$tid,
$current_power_menu,
)));
}
/**
* Set Breadcrumbs based on active menu trail.
* I borrowed this function from the menutrails module
*/
function power_menu_get_breadcrumbs() {
$item = menu_get_item();
// Give first priority to the selected menu.
$menu = power_menu_get_menu();
if (!$menu) {
$menu = db_result(db_query("SELECT menu_name FROM {menu_links} WHERE link_path = '%s' AND module = 'menu'", $item['href']));
}
$tree = menu_tree_page_data($menu);
$crumbs = array(
l(t('Home'), '<front>'),
);
_power_menu_recurse_crumbs($tree, $item, $crumbs);
return $crumbs;
}
/**
* I borowed this function from the menutrails menu. Thanks a lot
* @param array $tree
* @param array $item
* @param array $crumbs
* @param array $above
*/
function _power_menu_recurse_crumbs($tree, $item, &$crumbs, $above = array()) {
foreach ($tree as $menu_item) {
if (!$menu_item['link']['in_active_trail']) {
continue;
}
if ($menu_item['link']['link_path'] == $item['href']) {
foreach ($above as $trail_item) {
$crumbs[] = l($trail_item['link']['link_title'], $trail_item['link']['link_path']);
}
$crumbs[] = l($menu_item['link']['link_title'], $menu_item['link']['link_path']);
break;
}
if (is_array($menu_item['below'])) {
_power_menu_recurse_crumbs($menu_item['below'], $item, $crumbs, array_merge($above, array(
$menu_item,
)));
}
}
}
/**
* Return a themed set of links.
*
* The important difference is that we use the in_active_trail bit here to set
* an "active" CSS class, which is what most themes (e.g. garland) use to
* denote an active/open menu item. You should alter/override this as your
* design needs dictate.
*
* @param $links
* A keyed array of links to be themed.
* @param $attributes
* A keyed array of attributes
* @return
* A string containing an unordered list of links.
*/
function phptemplate_links($links, $attributes = array(
'class' => 'links',
)) {
global $language;
$output = '';
if (count($links) > 0) {
$output = '<ul' . drupal_attributes($attributes) . '>';
//dsm($links);
$num_links = count($links);
$i = 1;
foreach ($links as $key => $link) {
$class = $key;
// Add first, last and active classes to the list of links to help out themers.
if ($i == 1) {
$class .= ' first';
}
if ($i == $num_links) {
$class .= ' last';
}
if (isset($link['href']) && ($link['href'] == $_GET['q'] || $link['href'] == '<front>' && drupal_is_front_page()) && (empty($link['language']) || $link['language']->language == $language->language)) {
$class .= ' active';
}
$a = '';
if (isset($link['href'])) {
// Add active class for containing <li> and <a> if 'active-trail' is set
// on the link itself.
if (isset($link['attributes']['class']) && strpos($link['attributes']['class'], 'active-trail') !== FALSE && strpos($class, 'active') === FALSE) {
$class .= ' active';
$link['attributes']['class'] .= ' active';
}
// Pass in $link as $options, they share the same keys.
$a = l($link['title'], $link['href'], $link);
}
elseif (!empty($link['title'])) {
// Some links are actually not links, but we wrap these in <span> for adding title and class attributes
if (empty($link['html'])) {
$link['title'] = check_plain($link['title']);
}
$span_attributes = '';
if (isset($link['attributes'])) {
$span_attributes = drupal_attributes($link['attributes']);
}
$a = '<span' . $span_attributes . '>' . $link['title'] . '</span>';
}
$i++;
$output .= '<li' . drupal_attributes(array(
'class' => $class,
)) . '>';
$output .= $a;
$output .= "</li>\n";
}
$output .= '</ul>';
}
return $output;
}
/**
* Implementation of hook_form_ID_alter().
*
* When deleting an menu item we have to clean up the power_menu stuff
* @param array $form
* @param array $form_state
*/
function power_menu_form_menu_item_delete_form_alter(&$form, $form_state) {
$form['#submit'][] = 'power_menu_delete_menu_item_callback';
}
/**
* When deleting a menu item we have to make sure we also clean out our table
* @param array $form
* @param array $form_state
*/
function power_menu_delete_menu_item_callback($form, $form_state) {
db_query("DELETE FROM {power_menu} WHERE mlid = %d", $form['#item']['mlid']);
}
/**
* Implementation of hook_taxonomy().
*
* @param string $op
* @param string $type
* @param array $array
*/
function power_menu_taxonomy($op, $type, $array = NULL) {
if ($op == 'delete' && $type == 'term') {
db_query("DELETE FROM {power_menu} WHERE tid = %d", $array['tid']);
}
}
/**
* get a term id from a given mlid
* this can be used to find out if a menu item is connected to a taxonomy term
* @param array $mlid
*/
function power_menu_get_tids($mlid) {
$result = db_query("SELECT amt.tid,td.vid,td.name, amt.nodetype FROM {power_menu} amt LEFT JOIN {term_data} td ON amt.tid = td.tid\n WHERE mlid=%d", $mlid);
while ($row = db_fetch_object($result)) {
$ar[] = $row;
}
return $ar;
}
/**
* This is a rewrite of taxonomy_get_term_by_name but it also uses the vocab id (vid)
* @param string $name
* @param int $vid
*/
function power_menu_get_term_by_name_vocab($name, $vid) {
$db_result = db_query(db_rewrite_sql("SELECT t.tid, t.* FROM {term_data} t WHERE LOWER(t.name) = LOWER('%s') AND vid=%d", 't', 'tid'), array(
trim($name),
$vid,
));
$result = array();
while ($term = db_fetch_object($db_result)) {
$result[] = $term;
}
return $result;
}
function power_menu_get_menu_tree() {
$result = db_query("SELECT * FROM {menu_links} WHERE menu_name='%s'", power_menu_get_menu());
$tree = array();
while ($row = db_fetch_object($result)) {
$tree[] = $row;
}
return $tree;
}
function power_menu_get_mlid($href, $pms = '') {
if ($pms == '') {
$pms = power_menu_get_menu();
}
return db_fetch_object(db_query("SELECT * FROM {menu_links} WHERE link_path='%s' AND menu_name='%s'", $href, $pms));
}
/**
* Implementation of hook_token_values().
*
* @param $type
* @param $object
* @param $options
*/
function power_menu_token_values($type, $object = NULL, $options = array()) {
if ($type == 'node') {
$node = $object;
$pms = power_menu_get_pm_menus();
foreach (array_filter($pms) as $pm) {
$mlid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE menu_name='%s' AND link_path='%s'", array(
$pm,
"node/{$node->nid}",
)));
if ($mlid > 0) {
//we have a node that is in the menu
$href = db_result(db_query("select ml2.link_path FROM {menu_links} ml INNER JOIN {menu_links} ml2 ON ml.plid = ml2.mlid WHERE ml.mlid=%d", $mlid));
}
else {
if (($href = db_result(db_query("SELECT path FROM {power_menu} WHERE nodetype='%s' AND menu_name = '%s'", array(
$node->type,
$pm,
)))) != '') {
// a node type that belongs to a defined menu entry
}
else {
if (!empty($node->taxonomy)) {
// a node that belongs to the taxonomy
$href = _power_menu_get_node_location_taxonomy($node, $pm);
}
}
}
if (!module_exists('pm_external_url_aliases')) {
$tokens["power_menu_path_{$pm}-path"] = $href ? drupal_get_path_alias($href, $node->language) : 'content-default';
}
else {
if ($href) {
$path_alias = drupal_get_path_alias($href, $node->language);
if ($path_alias != $href) {
$tokens["power_menu_path_{$pm}-path"] = $path_alias;
}
else {
$path_alias = pm_external_url_aliases_get_alias($href);
if ($path_alias != $href) {
$tokens["power_menu_path_{$pm}-path"] = $path_alias;
}
else {
$tokens["power_menu_path_{$pm}-path"] = 'content-default';
}
}
}
else {
$tokens["power_menu_path_{$pm}-path"] = 'content-default';
}
}
}
return $tokens;
}
}
/**
* Implementation of hook_token_list().
*
* @param $type
*/
function power_menu_token_list($type = 'all') {
if ($type == 'node' || $type == 'all') {
$pms = power_menu_get_pm_menus();
foreach (array_filter($pms) as $pm) {
$tokens['node']["power_menu_path_{$pm}-path"] = t("Path based on the power menu: %power_menu", array(
'%power_menu' => $pm,
));
}
return $tokens;
}
}
/**
* Implementation of hook_preproces_page().
*
* loading properties for the page scope
* @param $vars
*/
function power_menu_preprocess_page(&$vars) {
$mlid = power_menu_get_mlid(check_plain($_GET['q']));
if (is_object($vars['node'])) {
$item = power_menu_node_location($vars['node']);
$mlid = power_menu_get_mlid($item['href']);
}
foreach (power_menu_get_all_property_definitions() as $item) {
if ($item['scope'] == 'page') {
include_once $item['path'] . '/' . $item['file'];
$ml = is_object($mlid) ? $mlid->mlid : $mlid;
$vars[$item['property_name']] = $item['property_load']($ml);
}
}
}
/**
* implementation of hook_block().
*
* @param $op
* @param $delta
* @param $edit
*/
function power_menu_block($op = 'list', $delta = 0, $edit = array()) {
$properties = power_menu_get_all_property_definitions();
$mlid = power_menu_get_mlid(check_plain($_GET['q']));
if (!$mlid && preg_match('|node/[0-9]*$|', $_GET['q'], $match)) {
$item = power_menu_node_location(node_load(arg(1)));
$mlid = power_menu_get_mlid($item['href']);
}
if ($op == 'list') {
foreach ($properties as $item) {
if ($item['scope'] == 'block') {
$blocks[$item['property_name']] = array(
'info' => 'Power Menu Block: ' . $item['property_name'],
'cache' => BLOCK_CACHE_PER_PAGE,
);
}
}
return $blocks;
}
else {
if ($op == 'view') {
include_once $properties[$delta]['path'] . '/' . $properties[$delta]['file'];
$block = array(
'content' => $properties[$delta]['property_load']($mlid),
'subject' => $properties[$delta]['title'],
);
return $block;
}
}
}
/*
* We don't want to be calling the hooks all the time, so we just get the from the cache
* cache is being flushed everytime a menu item is being saved
* @return $properties
*/
function power_menu_get_all_property_definitions() {
if ($cache = cache_get('power_menu_properties', 'cache')) {
$properties = $cache->data;
}
else {
$dir = dir(drupal_get_path('module', 'power_menu') . '/properties');
$properties = array();
while ($filename = $dir
->read()) {
$file = $dir->path . '/' . $filename;
if (filetype($file) == 'file') {
include_once $file;
$properties = array_merge($properties, module_invoke(str_replace(".inc", '', $filename), 'power_menu_properties'));
}
}
$dir
->close();
$properties = array_merge($properties, module_invoke_all('power_menu_properties'));
cache_set('power_menu_properties', $properties, 'cache');
}
return $properties;
}
Functions
Name![]() |
Description |
---|---|
phptemplate_links | Return a themed set of links. |
power_menu_block | implementation of hook_block(). |
power_menu_ctools_render_alter | implementation of hook_ctools_render_alter(). |
power_menu_delete_menu_item_callback | When deleting a menu item we have to make sure we also clean out our table |
power_menu_form_menu_edit_item_alter | implementation of hook_form_ID_alter(). |
power_menu_form_menu_edit_item_submit | Callback function when menu_edit_item form is being submitted |
power_menu_form_menu_item_delete_form_alter | Implementation of hook_form_ID_alter(). |
power_menu_form_menu_overview_form_alter | implementation of hook_form_ID_alter(). |
power_menu_get_all_property_definitions | |
power_menu_get_breadcrumbs | Set Breadcrumbs based on active menu trail. I borrowed this function from the menutrails module |
power_menu_get_menu | Get the menu which is defined as the power menu |
power_menu_get_menu_tree | |
power_menu_get_mlid | |
power_menu_get_navigation_taxonomy | |
power_menu_get_pm_menus | Return all menus that are used for power menu |
power_menu_get_term_by_name_vocab | This is a rewrite of taxonomy_get_term_by_name but it also uses the vocab id (vid) |
power_menu_get_tids | get a term id from a given mlid this can be used to find out if a menu item is connected to a taxonomy term |
power_menu_link | implementation of hook_link(). |
power_menu_menu | implementation of hook_menu(). |
power_menu_nodeapi | implementation of hook_nodeapi(). |
power_menu_node_location | Determine the menu location of a node. |
power_menu_preprocess_page | Implementation of hook_preproces_page(). |
power_menu_taxonomy | Implementation of hook_taxonomy(). |
power_menu_token_list | Implementation of hook_token_list(). |
power_menu_token_values | Implementation of hook_token_values(). |
_power_menu_get_active_menu_block | We are trying to figure out which of the blocks is currently active. We need this incase we display multiple menu blocks on the page, that are linked to the same term id, but have a different path. For example: |
_power_menu_get_node_location_taxonomy | |
_power_menu_recurse_crumbs | I borowed this function from the menutrails menu. Thanks a lot |
_power_menu_replace_tid_in_path | It's possible for the user to write a path like news/[tid] [tid] is like a token, that will be replaced by the either newly created term id ($tid) or the linked term id. |