I have a function where I duplicate a user to all subsite when they registered.
I achieved that by doing this:
function sync_user( $user_id )
{
$list_ids = get_sites();
$current_site = get_current_site();
$info = get_userdata($user_id);
foreach( $list_ids as $list )
{
if ( $list->blog_id != $current_site->id )
{
add_user_to_blog($list->id, $info->ID, 'subscriber');
}
}
// quick fix for: above somehow doesn't add to main site. add to main site here.
add_user_to_blog(1, $info->ID, 'subscriber');
}
Now, I want to "unsyc" the user when I removed the user from the site. I tried to hook it by using 'remove_user_from_blog', but it caused infinite loop.
Where can I hook the following code so that I can remove all those users that I added previously using above code?
function unsync_user( $user_id )
{
$list_ids = get_sites();
foreach( $list_ids as $list )
{
remove_user_from_blog( $user_id, $list->ID );
}
}
edited the title for clarity
AbdulRahman was correct about that. When user click 'remove' from the user list, the action not fire 'delete_user' or 'deleted_user' hook. I tested it.
I think it is tricky. So, here is how to add custom removed_user action. Add these lines below into your plugin.
add_action('remove_user_from_blog', function($user_id, $blog_id) {
// checking current action
// refer: wp-admin/users.php:99
$wp_list_table = _get_list_table( 'WP_Users_List_Table' );
if( $wp_list_table->current_action() != 'doremove' ) {
return; // only proceed for specific user list action
}
$fire_removed_user_hook = null; // closure reference
$fire_removed_user_hook = function() use ($user_id, $blog_id, &$fire_removed_user_hook) {
do_action( 'removed_user', $user_id, $blog_id );
// remove the hook back
remove_action('switch_blog', $fire_removed_user_hook);
};
// restore_current_blog called at the last line in the remove_user_from_blog function
// so action switch_blog fired
add_action('switch_blog', $fire_removed_user_hook);
}, 10, 2);
add_action('removed_user', function($user_id, $blog_id) {
// the user removed from be blog at this point
}, 10, 2);
The hook "deleted_user" runs after a user is deleted ("delete_user" runs before the deletion occurs):
https://codex.wordpress.org/Plugin_API/Action_Reference/deleted_user
Related
I enabled image uploads for contributors on my Wordpress site via the following code:
if ( current_user_can('contributor') && !current_user_can('upload_files') )
add_action('admin_init', 'allow_contributor_uploads');
function allow_contributor_uploads() {
$contributor = get_role('contributor');
$contributor->add_cap('upload_files');
}
It works great, but I also need to disallow them to delete the images they uploaded. Is there an easy way to do it? I know there's User Role Editor plugin, but I don't want to install it just for this.
You can use delete_attachment hook or pre_delete_attachment filter for that:
add_action('delete_attachment', 'wp66410923_prevent_delete_attachment', 11, 1);
function wp66410923_prevent_delete_attachment($postID)
{
if (current_user_can('contributor')) {
echo __('You can not delete attachments.');
die;
}
}
add_filter( 'pre_delete_attachment', 'wp66410923_filter_attachment_deletion', 10, 3 );
function wp66410923_filter_attachment_deletion( $delete, $post, $force_delete ){
if (current_user_can('contributor')) {
return false;
}
return true;
}
I would like to serve different content based on the URL.
I started with a custom page setup via a custom template but I am open to something else.
The main goal is to have one PHP page that can serve different contents programmatically based on the URL.
For example:
https://some-url.com/my-plugin/ -> run my page
https://some-url.com/my-plugin/foo/ -> run my page
https://some-url.com/my-plugin/foo2/abc/ -> run my page
etc...
I have been looking at add_rewrite_rule, add_rewrite_tag, flush_rewrite_rules and WP_Rewrite API but I am getting confused about which one I should use?
I found an example here but I could not make it work, I get 404s, any idea why?:
/*
Plugin Name: Products Plugin
Plugin URI: http://clivern.com/
Description: Register URL rules for our products
Version: 1.0
Author: Clivern
Author URI: http://clivern.com
License: MIT
*/
function products_plugin_activate() {
products_plugin_rules();
flush_rewrite_rules();
}
function products_plugin_deactivate() {
flush_rewrite_rules();
}
function products_plugin_rules() {
add_rewrite_rule('products/?([^/]*)', 'index.php?pagename=products&product_id=$matches[1]', 'top');
}
function products_plugin_query_vars($vars) {
$vars[] = 'product_id';
return $vars;
}
function products_plugin_display() {
$products_page = get_query_var('pagename');
$product_id = get_query_var('product_id');
if ('products' == $products_page && '' == $product_id):
//show all products
exit;
elseif ('products' == $products_page && '' != $product_id):
//show product page
exit;
endif;
}
//register activation function
register_activation_hook(__FILE__, 'products_plugin_activate');
//register deactivation function
register_deactivation_hook(__FILE__, 'products_plugin_deactivate');
//add rewrite rules in case another plugin flushes rules
add_action('init', 'products_plugin_rules');
//add plugin query vars (product_id) to wordpress
add_filter('query_vars', 'products_plugin_query_vars');
//register plugin custom pages display
add_filter('template_redirect', 'products_plugin_display');
First of all, make sure your pretty permalinks are enabled, in this case the option "Plain" in Settings - Permalinks should be unselected:
Select one of these options to enable pretty permalinks
You can check whether pretty permalinks are enabled in the code like so:
function is_enabled_pretty_permalinks() {
return !empty( get_option( 'permalink_structure' ) );
}
if ( is_enabled_pretty_permalinks() ) {
echo 'Pretty permalinks enabled';
}
Next add a new rewrite rule:
function add_my_rewrite_rule() {
$page_slug = 'products'; // slug of the page you want to be shown to
$param = 'do'; // param name you want to handle on the page
add_rewrite_rule('my-plugin/?([^/]*)', 'index.php?pagename=' . $page_slug . '&' . $param . '=$matches[1]', 'top');
}
add_action('init', 'add_my_rewrite_rule');
Add your parameter to query vars so you will be able to handle it on the page:
function add_my_query_vars($vars) {
$vars[] = 'do'; // param name you want to handle on the page
return $vars;
}
add_filter('query_vars', 'add_my_query_vars');
Then you can access your query var do in the page template or in a shortcode, for example:
function my_plugin_shortcode_handler( $atts ){
$do = get_query_var( 'do' );
if ( $do === 'this' ) {
return 'do this';
} else {
return 'do that';
}
}
add_shortcode( 'myshortcode', 'my_plugin_shortcode_handler' );
Then place the shortcode to the content via Gutenberg.
Check out the links:
https://some-url.com/my-plugin/this/ - outputs "do this"
https://some-url.com/my-plugin/that/ - outputs "do that".
This can be solved by using query params. Like you mentioned you have set up custom page via a custom template. You can read the URL and check for the parameters and based on that you can send data from the PHP template page.
e.g,
function cleanTheInput($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
$data = htmlentities($data);
return $data;
}
if (isset($_GET['page_url'])) {
$theUrl = cleanTheInput($_GET['page_url']);
}
if($theUrl == 266)){
// data for https://some-url.com/?page_url=266
}
if($theUrl == 366)){
// data for https://some-url.com/?page_url=366
}
I have two plugins installed, which has generated two "Events" submenu in my toolbar. I would like to rename one of them to be able to make a difference.
I have found this topic:
how to rename plugin title
With this I can achieve to rename BOTH "Events" to any other title:
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case 'Event' :
$translated_text = __( '3rd party Events', 'Event' );
break;
}
return $translated_text;
}
add_filter( 'gettext', 'my_text_strings', 20, 3 );
The problem with this is that it renames both of my Event menu and I only want to rename the first.
With this code I can target the admin menu to get the complete tree in the source code and get the plugin's unique name, but this only gets me admin menu, not the toolbar.
add_action( 'admin_menu', 'myRenamedPlugin' );
function myRenamedPlugin() {
global $menu;
$searchPlugin = "pgl_wp_files"; // Use the unique plugin name
$replaceName = "New Name for Plugin";
$menuItem = "";
foreach($menu as $key => $item){
if ( $item[2] === $searchPlugin ){
$menuItem = $key;
}
}
$menu[$menuItem][0] = $replaceName; // Position 0 stores the menu title
}
There is another topic discussing the question here, but this also renames ALL with the same name.
How do I target the exact menu item (not just the ones with matching name) in the Toolbar to rename?
I've looked at the code and there isn't any filters that I can see. So you basically will need to do a hack.
Option 1
Get at the node you want to change (by id). Remove that node, then change the title and add it back
add_action('wp_before_admin_bar_render', function () {
global $wp_admin_bar;
// Get the node
$node = $wp_admin_bar->get_node('some-event-id');
// Remove the node
$wp_admin_bar->remove_node('some-event-id');
// Change the node title
$node->title = 'Events #2';
// Add the node back to the menu
$wp_admin_bar->add_menu($node);
}, 9999999, 0);
Option 2
Capture the output buffer of the admin menu, do some string or regex find and replace, then output the buffer
add_action('wp_before_admin_bar_render', function () {
ob_start();
add_action('wp_after_admin_bar_render', function () {
$buffer = ob_get_clean();
// do some find/replace
echo $buffer;
}, 1, 0);
}, 9999999, 0);
There are pros/cons to each, and neither would be perfect. But as far as I can tell, that is your best shot.
i am creating plugin for my project. i want to create one page when plugin gets activate and same way i want to delete that page when plugin gets deactivate... i am able to create page but i am facing problem while deleting page...
my code is
global $page_id;
register_activation_hook(__FILE__,'createPage');
register_deactivation_hook(__FILE__, 'dropPage');
function createPage()
{
global $page_id;
$page['post_type'] = 'page';
$page['post_content'] = 'hello this page created by plugin';
$page['post_status'] = 'publish';
$page['post_title'] = 'dpage';
$page_id = wp_insert_post ($page);
}
function dropPage()
{
global $page_id;
wp_delete_page($page_id);
}
it's not deleting page... if i give wp_delete_post('116') then it's working fine... i have assigning page id in global variable then also i am not able to retrieve it..
can any one suggest me how to do it?
Thanks in advance
the global $page_id you're adding will only contain the page ID when you're activating the plugin. To store the page ID, use the Options API.
register_activation_hook(__FILE__,'createPage');
register_deactivation_hook(__FILE__, 'dropPage');
function createPage()
{
$page['post_type'] = 'page';
$page['post_content'] = 'hello this page created by plugin';
$page['post_status'] = 'publish';
$page['post_title'] = 'dpage';
$page_id = wp_insert_post ($page);
update_option('the_page_id_i_created', $page_id );
}
function dropPage()
{
if( get_option('the_page_id_i_created') ){
wp_delete_page( get_option('the_page_id_i_created') );
}
}
So I'm trying to hide certain ship methods in Woocommerce based on a product tag. The main problem I face is my own lack PHP knowledge so I frankensteined the following code together with the help of some very friendly folks:
add_filter( 'woocommerce_available_shipping_methods', 'hide_shipping_based_on_tag' , 10, 1 );
function check_cart_for_share() {
// load the contents of the cart into an array.
global $woocommerce;
$cart = $woocommerce->cart->cart_contents;
$found = false;
// loop through the array looking for the tag you set. Switch to true if the tag is found.
foreach ($cart as $array_item) {
if (isset($array_item['product_tag']) && $array_item['product_tag'] == "CHOSEN_TAG") { // Replace "CHOSEN_TAG" with what ever tag you want
$found = true;
break;
}
}
return $found;
}
function hide_shipping_based_on_tag( $available_methods ) {
// use the function abve to check the cart for the tag.
if ( check_cart_for_share() ) {
// remove the rate you want
unset( $available_methods['flat_rate'] ); // Replace "flar_rate" with the shipping option that yu want to remove.
}
// return the available methods without the one you unset.
return $available_methods;
}
I understand that this code is by no means universal and thus the variables will be different from case to case but perhaps someone can tell me if something looks off in the code. Much appreciated
No doubt you have sorted this by now but your code was a good start for me ... and since I sorted it I have published it below. Your problem was that woocommerce doesn't have the product_tag in the cart array so you have to go and get it.
/* !Hide Shipping Options Woocommerce */
add_filter( 'woocommerce_available_shipping_methods', 'hide_shipping_based_on_tag' , 10, 1 );
function check_cart_for_share() {
// load the contents of the cart into an array.
global $woocommerce;
$cart = $woocommerce->cart->cart_contents;
$found = false;
// loop through the array looking for the tag you set. Switch to true if the tag is found.
foreach ($cart as $array_item) {
$term_list = wp_get_post_terms( $array_item['product_id'], 'product_tag', array( "fields" => "names" ) );
if (in_array("Heavy",$term_list)) { // Replace "Heavy" with what ever tag you want
$found = true;
break;
}
}
return $found;
}
function hide_shipping_based_on_tag( $available_methods ) {
// use the function above to check the cart for the tag.
if ( check_cart_for_share() ) {
// remove the rate you want
unset( $available_methods['flat_rate'] ); // Replace "flat_rate" with the shipping option that you want to remove.
}
// return the available methods without the one you unset.
return $available_methods;
}
You can use shipping class of Woocommerce to achieve this.
Here is the step by step instructions.
Create a shipping class (woocommerce->settings->shipping->shipping classes).
Associate this shipping class with products (that you wand to hide shipping methods for)
Use this snippet. (copy and pate to function.php).
For more information about the snippet is available here.