remove_menu_page() not getting initialized within if condition - php

I am trying to remove some menu pages based on user role, but when I add the function inside the if condition it doesn't do anything.
function contributor_posts_action() {
if ($role == 'contributor_posts') { // contributor_posts - custom role
// echo 'here'; for testing purposes and WORKS, so it goes under the if condition
add_action( 'admin_menu', 'remove_menus_contrib' );
function remove_menus_contrib(){
remove_menu_page( 'edit-comments.php' );
remove_menu_page( 'tools.php' );
remove_menu_page( 'edit.php?post_type=directory' );
remove_menu_page( 'edit.php?post_type=city' );
} // this function doesn't get hooked
add_action( 'admin_bar_menu', 'remove_admin_bar_items', 999 );
function remove_admin_bar_items( $wp_admin_bar ) {
$wp_admin_bar->remove_node( 'new-directory' );
$wp_admin_bar->remove_node( 'new-city' );
}// this one works properly. It's for removing for admin bar.
}
}
add_action( 'admin_init', 'contributor_posts_action' );

Try pulling the remove_menus_contrib() and the add_action( 'admin_menu', 'remove_menus_contrib' ) hook function out of your contributor_posts_action() function.
Some Wordpress hooks won't work inside other (custom) functions.

Related

Hide wp menu items based on user role / id / etc

i've tried the following to hide a few wp menu items from my client dashboard:
// Hide admin menu items for shop manager
function hide_menu() {
if (current_user_can('manage_woocommerce')) {
/* WP DEFAULT MENUS */
remove_menu_page( 'edit.php' ); //Posts
remove_menu_page( 'edit.php?post_type=page' ); //Pages
remove_menu_page( 'edit-comments.php' ); //Comments
remove_menu_page( 'themes.php' ); //Appearance
remove_menu_page( 'users.php' ); //Users
remove_menu_page( 'tools.php' ); //Tools
/* PLUGINS */
remove_menu_page( 'edit.php?post_type=elementor_library&tabs_group=library' ); //Template
remove_menu_page( 'admin.php?page=yith_wcan_panel' ); //Yith
}
}
add_action('admin_head', 'hide_menu', 5 );
But now the admin menu items are gone for me as well (superuser).
What did i get wrong?
Also, while removing things also for me while it shouldn't, it didn't remove the WC submenu items "Settings" and "Addons", nor elementor's "Template" and Yith tab (see attachment).
EDIT
now i've tried this:
// Hide admin menu items for shop manager
function hide_menu() {
if ( !current_user_can('manage_options') ) {
/* WP DEFAULT MENUS */
remove_menu_page( 'edit.php' ); //Posts
remove_menu_page( 'edit.php?post_type=page' ); //Pages
remove_menu_page( 'edit-comments.php' ); //Comments
remove_menu_page( 'themes.php' ); //Appearance
remove_menu_page( 'users.php' ); //Users
remove_menu_page( 'tools.php' ); //Tools
/* PLUGINS */
remove_submenu_page( 'admin.php?page=wc-admin', 'admin.php?page=wc-settings'); // Settings
remove_submenu_page( 'admin.php?page=wc-admin', 'admin.php?page=wc-addons'); // Addons
remove_menu_page( 'edit.php?post_type=elementor_library&tabs_group=library' ); //Template
remove_menu_page( 'admin.php?page=yith_wcan_panel' ); //Yith
}
}
add_action('admin_head', 'hide_menu', 5 );
And it mostly works, however i'm still not able to hide the two woocommerce subpages (settings and marketplace), elementor's template and yith.
Change your conditional to if (current_user_can('manage_woocommerce') && ! is_admin()) {
Depending on your site you may need to use is_super_admin()

WordPress Remove Menu Pages Except for Super Admin

I have written a snippet to remove some WordPress menu pages.
add_action( 'admin_menu', 'notadmin_remove_menus', 999 );
function notadmin_remove_menus() {
remove_menu_page('edit.php');
remove_menu_page('edit.php?post_type=page');
remove_menu_page('upload.php');
remove_menu_page('jetpack');
remove_menu_page('users.php');
remove_menu_page('tools.php');
remove_menu_page('edit-comments.php');
remove_menu_page('edit.php?post_type=featured_item');
remove_menu_page('edit.php?post_type=feedback');
remove_menu_page('edit.php?post_type=blocks');
}
The problem is this code also remove menu pages for super admin. I want to remove these menu for all users except super admin. Please help.
Try this code
add_action( 'admin_menu', 'notadmin_remove_menus', 999 );
function notadmin_remove_menus() {
if ( !is_super_admin() ) {
remove_menu_page('edit.php');
remove_menu_page('edit.php?post_type=page');
remove_menu_page('upload.php');
remove_menu_page('jetpack');
remove_menu_page('users.php');
remove_menu_page('tools.php');
remove_menu_page('edit-comments.php');
remove_menu_page('edit.php?post_type=featured_item');
remove_menu_page('edit.php?post_type=feedback');
remove_menu_page('edit.php?post_type=blocks');
}
}
or
if ( !is_super_admin() ) {
add_action( 'admin_menu', 'notadmin_remove_menus', 999 );
}
function notadmin_remove_menus() {
remove_menu_page('edit.php');
remove_menu_page('edit.php?post_type=page');
remove_menu_page('upload.php');
remove_menu_page('jetpack');
remove_menu_page('users.php');
remove_menu_page('tools.php');
remove_menu_page('edit-comments.php');
remove_menu_page('edit.php?post_type=featured_item');
remove_menu_page('edit.php?post_type=feedback');
remove_menu_page('edit.php?post_type=blocks');
}

WP / WC calling add_action "init" from inside another function

I have a problem with a plugin and WooCommerce.
So I have a plugin with an options page, and a custom checkbox on it.
When this checkbox is activated, I want to hide/remove the default WooCommerce related product container.
I can remove this container if I just add this code:
add_action( 'init', 'add_action_function');
function add_action_function(){
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
}
But the problem is that I need to call this function from inside another "add_filter" function.
In the moment I have something like this:
add_filter( 'woocommerce_after_single_product_summary', 'add_filter_function' );
function add_filter_function () {
// Get the plugin option
$active = get_option( 'prfx_active', 'no');
// If option value is "yes", remove the related products container
if ($active = 'yes') {
// I think this add_action call is wrong
add_action( 'init', 'add_action_function');
function add_action_function(){
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
}
}//END if $active = yes
// Do some other stuff here
}//END add_filter_function
But when I change the option in the admin-settings, nothing changes. So I think the "init" hook is not right here.
I cant find the right hook to make this work. What hook must I use when I want it to fire when the plugin options get updated?
Thanks in advanced,
Mo
Thanks to Danijel and his answers.
I dont know why I didnt think of it this way.
Maybe this was to much "action" for me on that late evening ;)
I now placed the "add_action" outside of the "add_filter" function and just do the conditional-check there.
This is working:
add_action( 'init', 'hide_related');
function hide_related () {
if ( get_option( 'prfx_active', 'no' ) == 'yes' ) {
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
}
};
add_filter( 'woocommerce_after_single_product_summary', 'add_filter_function' );
function add_filter_function () {
...
Im quite certain that WP init action is fired before woocommerce_after_single_product_summary filter, and also if ( $active = 'yes' { ... expression will always be evaluated as true ( use == ). Try with this simple example:
add_action( 'init', function() {
if ( get_option( 'prfx_active', 'no' ) == 'yes' )
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
});
Try moving your add_action_funciton outside of add_filter_function
add_filter( 'woocommerce_after_single_product_summary', 'add_filter_function' );
function add_action_function(){
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
}
function add_filter_function () {
// Get the plugin option
$active = get_option( 'prfx_active', 'no');
// If option value is "yes", remove the related products container
if ($active = 'yes') {
// I think this add_action call is wrong
add_action( 'init', 'add_action_function');
}//END if $active = yes
// Do some other stuff here
}//END add_filter_function

PHP function reference using args

I'm new to PHP. I'm trying to hide certain dashboard nav items from certain users (editors). I've added this to the functions, which has hidden it for all users:
<?php
function remove_menus(){
remove_menu_page( 'edit-comments.php' ); //Comments
}
add_action( 'admin_menu', 'remove_menus' );
?>
It says here you can use 'current_user_can' to pinpoint certain users but I'm unsure how to use both together.
So far I've tried:
function remove_menus(){
current_user_can(
remove_menu_page( 'editor', 'edit-comments.php' ); //Comments
) );
}
and
function remove_menus(){
current_user_can( array(
remove_menu_page( 'editor', 'edit-comments.php' ); //Comments
) );
}
..but from looking at other functions, they seem to in brackets with => inbetween so I'm presuming I'm using this function the wrong way.
Any help would be appreciated, thanks.
First answer, very simple , use logic "OR" operator:
<?php
function remove_menus(){
if( current_user_can('editor') || current_user_can('administrator') ) { // stuff here for admins or editors
remove_menu_page( 'edit-comments.php' ); //stuff here for editor and administrator
}
} ?>
If you want to check more than two roles, you can check if the roles of current user is inside an array of roles, something like:
<?php
function remove_menus(){
$user = wp_get_current_user();
$allowed_roles = array('editor', 'administrator', 'author');
if( array_intersect($allowed_roles, $user->roles ) ) {
remove_menu_page( 'edit-comments.php' ); //stuff here for allowed roles
}
} ?>
However, current_user_can can be used not only with users role name, but also with capabilities. So, once both editors and administrators can edit pages, your life can be easier checking for that capabilities:
<?php
function remove_menus(){
if( current_user_can('edit_others_pages') ) {
remove_menu_page( 'edit-comments.php' );// stuff here for user roles that can edit pages: editors and administrators
}
}
?>
Have a look here for more info on capabilities.

need help removing action from plugin file

Hello I am trying to remove an action from a wordpress plugin file. The plugin is called Woocommerce Points and Rewards. I have found the action I want to remove in one of the class files. When I comment out the "add_action" it does exactly what I want. But I am trying to remove the action from functions.php in my child them. I have been reading on this and I think my problem is I need to "globalize" the class variable that the action is in; but I am not sure what that class variable is…
here is the code where it adds the action (part of a file):
class WC_Points_Rewards_Cart_Checkout {
/**
* Add cart/checkout related hooks / filters
*
* #since 1.0
*/
public function __construct() {
// Coupon display
add_filter( 'woocommerce_cart_totals_coupon_label', array( $this, 'coupon_label' ) );
// Coupon loading
add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'points_last' ) );
add_action( 'woocommerce_applied_coupon', array( $this, 'points_last' ) );
// add earn points/redeem points message above cart / checkout
add_action( 'woocommerce_before_cart', array( $this, 'render_earn_points_message' ), 15 );
add_action( 'woocommerce_before_cart', array( $this, 'render_redeem_points_message' ), 16 );
add_action( 'woocommerce_before_checkout_form', array( $this, 'render_earn_points_message' ), 5 );
add_action( 'woocommerce_before_checkout_form', array( $this, 'render_redeem_points_message' ), 6 );
// handle the apply discount submit on the cart page
add_action( 'wp', array( $this, 'maybe_apply_discount' ) );
// handle the apply discount AJAX submit on the checkout page
add_action( 'wp_ajax_wc_points_rewards_apply_discount', array( $this, 'ajax_maybe_apply_discount' ) );
}
The function I want to remove is this one:
add_action( 'woocommerce_before_cart', array( $this, 'render_redeem_points_message' ), 16 );
so far no luck in getting it removed; here is what I have in functions.php:
global $woocommerce, $wc_points_rewards;
/*
global $this;
*/
remove_action( 'woocommerce_before_cart', array( $this, 'render_redeem_points_message' ), 16 );
so - I am sure this can be done in this way at least I have read that it can be done, I think I just have some thing wrong on this…
I tried globalizing $this, but that just gave me an error message...
if you need to see the entire file or something else please just let me know…
So I am hoping someone on here can help me identify what I am doing wrong…
** UPDATE Monday 8/18 ********
Looking for where class is instantiated; I have found this in the "woo commerce-points-and-rewards.php" file; this looks like this may be it but not sure what I am looking at;
does this look like where the "WC_Points_Rewards_Cart_Checkout" is instantiated?
And if so I am not sure how i use this to write my "remove action" in functions.php...
private function includes() {
// product class
require( 'classes/class-wc-points-rewards-product.php' );
$this->product = new WC_Points_Rewards_Product();
// cart / checkout class
require( 'classes/class-wc-points-rewards-cart-checkout.php' );
$this->cart = new WC_Points_Rewards_Cart_Checkout();
// order class
require( 'classes/class-wc-points-rewards-order.php' );
$this->order = new WC_Points_Rewards_Order();
// discount class
require( 'classes/class-wc-points-rewards-discount.php' );
$this->discount = new WC_Points_Rewards_Discount();
// actions class
require( 'classes/class-wc-points-rewards-actions.php' );
$this->actions = new WC_Points_Rewards_Actions();
// manager class
require( 'classes/class-wc-points-rewards-manager.php' );
// points log access class
require( 'classes/class-wc-points-rewards-points-log.php' );
if ( is_admin() )
$this->admin_includes();
}
Thanks so much...
Try this:
// Use the class name instead of a globalized $this
remove_action( 'woocommerce_before_cart', array( 'WC_Points_Rewards_Cart_Checkout', 'render_redeem_points_message' ), 16 );
As $this is an internal referrer to the class it is used in, globalizing it may not be a good thing.
Does the plugin allow you to extend the class with your own and use it instead?
you found a solution for this? having the same problem with another wc plugin ;)
alright. found an answer in the wc docs. in my case:
function wc_move_checkout_addons() {
remove_action( 'woocommerce_checkout_after_customer_details', array( $GLOBALS['wc_checkout_add_ons']->frontend, 'render_add_ons' ) );
add_action( 'woocommerce_checkout_before_customer_details', array( $GLOBALS['wc_checkout_add_ons']->frontend, 'render_add_ons' ) );
}
add_action( 'init', 'wc_move_checkout_addons' );
so in your case it should be something like that:
function wc_remove_message() {
remove_action( 'woocommerce_before_cart', array( $GLOBALS['wc_points_rewards_cart_checkout']->frontend, 'render_redeem_points_message' ) );
}
add_action( 'init', 'wc_remove_message' );
In case anyone else is wondering, I just accomplished removing the action in this plugin in the following way.
I wanted to remove the action defined in class-wc-points-rewards.php on line 34:
add_action( 'woocommerce_single_product_summary', array( $this, 'render_product_message' ) );
To do that, I looked at woocommerce-points-and-rewards.php. On line 46 it shows:
$GLOBALS['wc_points_rewards'] = new WC_Points_Rewards();
And in the same file for the definition of the WC_Points_Rewards class, on line 249-250 it shows:
require( 'includes/class-wc-points-rewards-product.php' );
$this->product = new WC_Points_Rewards_Product();
With that information, I was able to remove the action:
remove_action( 'woocommerce_single_product_summary', array( $GLOBALS['wc_points_rewards']->product, 'render_product_message' ) );
I was able to figure out how to remove the render_redeem_points_message effectively with the following code:
/* Removes render_redeem_points_message() */
function wc_remove_points_message() {
global $woocommerce;
global $wc_points_rewards;
// Removes message from cart page
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 16 );
// Removes message from checkout page
remove_action( 'woocommerce_before_checkout_form', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 6 );
}
// Removes action on init
add_action( 'init', 'wc_remove_points_message' );
To share a bit more, I wanted to create a minimum purchase amount to be able to redeem points:
/* Adds Minimum Order for Points Redemption */
function wc_min_order_points_message() {
global $woocommerce;
global $wc_points_rewards;
// Get cart subtotal, excluding tax
$my_cart_total = $woocommerce->cart->subtotal_ex_tax;
if ($my_cart_total < 30) { // $30 minimum order
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 16 );
remove_action( 'woocommerce_before_checkout_form', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 6 );
} // endif $my_cart_total
}
// Adds action for cart and checkout pages instead of on init
add_action( 'woocommerce_before_cart', 'wc_min_order_points_message' );
add_action( 'woocommerce_before_checkout_form', 'wc_min_order_points_message' );
I hope this helps anyone else trying to similarly expand on the WooCommerce Points and Rewards plugin.
SOLUTION-1:
In this case, as we have the plugin object's global instance, then we can do it easily:
remove_action('woocommerce_before_cart',array($GLOBALS['wc_points_rewards']->cart,'render_redeem_points_message'),16);
SOLUTION-2:
We will not be lucky always like the above solution getting the instance of the class object if any plugin author creates the class object anonymously without storing it to any global variables or keeping no method which can return it's own instance. In those cases, we can use the following :)
//keeping this function in our functions.php
function remove_anonymous_object_action( $tag, $class, $method, $priority=null ){
if( empty($GLOBALS['wp_filter'][ $tag ]) ){
return;
}
foreach ( $GLOBALS['wp_filter'][ $tag ] as $filterPriority => $filter ){
if( !($priority===null || $priority==$filterPriority) )
continue;
foreach ( $filter as $identifier => $function ){
if( is_array( $function)
and is_a( $function['function'][0], $class )
and $method === $function['function'][1]
){
remove_action(
$tag,
array ( $function['function'][0], $method ),
$filterPriority
);
}
}
}
}
And calling the following line appropriately when we need (may be with a hook or something):
//-->Actual Target: this line does not work;
//remove_action( 'personal_options', array('myCRED_Admin','show_my_balance') );
//-->But instead this line will work ;)
remove_anonymous_object_action('personal_options','myCRED_Admin','show_my_balance');
exactly this function worked for me
if (class_exists('WC_Points_Rewards')) {
global $woocommerce, $wc_points_rewards;
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_earn_points_message' ), 15 );
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 16 );
}

Categories