I have a menu item called "Inbox" on a menu called "dealer-menu". I want to change "Inbox" to "Inbox (1)" or "Inbox (2)" depending on the number of messages the user has in his inbox. How do I change the value ON THE FLY. I.e. on every page refresh?
I ended up solving it like this:
$dealerMenu = menu_navigation_links('menu-dealer-menu');
$menu = theme('links', $dealerMenu);
print str_replace("Inbox", "Inbox (".get_number_of_messages_in_inbox().")", $menu);
If you call hook_menu_link_alter then you can set $item['options']['alter'] = TRUE; on each menu item - you will need to edit the menu item for this hook to be called and the alter permission set to true.
Once this has been set then hook_translated_menu_link_alter will be called before each menu item is rendered allowing you to change the menu item title.
Example code would be:
function MY_MODULE_menu_link_alter(&$item) {
$item['options']['alter'] = TRUE;
}
function MY_MODULE_translated_menu_link_alter(&$item, $map) {
if($item['mlid']==89) {
$item['title'] .= ' ('.get_number_of_messages_in_inbox().')';
}
}
The only limitation of this is that hook_menu_link_alter will mark every link as alterable which is not necessarily desirable (adverse effect on performance) - some additional checks on the $item here would mean you are only marking them menu items you want as alterable.
Related
How I can create admin page, to edit single item from custom table WP_List_Table?
Data: Custom DB Table, on admin I have add menu item with method which build this table through WP_List_Table.
There I want to create 'manage' button, to manage single item from this table.
How can I do this?
Is there some action hook
or i have to just add second class
Or like menu item
I have try add like menu item, But how can I add it without adding to the menu? add_submenu_page with parent slug = null is it really clear WP solution?
For my situation good solution:
if ( array_key_exists( 'single', $_REQUEST ) ) {
//function to process single item
} else {
//Create an instance of our package class...
$withdraw = new Class_Table();
//Fetch, prepare, sort, and filter our data...
$withdraw->prepare_items();
}
I have 3 pages in my menu that basically link to the same page, but with a different contextual filter on them.
Is there any way to only set the correct "page" as the active page in my menu so the other links don't get the active menu item style?
These are the links:
xxx.ons-aanbod/% (contextual filter)
xxx.ons-aanbod/diversiteit (VOORGROEPEN)
xxx.ons-aanbod/architectuur (VOOR SCHOLEN)
I'm not sure but think you can hook menu links , like this :
function MODULENAME_menu_link_alter(&$item)
{
$path = current_path(); // get path of current page displayed
if($item['link_path']== $path) // or something like
{
// add class active
}
}
https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_menu_link_alter/7.x
https://api.drupal.org/api/drupal/includes%21path.inc/function/current_path/7.x
I do not want my clients to select a parent page from the drop down list, when creating a child page in Wordpres, so I would like to now if there is a way to create a link on the dashboard which links to "add new page" - but with a preselected parent page?
If this is not possible, then is there a way to change the default parent from "(no parent)" to a parent of my choice?
Put this script in your plugins folder and it'll give new pages a parent of whatever you set as $parent_id
<?php
function set_parent($content) {
/* >> Begin user-configurable variable >> */
$parent_id = '1'; // ID for parent page >> */
/* >> End user-configurable variable >> */
$pattern = "option value='{$parent_id }'";
$replace = "option value='{$parent_id }' selected=\"selected\"";
$content = str_replace($pattern, $replace, $content);
return $content;
}
if( strstr($_SERVER['REQUEST_URI'], 'wp-admin/post-new.php?post_type=page') ) {
ob_start('set_parent');
}
?>
That should do what you want. And I suppose you could add a dropdown option in somewhere to select parents if a set default parent isn't sufficient like in this example.
This is a tough question to answer sticking with core wordpress ideas. Would you normally have more than one parent page available?
Do you think that about a different way for your client to manage page structure would work?
Admin Column View Plugin is great and allows the user to use drag and drop to reorder pages - http://wordpress.org/plugins/admin-column-view/screenshots/
Hope this helps.
Can I hide the
Edit | View
tabs on top of each node ?
I've searched for this option in theme settings (both global and standard theme but I couldn't find it).
I still want to be able my customer to edit / administer content, so I cannot just remove the permission for it.
thanks
here is a very easy solution for you. (Drupal 7)
Open your page.tpl.php in your current template and search for the $tabs variable.
Remove the render code if you want to hide it completely.
If you want to display it only to administrators use this code
<?php if ($tabs and $is_admin): ?>
<div class="tabs">
<?php print render($tabs); ?>
</div>
The above code checks if the user is administrator. If it is it will render the tabs. If not it wont render them.
This really is a presentational thing, not a functionality thing, so it should be done at the theme level.
The problem with overriding theme_menu_local_tasks() is that you override/take a hatchet to the entire local task display, when you really just want to get in there with a scalpel to remove two specific local tasks. So, you need to get a little more specific.
theme_menu_local_tasks() gets the current page's local tasks and passes them to menu_local_tasks(). Here, two theme functions are used:
theme_menu_item_link(), which gets the link markup for the task
theme_menu_local_task(), which gets the <li> element for the task.
So, you can get rid of the View and Edit local tasks in a really robust way by overriding theme_menu_item_link() and theme_menu_local_task() to include your check for them:
function mytheme_menu_item_link($link) {
// Local tasks for view and edit nodes shouldn't be displayed.
if ($link['type'] & MENU_LOCAL_TASK && ($link['path'] === 'node/%/edit' || $link['path'] === 'node/%/view')) {
return '';
}
else {
if (empty($link['localized_options'])) {
$link['localized_options'] = array();
}
return l($link['title'], $link['href'], $link['localized_options']);
}
}
function mytheme_menu_local_task($link, $active = FALSE) {
// Don't return a <li> element if $link is empty
if ($link === '') {
return '';
}
else {
return '<li '. ($active ? 'class="active" ' : '') .'>'. $link ."</li>\n";
}
}
This way, you're relying on the menu router path, not modifying the menu router item, and achieving the result you want with minimal changes to core functionality or theming.
On the module side, you could do something that decouples the Edit's menu entry from the local tasks for the node:
function custom_menu_alter(&$items) {
$items['node/%node/edit']['type'] = MENU_CALLBACK;
}
The edit path is still there, but now it is not associated with the View tab. This includes the edit page itself--no View tab there.
there is a module for that: tab tamer allows to hide or disable tabs and rename them as well.
I use the following in template.php by theme (which is perhaps a little hacky, I feel I should be considering unsetting $tabs instead):
function THEME_NAME_menu_local_tasks() {
return '';
}
Or you could ommit:
if ($tabs) echo $tabs;
from your page.tpl.php...
View and Edit are functional features. They have a reason for being there.
The best way to "remove" them, is to "remove" that functionality alltogether. After all: why remove the interface of a piece of functionality, but not the functionality itself?
Besides, simply not printing the tabs, does not remove the url endpoints. In other words: if you don't print the edit tab, people can still access the edit page.
Again: best is to remove that functionality: The fact that you don't want the edit tab, sounds as if you don't want the edit functionality for certain users.
If so, then just remove that permission for that role. That is all. The tabs will be gone.
If, however, you simply wish to display these tabs differently, Drupal is your friends. As you may have noticed, they are called local tasks and not tabs. That is because the theme decides how to render them: The theme is the thing that decides to show them as tabs.
Simply override the theme_menu_local_tasks() to create your own HTML for the "local-tasks". And in your page-tpl, simply move the $tabs variable around to a place, where you want them.
But again: Don't try to change the behavior of the app, by removing interface-elements. That is not the right thing to do: you should change the behavior, in order to change the behavior :)
For all the people stumbling upon this question while looking for a D7 solution: As stated on https://drupal.stackexchange.com/a/77964/15055 it's hook_menu_local_tasks_alter()
/**
* Implements hook_menu_local_tasks_alter() to unset unwanted tabs
*/
function MYMODULE_menu_local_tasks_alter(&$data) {
foreach ($data['tabs'][0]['output'] as $key => $value) {
if ($value['#link']['path'] == 'node/%/view') {
unset($data['tabs'][0]['output'][$key]);
}
}
}
This is not the answer to the question of what the author asked. But somehow it might be useful for others user who facing the similar problem with me. Please let me know if this is not suitable to put in here.
I get the answer from #grayside and modified a bit to hide the view | edit tab from node based on the content type I want.
function MYMODULE_menu_alter(&$items) {
$items['node/%node/view']['access callback'] = 'MYMODULE_disable_node_view';
$items['node/%node/view']['access arguments'] = array(1);
}
function MYMODULE_disable_node_view($node){
if($node->type == 'product'){
return false;
}
}
product is the machine name of my content type, I don't want anywant to access it including root user.
The simplest solution to hide the tabs is to add this class in your theme css
.tabs{ display:none;}
Thanks for the last answer. But be aware of this detail: if you try it as-is it cannot work: literals should be just rounded with " or ', not both of them altogether. So it should be:
/**
* Implements hook_menu_local_tasks_alter() to unset unwanted tabs
*/
function MYMODULE_menu_local_tasks_alter(&$data) {
foreach ($data['tabs'][0]['output'] as $key => $value) {
if ($value['#link']['path'] == "node/%/view") {
unset($data['tabs'][0]['output'][$key]);
}
}
}
Once taken care of it, it works :)
D8 solution: If you want to hide all "local" tabs on certain pages, remember that "Tabs" is listed in the block library: find it in the "Content" region and exclude by content type, page URL or user role.
can I automatically add a menu item when I add a node to the page in Drupal?
In other words, can I associate a menu parent with a node content-type, and then automatically add the children if new nodes are added ?
thanks
You can do it with Rules on Drupal 7. This module: http://drupal.org/project/menu_rules adds some actions to rules. One of them is to create a menu item for a node. You select:
Event: Create a node | Update a node
Condition: Content type is "your content type"
Action: Update a menu item for node (there is a checkbox to create the menu item if it doesnt exist)
There's also the Menu Position module that allows to put content under specific menu entries, depending on their content type, their language and taxonomy. It also has a small API to add other criteria.
Yes.
I am sure there is a module do to something like that, but you could also create your own.
There are two ways you could go about it.
You could use hook_menu() to query for the items you want and return the correct menu structure. You would need to also make sure the menu cache is rebuilt on a node save using hook_nodeapi().
See henricks' comments below about why this is a bad idea
Alternitivly you could use hook_nodeapi() to add custom menu items with menu_link_save().
Edit
hook_menu should return an array of menu items, often these are pretty static however there is nothing wrong with these arrays being dynamically generated.
So you can query the node table to get a list of nodes you want, loop through these items and dynamically create an array which contains the correct menu items.
very roughly:
function example_menu() {
$result = db_query('select * from node where ...'); // put in your own select items and where clause
$menu = array();
while ($row = db_fetch_object($result)) {
$menu['my_path/' . $row->nid;] = array(
// See hook menu docs for what to put here.
);
}
return $menu;
}
You should take a look at the Auto Menu module - while the Drupal 6 version is still a dev release, it might cover your needs. If not, you can take it as an example of how to use menu_link_save() to create your own solution.
I would also go for a menu_link_save() call. Together with the Rules module, you can set up an action whenever a new node is saved, to create an appropriate menu item automatically.
You might want to have a look at the tutorial I wrote some time ago, which deals with programatically creating menu items using menu_link_save() and Rules: http://jan.tomka.name/blog/programmatically-creating-menu-items-drupal
Here is case where you can do this....
A node campaign creating menu item 'CAMPAIGN 001' when it is created. Using default_menu_link
Now another content type, 'Sub Campaign' creating a node, using campaign as EntityRef so its menu item should be under the Menu Item of campaign created earlier.
function mymodule_node_insert($node) {
if ($node->type == 'sub-campaign') {
if (isset($node->field_reference_campaign['und'][0]['target_id'])) {
$campaign_node_id = $node->field_photo_album_campaign['und'][0]['target_id'];
$campaign_loaded = node_load($campaign_node_id);
// Get menu link id for the campaign node.
$campaign_node_id_mlid = custom_node_mlid($campaign_node_id);
$campaign_loaded_title = strtolower(str_replace(' ', "-", $campaign_loaded->title));
$campaign_loaded_title_link_path = 'campaign/' . $campaign_loaded_title . '/photo-albums';
//I will query if it exist or not, if not then will create a sub menu item.
$link_exist = db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $campaign_loaded_title_link_path))->fetchField();
dsm($link_exist);
if (!$link_exist) {
// Create menu item under campaign.
custom_create_menu_item($campaign_loaded_title_link_path, 'photo-albums', $campaign_node_id_mlid);
//watchdog('glue_site - Menu Item', 'Link Created');
}
else {
//dsm('Link Exist.');
watchdog('glue_site - Menu Item', 'Link Already Exist');
}
}
}
if ($node->type == 'campaign') {
}
}
Then a custom function to create menu item
function custom_create_menu_item($campaign_loaded_title_link_path, $type, $plid) {
switch ($type) {
case 'photo-albums':
$item = array(
'link_path' => $campaign_loaded_title_link_path,
// If changing the title here, change it in template.php as well.
'link_title' => 'Sub Campaign',
'menu_name' => 'menu-campaign-menu', // Menu machine name, for example: main-menu
'weight' => 0,
'plid' => $plid, // Parent menu item, 0 if menu item is on top level
'module' => 'menu',
'router_path' => 'campaign/%/sub-campaign',
'customized' => '1',
);
menu_link_save($item);
menu_cache_clear_all();
watchdog('glue_site - Menu Item', 'Link Created');
break;
}
}
To get the mlid of parent node. Campaign node...
function custom_node_mlid($nid) {
// Require menu node module.
$arr = menu_node_get_links($nid);
$mlid = array_keys($arr);
return $mlid[0];
}
For this you need menu_node
This is a simple problem that unfortunately the Drupal community has decided it wants to make complicated. Forget about all the hacky solutions with rules and hooks. There are two modules, depending on whether you're on Drupal 6 or Drupal 7, that solve the problem very elegantly. I advise against actually creating menu entries. Instead the two modules below dynamically render the nodes in the menu, so that your menu editor doesn't get filled with thousands of nodes. Then, for example, if you decide you want all the blog posts to be moved from [Our Blog] to [About Us]->[News] it's just a mater of changing one setting. No updating thousands of nodes.
D6 Menu Trails
D7 Menu Position
It looks like there's a Drupal module that does this: Auto Menu. Some more details about this module (from its project page):
The Auto Menu module automatically generates menu entries on node creation/edition. Parent menu item can be specified on a per content type basis.
This module acts when the menu section of a node is left empty only. So, users can still organize menus manually. Moreover, default setting for content types is to not create menu items automatically.
Menu Views is an interesting module for Drupal 7 to automatically generate menu links. It allows you to use the power of Views to create menu links and can be used out-of-the-box in combination with modules such as Superfish and Nice Menus.
(PS: my reputation is not high enough to provide more than two links, therefore I have marked the other modules bold instead of providing hyperlinks)