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.
Related
I'm building a simple plugin that uses the geoservices web service and what I'm trying to do is dynamically change the content on a WordPress page based on their location. I have it working somewhat but my issue is that it's returning both the location-specific text AND the default. I know it's because i'm using the shortcode instance more than once but I don't know how to change it to ONLY show the location specific content and if the location is not set or does not match the shortcode params then fall back to the default one. I don't want to add "default" as a shortcode param because it could contain HTML or something else.
Here is an example of my shortcode:
[geo city="Orlando"]555-123-6349[/geo][geo city="Raleigh"]919-999-9999[/geo][geo city="Default"]Default text here[/geo]
So based on the above, the desired result would show Orlando's phone number if the user is from Orlando or it would show Raleigh number if they are from Raleigh. Otherwise, if they are not from either of those places, it would use the default.
Here is my shortcode:
function geo_services( $atts , $content = null ) {
// Attributes
extract(shortcode_atts(array(
'city' => '',
'state' => '',
), $atts));
require_once('geoplugin.class.php');
$geoplugin = new geoPlugin();
$geoplugin->locate();
if($city === $geoplugin->city){
return $content;
} elseif ($state === $geoplugin->region){
return $content;
} elseif ($city === 'Default') {
return $content;
}
}
add_shortcode( 'geo', 'geo_services' );
And here is what is happening when I use the example shortcode above:
I believe you may be misunderstanding how shortcodes work in WP. In your example, you have added 3 shortcodes to the content. Each of those shortcodes is going to run. Not one or the other. So doing,
[geo city="Orlando"]555-123-6349[/geo][geo city="Raleigh"]919-999-9999[/geo][geo city="Default"]Default text here[/geo]
means that each of those will be called and evaluated. $geoplugin->city is always going to return the city of the user, regardless of what attributes you supplied. And since you are returning $content in all cases, it will always spit out the content that you added inside the shortcode. This is why you are seeing all 3 responses.
Instead, I would try the approach below. If your goal is to spit out content based on the city of the user, you really don't need to supply an attribute to the shortcode. See the following example:
//in your post/page content, simply use the shortcode geo
[geo]
//your function should be
function geo_services( $atts , $content = null ) {
//
require_once('geoplugin.class.php');
//
$geoplugin = new geoPlugin();
$geoplugin->locate();
//
switch( $geoplugin->city ) {
case 'Orlando':
return '555-123-6349';
break;
case 'Raleigh':
return '919-999-9999';
break;
default:
return 'Default text here';
break;
}
}
add_shortcode( 'geo', 'geo_services' );
Providing another answer based on OP comments. If you really need to manage the content via the WYSIWYG, then you could supply the content for each city as an attribute.
//add shortcode to post/page content
[geo orlando="555-123-6349" raleigh="919-999-9999" default="Custom default text here"]
//your function should be
function geo_services( $atts , $content = null ) {
//don't use extract since we expect X number of atts now
$atts = shortcode_atts(array(
'default' => 'Default text here'
), $atts);
//
require_once('geoplugin.class.php');
//
$geoplugin = new geoPlugin();
$geoplugin->locate();
//was the city provided as an attribute?
if( isset($atts[ strtolower($geoplugin->city) ]) ) {
return $atts[ strtolower($geoplugin->city) ];
}else {
return $atts['default'];
}
}
add_shortcode( 'geo', 'geo_services' );
You may have to get creative with the HTML portion of the content, but now you can include X number of cities, with their custom content, in the shortcode itself. If the city is not supplied, or does not match, it will fallback to the default.
This question already has answers here:
WooCommerce: Set country by default in checkout page
(5 answers)
Closed 2 years ago.
in the checkout of my Woocommerce-Shop is a dropdown to choose your country.
On default the USA is automatically selected already.
How to just have a placeholder with “select your country” instead?
I couldn’t find any solution to this topic somebody have any idea?
I changed the other Placeholders which aren't Dropdowns but are inside the same form:
add_filter( 'woocommerce_checkout_fields' , 'override_billing_checkout_fields', 20, 1 );
function override_billing_checkout_fields( $fields ) {
$fields['billing']['billing_first_name']['placeholder'] = 'First Name*';
$fields['billing']['billing_last_name']['placeholder'] = 'Last Name*';
$fields['billing']['billing_city']['placeholder'] = 'Town / City*';
$fields['billing']['billing_postcode']['placeholder'] = 'ZIP*';
$fields['billing']['billing_email']['placeholder'] = 'Email Address*';
return $fields;
}
My poor solution for now is: I created a new "Country in the Dropdown List" which I just named: select your country* and then just selected it on default instead of the USA. But the problem is here that the system thinks a real country is chosen already so it's not a mandatory field anymore and also the fact that it just doesn't look usual for the user when they choose their country:
function woo_add_my_country( $country ) {
$country["PLACE"] = 'select your country*';
return $country;
}
add_filter( 'woocommerce_countries', 'woo_add_my_country', 10, 1 );
add_filter( 'default_checkout_billing_country', 'bbloomer_change_default_checkout_country' );
function bbloomer_change_default_checkout_country() {
return 'PLACE';
}
I would appreciate any help or tips!
This is working for my side try this
// Change the default country and state on checkout page.
// This works for a new session.
add_filter( 'default_checkout_country', 'xa_set_default_checkout_country' );
add_filter( 'default_checkout_state', 'xa_set_default_checkout_state' );
function xa_set_default_checkout_country() {
// Returns empty country by default.
return null;
// Returns India as default country.
// return 'IN';
}
function xa_set_default_checkout_state() {
// Returns empty state by default.
return null;
// Returns Madhya Pradesh as default state.
// return 'MP';
}
function woo_add_my_country( $country ) {
$country["PLACE"] = 'select your country*';
return $country;
}
add_filter( 'woocommerce_countries', 'woo_add_my_country', 10, 1 );
add_filter( 'default_checkout_billing_country', 'bbloomer_change_default_checkout_country' );
function bbloomer_change_default_checkout_country() {
return 'PLACE';
}
Just go to WooCommerce > Settings.
On General tab you will find Default customer location. Set it to No location by default
This was one of the first results that popped up for me when searching how to set a placeholder for a select field on the Woocommerce checkout page, so for any future visitors:
I have a company select field that I populate dynamically with values from the database. In order to set a placeholder value, I just add an option with a blank value.
add_filter( 'woocommerce_checkout_fields' , 'populate_company_field' );
function populate_company_field($fields) {
$results = get_results_from_database();
$options[''] = __('Choose your company', 'gs'); //add blank value = placeholder
foreach ($results as $result) {
if (!empty($result->company)) {
$options[$result->ID] = $result->company;
}
}
$fields['billing']['company']['options'] = $options;
return $fields;
}
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
In Gutenberg Editor, I try to modify the categories panel (the one on the right where I choose the categories my post will be placed into).
One should not be able to add a post to a category if that category has child-categories. As the categories are static, it'll be ok to use the category-id.
My idea was to use the enqueue_block_editor_assets and add some javascript to disable the checkbox via the ID of the element.
This does not work, the element could not be found :-(
This is my unfunctional code so far:
functions.php:
function gutenberg_enqueue()
{
wp_enqueue_script(
'gutenberg-additions-script',
get_stylesheet_directory_uri().'/gutenberg-additions.js',
array(), true, true
);
}
add_action('enqueue_block_editor_assets', 'gutenberg_enqueue', 999);
(I use get_stylesheet_directory_uri(), because I am in a child theme)
gutenberg-additions.js:
window.onload = function () {
var cat1 = document.getElementById('editor-post-taxonomies-hierarchical-term-1');
if (cat1 != null) {
cat1.disabled = true;
}
Welcome to Stackoverflow. There is an example about that in the gutenberg github directory. It is written in the old es5 syntax, but should easily be transferrable to esnext. It uses the editor.PostTaxonomyType filter to edit the taxonomies component.
var el = wp.element.createElement;
function customizeProductTypeSelector( OriginalComponent ) {
return function( props ) {
if ( props.slug === 'product-type' ) {
return el(
'div',
{},
'Product Type Selector'
);
} else {
return el(
OriginalComponent,
props
);
}
}
};
wp.hooks.addFilter(
'editor.PostTaxonomyType',
'my-custom-plugin',
customizeProductTypeSelector
);
If you need more information, also read the comments on this github issue.
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.