Suppose I have parent pages A1 and B1. A1 has child pages A1.1, A1.2,A1.3 and B1 has child pages B1.1, B1.2.
When I am on page A1.1 I shall be able to display A1.2 and A1.3.
Same for A1.2, I shall be able to see A1.1 and A1.3.
If I am on page B1.1, I shall see B1.2 and vice versa.
Note: Every page has an image and a title. I want to get a solution using views.
This thread may be linked to this link if we need the child pages: How to list all child pages of current parent page in drupal 7?
Add a contextual filter nid on both pages, in default select content id from url, then down below in advance section check exclude option.
I managed to do it by creating a view with the following php code in contextual filter
$sibbling = array();
$current = db_query("select menu_name, mlid from {menu_links} where link_path = :node", array(':node' => $_GET['q']));
$current_info = array();
foreach ($current as $value) {
$current_info[] = $value;
}
if($current_info) {
$result = db_query("select mlid, plid, link_path, link_title from {menu_links} where link_path != :node and plid = ( select plid FROM {menu_links} WHERE link_path =:node)", array(':node' => $_GET['q']));
foreach ($result as $row) {
$sibbling[] = $row;
}
}
$nids = array();
foreach ($sibbling as $value){
if( substr( $value->link_path, 0, 5 ) == 'node/' ){
$nids[] = substr( $value->link_path, 5 );
}
}
return implode('+',$nids);
And finally in the plus options we got to check "Allow multiple values "
Save and its done ;-)
Related
I need to conditionally show information in the wordpress admin based on what locations a menu has been added to. So to achieve this I must be able to get all locations assigned to a nav menu but I am really struggling to find out how.
When a menu is created it creates and entry for that menu in wp_terms and a taxonomy entry of nav_menu associated to this term in wp_term_taxonomy. When an item is created on that menu it creates a post of type nav_menu_item. It also creates and entry in wp_term_relationships linking it to the correct nav_menu.
Where does it save the menu location?
I have checked wp_postmeta, wp_termmeta and wp_options but I cannot see it. I cannot figure out any way to achieve my goal.
get_nav_menu_locations() sets the array key to the ID of the menu. This code worked for me:
$locations = get_registered_nav_menus();
$menu_locations = get_nav_menu_locations();
$nav_menu_selected_id = isset( $_REQUEST['menu'] ) ? (int) $_REQUEST['menu'] : 0;
$selected_menus = array();
foreach($locations as $location => $description){
$checked = isset( $menu_locations[ $location ] ) && $menu_locations[ $location ] === $nav_menu_selected_id;
if($checked) $selected_menus[] = $location;
}
Suppose I have parent pages A1 and B1. A1 has child pages A1.1, A1.2,A1.3 and B1 has child pages B1.1, B1.2. I want to list all the respective child pages on A1 and B1. In every child page I have an image and a title. These 2 information needs to be listed in the form of a teaser on the parent page. I need help in doing this whether by coding or by using views, I don't mind as far as I get the proper results. Thank you
You can do this is views by creating a view displaying the fields you require or a teaser. Then add a "Content Nid" contextual filter, in the configeration for this filter under "WHEN THE FILTER VALUE IS NOT AVAILABLE" select "Provide default value" and then "PHP Code" then the code I use is as follows
$children = array();
$current = db_query("select menu_name, mlid from {menu_links} where link_path = :node", array(':node' => $_GET['q']));
$current_info = array();
foreach ($current as $value) {
$current_info[] = $value;
}
if($current_info) {
$result = db_query("select mlid, plid, link_path, link_title from {menu_links} where menu_name=:menu and plid=:mlid and hidden=0 order by weight, link_title", array(':menu' => $current_info[0]->menu_name, ':mlid' => $current_info[0]->mlid));
foreach ($result as $row) {
$children[] = $row;
}
}
$nids = array();
foreach ($children as $value){
if( substr( $value->link_path, 0, 5 ) == 'node/' ){
$nids[] = substr( $value->link_path, 5 );
}
}
return implode('+',$nids);
The last thing to do, under "more" at the bottom of the page sellect "Allow multiple values"
I'm using menu_tree_all_data() to get whole menu structure and then I'm "manually" crawling menu tree.
Also just after reading the tree, I'm calling menu_tree_add_active_path() which will add active trail indicator. It's part of menu block module so you'll have to install it and don't forget to add dependencies for menu block in your module.
$tree = menu_tree_all_data($menu);
menu_tree_add_active_path($tree);
I want to add current-menu-item class to the li if it is a single page.
I am trying to do this by using wp_nav_menu_objects hook with a custom function but don't know how to get the particular menu item and set a condition to assign the class to it.
Here is the code.
add_filter('wp_nav_menu_objects' , 'my_menu_class');
function my_menu_class($menu) {
//if it is a single post page of a particular post type (in this case 'property')
if( is_single() && is_post_type_archive( 'property' ) ) {
//get all the menu items
foreach($menu as $key => $item) {
// check if the menu item is "Commercial Property"
if($item == "Commercial Property") {
//assign the class to that menu item
$menu[$key]->classes[] = 'current-menu-item';
}
}
}
return $menu;
}
This code is just to represent the logic. Please suggest if what I need can be achieved with this method or there is a better approach to it.
Thanks.
In my WP theme, I wanted to remove all wordpess menu classes, add my own and on specific condition ( for example if the menu has an active class ) to add another class. Here s my code
function add_custom_classes($classes){
$newClasses[] = "navigation__item";
if( in_array('current_page_item', $classes) ){
array_push($newClasses, "navigation__item-active");
}
return $newClasses;
}
add_filter('nav_menu_css_class', 'add_custom_classes', 100, 1);
add_filter('nav_menu_item_id', 'add_custom_classes', 100, 1);
add_filter('page_css_class', 'add_custom_classes', 100, 1);
You can add your own conditions
is_single is actually looking for a single post. You need is_page
Wordpress already provides the class if it is a single page
current-post-ancestor
on any post detail page you can inspect the menu you will find that class so in other way you can utilize current-post-ancestor class for what you need to do
Hope it makes sense
I have solved it using the HTTP_REFERER to set conditions in the same function.
Don't feel it is the best way to achieve this but it sorts me out.
Here is the code if anyone else needs a reference.
function nav_menu_class($menu) {
//To dynamically get the directory path from the URL irrespective of the local or web server.
$ref = $_SERVER['HTTP_REFERER']; // prev page url.
$split_ref = pathinfo($ref); // splitting the url to seperate the directory (http://dev.calyxagency.com/horizoncapital/site-new/) from the file path.
$dir_path .= $split_ref[ "dirname" ]; // extracting the host + directory from the full path
$class = 'current-menu-item'; // class to be assigned.
foreach($menu as $key => $item) {
if( $menu[$key]-> ID == 101 ) { // check if the menu item matches this ID
if( $ref == $dir_path.'/properties-to-let/' || $ref == $dir_path.'/properties-for-sale/' || $ref == $dir_path.'/commercial-property/' ) {
$menu[$key]->classes[] = $class;
}
} elseif( $menu[$key]-> ID == 15 ) { // check if the menu item matches this ID
if( $ref == $dir_path.'/business-for-sale/' ) { // check if the single page has come from this page for assigning current class to only this menu item
$menu[$key]->classes[] = $class;
}
} elseif( $menu[$key]-> ID == 18 ) { // check if the menu item matches this ID
if( $ref == $dir_path.'/news/' ) { // check if the single page has come from this page for assigning current class to only this menu item
$menu[$key]->classes[] = $class;
}
}
}
return $menu;
}
add_filter('wp_nav_menu_objects' , 'nav_menu_class');
I'm building a Drupal site, and have added two custom menus to give two different groups of management links (some people will see one menu or the other, some will see both, and anonymous/low-level users will see neither).
The problem is, at the moment, all users can see the menus (but the menu items are not visible).
I'm trying to create a simple permissions module - and have created the administration forms which specify which menus are viewable by which role.
But I can't find a hook which lets me override the visibility of a particular menu - only the items.
So, how do I limit access to menu by role in Drupal now that I have a list of permissions in the database?
--
I have looked at Menu per Role and Menu Access. Unfortunately, these work at the item level and not on the menus directly.
Each menu is in a block, and blocks can be set to be visible for given user group (access level).
On drupal admin site: Structure/Blocks
Menu Per Role module?
http://drupal.org/project/menu_per_role
As long you use a block as a menu you can use the access by role for block setting, provided by core.
For menu listing this function work: menu_get_names();
But it hasn't any permission checks or hooks.
Where did you want to restrict menu list? if at node editing you can alter menu there via hook_form_alter.
It's not the most elegant solution, but you can do your access check in the theme.
I've come up with a solution - instead of using the auto-generated menu blocks for display, I've created a single block and put the following code in my module:
function amh_menu_block($op = 'list', $delta = 0, $edit = array())
{
if ($op == 'list') {
$blocks[0] = array(
'info' => t('AMH Menu block'),
'weight' => 0,
'status' => 1,
'region' => 'left',
);
return $blocks;
} elseif ($op == 'view') {
switch($delta) {
case 0:
$block = array(
'subject' => '',
'content' => _amh_menu_display(),
);
break;
}
return $block;
}
}
function _amh_menu_display()
{
global $user;
$content = '';
if ($user->uid != 0) {
$result = db_query('SELECT * FROM {amh_menu_permission} p LEFT JOIN {menu_custom} m ON p.menu_name = m.menu_name LEFT JOIN {users_roles} u ON p.rid = u.rid WHERE u.uid = %d OR p.rid = 2', $user->uid);
} else {
$result = db_query('SELECT * FROM {amh_menu_permission} p LEFT JOIN {menu_custom} m ON p.menu_name = m.menu_name WHERE p.rid = 1');
}
$menus = array();
while ($m = db_fetch_object($result)) {
$menu = menu_tree($m->menu_name);
if ($menu) {
$content .= "\r\n<h2>" . $m->title . "<h2>\r\n";
$content .= theme_menu_tree($menu);
}
}
return $content;
}
This seems to work fine.
The Menu Admin Per Menu module will allow you to restrict edit access to each menu by role. https://www.drupal.org/project/menu_admin_per_menu
Does anyone know how or can guide me in the right direction on how to add a body css class for the current node's taxonomy term? i.e. <body class="term-dogs"> where "dogs" is the taxonomy term name. It could also be just the term ID. Either way is fine I just need a solution. This will be for a Drupal 7 zen sub-theme
This answer took longer than I expected to figure out. The hard part was collecting the terms on the node, since All taxonomy functions relating to nodes have been removed or refactored. Ultimately, page 355 of Pro Drupal 7 Development saved the day with a snippet that does the job previously handled by taxonomy_node_get_terms.
Below is the code that worked for me (look for the part that says "MAGIC BEGINS HERE"). Assuming you're creating a sub-theme of Zen, you'll want to move this to your sub-theme's template.php file and rename it to YOURSUBTHEMENAME_preprocess_html:
/**
* Override or insert variables into the html template.
*
* #param $vars
* An array of variables to pass to the theme template.
* #param $hook
* The name of the template being rendered ("html" in this case.)
*/
function zen_preprocess_html(&$vars, $hook) {
// If the user is silly and enables Zen as the theme, add some styles.
if ($GLOBALS['theme'] == 'zen') {
include_once './' . drupal_get_path('theme', 'zen') . '/zen-internals/template.zen.inc';
_zen_preprocess_html($vars, $hook);
}
// Classes for body element. Allows advanced theming based on context
// (home page, node of certain type, etc.)
if (!$vars['is_front']) {
// Add unique class for each page.
$path = drupal_get_path_alias($_GET['q']);
// Add unique class for each website section.
list($section, ) = explode('/', $path, 2);
if (arg(0) == 'node') {
if (arg(1) == 'add') {
$section = 'node-add';
}
elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
$section = 'node-' . arg(2);
}
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
$vars['classes_array'][] = strtolower($result['#title']);
}
}
// MAGIC ENDS HERE
}
$vars['classes_array'][] = drupal_html_class('section-' . $section);
}
if (theme_get_setting('zen_wireframes')) {
$vars['classes_array'][] = 'with-wireframes'; // Optionally add the wireframes style.
}
// Store the menu item since it has some useful information.
$vars['menu_item'] = menu_get_item();
switch ($vars['menu_item']['page_callback']) {
case 'views_page':
// Is this a Views page?
$vars['classes_array'][] = 'page-views';
break;
case 'page_manager_page_execute':
case 'page_manager_node_view':
case 'page_manager_contact_site':
// Is this a Panels page?
$vars['classes_array'][] = 'page-panels';
break;
}
}
I needed to know how to do this and Matt V's solution worked perfectly. I made a couple of additions to his work. I called drupal_html_class which replaces spaces and invalid characters. And I added in the term ID to allow you to target a term even if the name of the term changes.
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
// Call drupal_html_class to make safe for a css class (remove spaces, invalid characters)
$vars['classes_array'][] = "taxonomy-" . strtolower(drupal_html_class( $result['#title']) );
// Add taxonomy ID. This will allow targeting of the taxonomy class even if the title changes
$vars['classes_array'][] = "taxonomy-id-" . $result['#options']['entity']->tid ;
}
}
// MAGIC ENDS HERE
Not sure what you mean with that body tag, but the classes on the node are generated here:
http://api.drupal.org/api/drupal/modules--node--node.module/function/template_preprocess_node/7
You can add more by implementing yourmodule_preprocess_node($vars) and then add whatever you want to $vars['classes_array']