List Pages on Admin Menu in WordPress - wordpress

I am trying to make my clients dashboard as simple as possible. Is there a way to do a wp_list_pages down the left side of the admin menu? Instead of clicking on Pages first.

Yes, it's a matter of using get_pages with add_submenu_page.
add_action('admin_menu', 'admin_pages_so_19817501' );
function admin_pages_so_19817501()
{
$pages = get_pages( array( 'parent' => 0 ) );
foreach( $pages as $p )
{
add_submenu_page(
'edit.php?post_type=page',
$p->post_title,
$p->post_title,
'edit_pages',
'/post.php?post='.$p->ID.'&action=edit',
null
);
}
}
You'll need some jQuery to manipulate the current CSS class from the submenu items.
See: Highlighting a Menu Item by Post Name.

Related

WordPress unlimited sidebars

Just wondering if someone could give me some advice on how to create unlimited sidebars for a WordPress theme.
So, basically I am looking into adding a meta box on posts and pages with a drop down list of all available sidebars, where the user can then select a specific sidebar for any post or page. This part I have figured out, however I would also like to add functionality here to allow users to create custom sidebars for any post or page. So, essentially the user could choose any sidebar for any post or page or create new sidebars for any post or page which then could be filled with widgets on the widgets page.
I half there, just not sure how to go about creating the functionality to create new sidebars.
There is a way to do it but it's a bit lengthy.
Create a customizer control to add multiple sidebars
The easiest way is to just take the custom control called Multi Input field from here. Also, be sure to add this custom control, and all the jQuery functionality that goes with it (in the .js file).
With that, add to your customizer file (or if you don't have a dedicated customizer file, to your functions.php file)
if(!function_exists('yourtheme_text_sanitization')){
function yourtheme_text_sanitization($input){
return wp_kses_post( force_balance_tags($input) );
}
}
/**
------------------------------------------------------------
SECTION: Sidebars
------------------------------------------------------------
**/
$wp_customize->add_section('section_sidebars', array(
'title' => esc_html__('Sidebars', 'yourtheme'),
'priority' => 0,
));
/**
Sidebars
**/
$wp_customize->add_setting('sidebars', array(
'default' => '',
'sanitize_callback' => 'yourtheme_text_sanitization',
));
$wp_customize->add_control(new Multi_Input_Custom_control($wp_customize, 'sidebars', array(
'label' => esc_html__( 'Sidebars', 'yourtheme' ),
'description' => esc_html__( 'Add as many custom sidebars as you need', 'yourtheme' ),
'settings' => 'sidebars',
'section' => 'section_sidebars',
)));
The first function is the sanitization function for your customizer sanitization callback.
So now you should have 'Sidebars' in your Appearance > Customize menu.
Create sidebars dynamically
But now you need to add your sidebars. If you have a dedicated sidebar file like sidebars.php where you register your theme sidebars, you can put this there, or in your functions.php file
if ( function_exists( 'register_sidebar' ) ) {
$sidebars=get_theme_mod('sidebars','');
if($sidebars!=''){
$sidebars = explode('|', $sidebars);
$i = 0;
foreach($sidebars as $sidebar){
$i++;
register_sidebar(array(
'name'=>$sidebar,
'id' => 'sidebar-'.$i,
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<div class="sidebar-widget-heading"><h3>',
'after_title' => '</h3></div>',
));
}
}
}
This is the minimum you need so that you can add multiple sidebars in the theme, and they should appear in Appearance > Widgets.
Add sidebar metabox
Now adding a metabox to display them is relatively easy. In your functions.php, or a separate file where you add metaboxes to posts/pages/CPT, add
// Add metabox
add_action('admin_init', 'yourtheme_post_add_meta');
if ( ! function_exists( 'yourtheme_post_add_meta' ) ){
function yourtheme_post_add_meta(){
add_meta_box('post-sidebar', esc_html__('Select Sidebar', 'yourtheme'), 'yourtheme_post_sidebar_meta_box', 'post');
}
}
//Metabox
if ( ! function_exists( 'yourtheme_post_sidebar_meta_box' ) ){
function yourtheme_post_sidebar_meta_box( $post ){
$values = get_post_custom( $post->ID );
$custom_sidebar = (isset($values['custom_sidebar'][0])) ? $values['custom_sidebar'][0] : '';
wp_nonce_field( 'my_meta_box_sidebar_nonce', 'meta_box_sidebar_nonce' );
?>
<p>
<select name="custom_sidebar" id="custom_sidebar">
<?php
global $wp_registered_sidebars;
$sidebar_replacements = $wp_registered_sidebars;
if(is_array($sidebar_replacements) && !empty($sidebar_replacements)){
foreach($sidebar_replacements as $sidebar){
echo "<option value='{$sidebar['name']}'".selected($sidebar['name'], $custom_sidebar, false).">{$sidebar['name']}</option>";
}
}
?>
</select>
</p>
<?php
}
}
//Save Metabox
add_action( 'save_post', 'yourtheme_post_save_sidebar_meta_box' );
if ( ! function_exists( 'yourtheme_post_save_sidebar_meta_box' ) ){
function yourtheme_post_save_sidebar_meta_box( $post_id ){
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
return;
}
if( !isset( $_POST['custom_sidebar'] ) || !wp_verify_nonce( $_POST['meta_box_sidebar_nonce'], 'my_meta_box_sidebar_nonce' ) ) {
return;
}
if( !current_user_can( 'edit_pages' ) ) {
return;
}
if( isset( $_POST['custom_sidebar'] ) ){
update_post_meta( $post_id, 'custom_sidebar', wp_kses( $_POST['custom_sidebar'] ,'') );
}
}
}
And this should be it. A bit lengthy, but a way to add as many sidebars to your theme as you wish :)
Hope it helps.
Giving the users option to choose a sidebar is fine, but i dont think its a good idea to give them functionality to create their own sidebars. You will quickly get into the problem where you will have tons of sidebars in your widget area each for a different post.
However if i was in your situation, i would have created a single sidebar and then dynamically added widgets to this sidebar depending on the post that is being viewed. For the end user both will look the same. Anyways there is no right or wrong answer here, it depends on how you want to tackle the situation.

wordpress class 'current-menu-item' not showing in nav menu in some pages when we are on the current page

I am working on the wordpress. I have created Footer Menu in admin panel and I want to show it on my site footer. I have used the function below. Problem is that the class 'current-menu-item' not appearing on some pages when we are on the current page to show active menu item selected. can I make it selected ?
<?php
$defaults = array(
'menu' => 'Footer Menu'
);
wp_nav_menu( $defaults ); ?>
Using jQuery solwing these problem :
Please write these jQuery script and check
<script>
jQuery(function(){
var activeurl = window.location;
if(jQuery('a[href="'+activeurl+'"]').parent().parent().parent().parent().parent().hasClass('menuitem'))
{
jQuery('a[href="'+activeurl+'"]').parent().parent().parent().children('h3').children('a').addClass('current-menu-item');
jQuery('a[href="'+activeurl+'"]').parent().parent().addClass('current-menu-item');
}
else
{
jQuery('a[href="'+activeurl+'"]').parent().parent().parent().children('a').addClass('current-menu-item');
jQuery('a[href="'+activeurl+'"]').addClass('current-menu-item');
jQuery('a[href="'+activeurl+'"]').parent().parent().addClass('current-menu-item');
}
});
</script>

How to change the links in top menu based on login status?

Can someone please answere the question how can I change the top menu item's link based on login status? e.g. if you're not logged it, you'll see /register link, if you're logged in you'll get # link of even (if this item is root) you will see the list of subpages for that menu?
If you are hard coding the links yourself, do something like this.
if(is_user_logged_in() ){
echo 'home';
}else{
echo 'register';
}
I did the same thing in my site like this.
step 1: create of two menu's position
You have to create two menu position like this
function register_my_menus(){
register_nav_menus(
array(
'new_user_navigation'=>__('New User Navigation'),
'registered_user_navigation'=>__('Registered Navigation'),
)
);
}
add_action( 'init','register_my_menus' );
Place the above code in function.php file.
now this will create two navigation areas in your admin panel menu section. From ware you can select the menu to be shown under these navigation areas in front panel.
Step 2: Select the menu from admin panel.
Now select the menu to be shown in particulate menu position.
Step 3: Edit the code in header.php file.
Now by using #In God I Trust code you can let the WordPress decide which menu to be displayed when the user in logged in like this.
if(is_user_logged_in() ){
if ( has_nav_menu( 'registered_user_navigation' ) ){
wp_nav_menu( array('theme_location' => 'registered_user_navigation',
'menu_item' => 'object_id'
) );
}
}else{
if ( has_nav_menu( 'new_user_navigation' ) ){
wp_nav_menu( array('theme_location' => 'new_user_navigation',
'menu_item' => 'object_id'
) );
}
}

Disable Shop page on Woocommerce to protect categories

Im trying to disable "shop" page in Woocommerce. Basically im creating a shop theme to sell prints and image downloads for a photographer.
Because i need to create private galleries i created a custom post type where i use the woocommerce category shortcode to show products and then i password protect the post type.
This is a workaround for password protecting the woocommerce categories (if someone knows a better one please explain).
The problem is that is someone goes to /shop they will all products, including the "protected ones". So i need to disable the shop page and i need to do it programmatically on my theme functions. Any thoughts?
To disable the shop page, copy over the archive-product.php file from the /wp-content/plugins/woocommerce/templates/archive-product.php and put in /wp-content/themes/{Your Theme}/woocommerce/archive-product.php
Open up the file and overwrite everything in file with the following code below:
<?php
global $wp_query;
$wp_query->set_404();
status_header(404);
get_template_part('404');
Save the file, and now your Shop page is gone and replaced with a 404 Page!
Add this to functions:
function woocommerce_disable_shop_page() {
global $post;
if (is_shop()):
global $wp_query;
$wp_query->set_404();
status_header(404);
endif;
}
add_action( 'wp', 'woocommerce_disable_shop_page' );
Docs: WooCommerce Conditional Functions Documentation
WooCommerce has a filter for the array that it uses to create the Product post type: woocommerce_register_post_type_product.
Rather changing the archive template to force it to redirect, you can completely remove the post type’s archive, but changing the has_archive attribute on the post type on creation.
add_filter('woocommerce_register_post_type_product', function($post_type) {
$post_type['has_archive'] = false;
return $post_type;
});
You should then remove the shop page in the CMS by going to WooCommerce » Settings » Product » Display, and clicking the “x” on the “Shop Page” option.
You might need to flush the permalink cache, which you can do just by clicking the “Update” button in Settings » Permalinks.
*Edit -
Apparently the page setting I suggested below no longer works. If WooCommerce doesn't have a plugin setting to change it, I personally would use a wordpress redirect plugin like Redirection. This way you can automatically redirect them from the undesired shop page to whatever page displays your products. It avoids a 404 issue and keeps everything in tact. It also avoids editing template files which adds complications to non-developers.
Old Answer:
Have you tried Woo settings?
Admin area, left main menu, Woocommerce > Settings
Click the pages tab.
Under Pages setup is "Shop Base Page", on the dropdown, there's a small "x" to right right. Click that to get rid of the page.
If there are links elsewhere that need to be fixed let me know and I'll find the hooks/filters to remedy it.
template_redirect is the last hook before page render so in my use case I ask if the page being viewed is the "shop" page and if it is I redirect to (in my case) a pricing page.
function my__template_redirect(){
if(is_shop()){
wp_redirect(site_url() . '/pricing/', '302');
}
}
add_action('template_redirect', 'my__template_redirect');
The last suggestion didn't work for me with WP 4.6.1 and WooCommerce 2.6.4. Hiding products in the Publish tab works for me.
http://paperhedge.com/hide-products-from-displaying-in-shop-page-woocommerce/
To disable the default shop page and leave the /shop/ slug free for custom pages use this:
function remove_woocommerce_default_shop( $args, $post_type ) {
if (class_exists('WooCommerce')) {
if ( $post_type == "product" ) {
$args['has_archive'] = true;
}
return $args;
}
}
add_filter('register_post_type_args', 'remove_woocommerce_default_shop', 20, 2);
You need to hook a couple (or maybe more) things:
/* hide category from shop pages */
add_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
if ( ! is_admin() ) {
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( YOUR-CATEGORY-SLUG, YOUR-CATEGORY-SLUG-2 ), // Don't display products in the knives category on the shop page
'operator' => 'NOT IN'
)));
}
remove_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
Change, obviusly YOUR-CATEGORY-SLUG, YOUR-CATEGORY-SLUG-2 for your cat or cats to hide from shop pages.
Then, you need to hide them from menues too, right?:
/* hide category from menues */
add_filter( 'get_terms', 'get_subcategory_terms', 10, 3 );
function get_subcategory_terms( $terms, $taxonomies, $args ) {
$new_terms = array();
// if category and on the shop page (change it with is_woocommerce() if want to hide from all woo pages)
if ( in_array( 'product_cat', $taxonomies ) && ! is_admin() && is_shop() ) {
foreach ( $terms as $key => $term ) {
if ( ! in_array( $term->slug, array( YOUR-CATEGORY-SLUG, YOUR-CATEGORY-SLUG-2 ) ) ) {
$new_terms[] = $term;
}
}
$terms = $new_terms;
}
return $terms;
}
But i don´t think this solve 100% the thing, since then, what about search results?
Try this
Create new page named "Shop"
Go to "woocommerce" > "Settings" > "Product" > "Display tab"
Select shop page named "Shop" then click save changes
Back to "Pages" then delete "Shop" page (keep the page on trash,
don't delete permanently)
This method works fine for me

WordPress wp_nav_menu specific sub menu only

I want to create a menu that pulls only the sub-menu options for a particular page.
For example, if the menu option DASHBOARD has the sub-menus MESSAGE BOARD and CALENDAR, I want to be able to create a separate menu with just MESSAGE BOARD and CALENDAR.
I'd like to do this without the wp_list_pages function so that the menu options can be managed using the Appearances > Menus tab in WordPress.
Thanks!
If I understood you correctly, you want additional menu items for sub pages?
I.E. You have a menu that looks like this
HOME ABOUT DASHBOARD FAQ CONTACT
DASHBOARD has 2 sub-pages -> BOARD CALENDAR
When you are on the DASHBOARD page you want the BOARD and CALENDAR pagees to show like this:
HOME ABOUT DASHBOAR FAQ CONTACT
BOARD CALENDAR
You can add an aditional menu in functions.php like this
<?php if (function_exists('register_nav_menus'))
{
register_nav_menus
(
array
(
'main_nav'=>'main menu', // your main menu
'dash_nav'=>'dashboard menu', //your dashboard menu
)
);
}?>
And then create a page template for dashboard which will have this:
<?php wp_nav_menu(array('menu'=>'dashboard menu'));?>
EDIT:
Well you could edit the header.php and add something like this
<?php if (is_page_template('dashboard.php') :?>
<link href="csspath" rel="stylesheet" type="text/css" />
<?php endif;?>
That way you add another css file that overrides the submenu.
I think I had a similar desire as you to select and only show a sub menu being just the children menu items from an existing wordpress menu. This can be done by editing the functions.php and adding a shortcode that has it's own walker class to target and display a submenu.
PHP code for "menu" shortcode and customized menu walker class (all goes in functions.php):
//register menu shortcode
add_shortcode('menu', 'shortcode_menu');
function shortcode_menu($args ) {
//don't echo the ouput so we can return it
$args['echo']=false;
//in case menu isn't found display a message
$args['fallback_cb']='shortcode_menu_fallback';
//check if showing a submenu, if so make sure everything is setup to do so
if (isset($args['show_submenu']) && !empty($args['show_submenu'])) {
if (!isset($args['depth'])) {
$args['depth']=1;
}
$args['walker']=new Sub_Menu_Walker_Nav_Menu();
}
$menu=wp_nav_menu( $args );
return $menu;
}
//message to display if menu isn't found
function shortcode_menu_fallback($args ) {return 'No menu selected.';}
//special walker_nav_menu class to only display submenu
//depth must be greater than 0
//show_submenu specifies submenu to display
class Sub_Menu_Walker_Nav_Menu extends Walker_Nav_Menu {
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
if ( !$element )
return;
$id_field = $this->db_fields['id'];
$displaythiselement=$depth!=0;
if ($displaythiselement) {
//display this element
if ( is_array( $args[0] ) )
$args[0]['has_children'] = ! empty( $children_elements[$element->$id_field] );
$cb_args = array_merge( array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'start_el'), $cb_args);
}
$id = $element->$id_field;
if ( is_array( $args[0] ) ){
$show_submenu=$args[0]['show_submenu'];
}else
$show_submenu=$args[0]->show_submenu;
// descend only when the depth is right and there are childrens for this element
if ( ($max_depth == 0 || $max_depth >= $depth+1 ) && isset( $children_elements[$id]) && $element->title==$show_submenu) {
foreach( $children_elements[ $id ] as $child ){
if ( !isset($newlevel) ) {
$newlevel = true;
//start the child delimiter
$cb_args = array_merge( array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'start_lvl'), $cb_args);
}
$this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
}
unset( $children_elements[ $id ] );
}
if ( isset($newlevel) && $newlevel ){
//end the child delimiter
$cb_args = array_merge( array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'end_lvl'), $cb_args);
}
if ($displaythiselement) {
//end this element
$cb_args = array_merge( array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'end_el'), $cb_args);
}
}
}
Display a submenu titled "About" from the "Main" menu (capitalization matters):
[menu menu='Main' show_submenu='About']
Display the full "Main" menu:
[menu menu='Main']
For further reading/reference see this wordpress question.
I am surprised that Wordpress doesn't have this option built into the wp_nav_menu function. It has always been a struggle to implement secondary or split menus in Wordpress. After trying a number of different solutions to accomplish this goal I finally decided to make my own plugin that lets you choose the start depth for your menu. So you can just set the start depth to '1' for a secondary menu.
you use the plugin like this:
wp_nav_plus(array('theme_location' => 'primary_navigation', 'start_depth' => 1));
The plugin is available on my site here for anyone interested: https://mattkeys.me/products/wp-nav-plus/

Resources