Problems adding action links to WordPress plugin? - wordpress

I'm trying to add some action links to a WordPress plugin. I started with the following.
class Angelleye_PayPal_WooCommerce
{
public function __construct()
{
add_filter('plugin_action_links', array($this,'plugin_action_links'));
}
public function plugin_action_links($actions)
{
$custom_actions = array(
'configure' => sprintf( '%s', admin_url( 'admin.php?page=wc-settings&tab=checkout' ), __( 'Configure', 'paypal-for-woocommerce' ) ),
'docs' => sprintf( '%s', 'http://docs.angelleye.com/paypal-for-woocommerce/', __( 'Docs', 'paypal-for-woocommerce' ) ),
'support' => sprintf( '%s', 'http://www.angelleye.com/contact-us/', __( 'Support', 'paypal-for-woocommerce' ) ),
'review' => sprintf( '%s', 'http://wordpress.org/support/view/plugin-reviews/paypal-for-woocommerce', __( 'Write a Review', 'paypal-for-woocommerce' ) ),
);
// add the links to the front of the actions list
return array_merge( $custom_actions, $actions );
}
}
This works except that it puts the links on every single plugin that's currently enabled instead of just my own. I'm looking at the WordPress codex info about this, and it shows to use the filename appended to the filter name. So I made the adjustment like this:
add_filter('plugin_action_links_'.__FILE__, array($this,'plugin_action_links'));
When I do that, though, all of the links go away altogether and they don't show up anywhere, not even my own. What am I doing wrong here?

As explained by Akshay, we need to use the plugin_basename as suffix for the hook. But for completeness, a couple of missing details.
The hook can also take a prefix to show the action links in the Network screen of a Multisite installation:
$basename = plugin_basename( __FILE__ );
$prefix = is_network_admin() ? 'network_admin_' : '';
add_filter(
"{$prefix}plugin_action_links_$basename",
array( $this,'plugin_action_links' ),
10, // priority
4 // parameters
);
The hook takes 4 parameters, which may contain useful information for building the links:
public function plugin_action_links( $actions, $plugin_file, $plugin_data, $context )
{
// $plugin_file is the plugin_basename
// $plugin_data contains the plugin's header information
// $context is the current screen (all: All plugins, active: Active plugins)
}
If we use the hook without the basename suffix, we can use the $plugin_file param to filter out only our plugin(s).

Use plugin_basename( __FILE__ ) instead of __FILE__.
Use following filter to add action links.
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array($this, 'plugin_action_links') );
I had working this filter in one of my plugin, hope its work for you too.

use &$this instead of $this,
add_filter('plugin_action_links_' . $this->plugin_file, array(&$this, 'settings_links'), 10, 1);

Related

Media Modal Gutenberg missing styles

So today, all my websites were updated to the new release of WordPress 5.9.1. Good good. However, my custom blocks in Gutenberg that are containing an image element are breaking the style of the media modal (where you can add an image directly in the post).
I started a new project, just to test if it was my theme, or the plugins, but even without any plugin (except ACF Pro) and on the Twenty Twenty-Two theme, if I add my registration code in the functions.php file of 2022 theme, I get the same problem.
Here's the register-block code:
add_action('acf/init', 'my_acf_init_block_types');
function my_acf_init_block_types() {
if( function_exists('acf_register_block_type') ) {
acf_register_block_type(array(
'name' => 'carousel',
'title' => __('Carrousel'),
'description' => __(''),
'render_template' => 'web/blocks/carousel.php',
'category' => 'custom-blocks',
'icon' => 'images-alt',
'keywords' => array( 'carousel', 'carrousel'),
'supports' => array( 'anchor' => true),
));
}
}
And I've created a Field group trying the image with the array annnnnd the one using only the URL.
What I tried:
no plugins (except ACF)
WP theme (2022)
custom theme with no functions
adding the registration code to 2022 theme (same error)
Please, help a sister our here.
I think it was cause by the 5.9.1 update
You can use this in functions.php as temporary fix
function fix_media_views_css() {
echo '<link rel="stylesheet" id="fix-media-views-css" href="'.get_bloginfo('url').'/wp-includes/css/media-views.min.css?ver=5.9.1" media="all">';
}
add_action('admin_footer', 'fix_media_views_css');
I've added that piece of code to my functions.php file (at the end, no biggy).
function acf_filter_rest_api_preload_paths( $preload_paths ) {
if ( ! get_the_ID() ) {
return $preload_paths;
}
$remove_path = '/wp/v2/' . get_post_type() . 's/' . get_the_ID() . '?context=edit';
$v1 = array_filter(
$preload_paths,
function( $url ) use ( $remove_path ) {
return $url !== $remove_path;
}
);
$remove_path = '/wp/v2/' . get_post_type() . 's/' . get_the_ID() . '/autosaves?context=edit';
return array_filter(
$v1,
function( $url ) use ( $remove_path ) {
return $url !== $remove_path;
}
);
}
add_filter( 'block_editor_rest_api_preload_paths', 'acf_filter_rest_api_preload_paths', 10, 1 );
It works perfectly like before. I've tried to downversion it to 5.9 and it worked as well, but it takes more time/effort and many mistakes can happen.
Hope it helps more than one.
ACF is aware of the issue: https://github.com/AdvancedCustomFields/acf/issues/612
Here is the temp fix, paste in your functions.php:
function acf_filter_rest_api_preload_paths( $preload_paths ) {
global $post;
$rest_path = rest_get_route_for_post( $post );
$remove_paths = array(
add_query_arg( 'context', 'edit', $rest_path ),
sprintf( '%s/autosaves?context=edit', $rest_path ),
);
return array_filter(
$preload_paths,
function( $url ) use ( $remove_paths ) {
return ! in_array( $url, $remove_paths, true );
}
);
}
add_filter( 'block_editor_rest_api_preload_paths', 'acf_filter_rest_api_preload_paths', 10, 1 );

Need to Change Sale Badge Text in WooCommerce

The following works for the Product page but it does not work for the Shop page.
<?php
add_filter('woocommerce_sale_flash', 'woocommerce_custom_sale_text', 10, 3);
function woocommerce_custom_sale_text($text, $post, $_product)
{
return '<span class="onsale">PUT YOUR TEXT</span>';
}
Please suggest modifications.
Thanks!
Use This
add_filter( 'woocommerce_sale_flash', 'wooc_custom_replace_sale_text' );
function wooc_custom_replace_sale_text( $html ) {
return str_replace( __( 'Sale!', 'woocommerce' ), __( 'Your Text', 'woocommerce' ), $html );
}
I tried your code and it works perfectly for the shop page as well. You may try increasing the priority or it can be a conflict with some other plugin or theme.
You may also check the following file to confirm it has applied the woocommerce_sale_flash filter
woocommerce\templates\loop\sale-flash.php

Woocommerce ajax call on single product page

I get all my products from an API and those who are variations to each other all share a custom meta key called "api_product_family". The products with the same api_product_family are variants to each other, so on the single page I have a hook where I display the other variants with image and anchor to it's variants.
My code:
function mv_variations() {
global $post;
global $wpdb;
$product_id = $post->ID;
$product_family = get_post_meta( $post->ID, 'api_product_family', true );
if(!empty($product_family)) {
$query = "
SELECT post_id
FROM " . $wpdb->prefix . "postmeta
WHERE meta_value = '" . $product_family . "'
";
$products = $wpdb->get_col($query);
if(count($products) > 0) {
for($i=0; $i<count($products); $i++) {
if($products[$i] == $product_id) {
unset($products[$i]);
}
}
if(count($products) > 0) {
print '<h3>Choose other variants: </h3>';
foreach($products as $product) {
$image = wp_get_attachment_image_src(get_post_thumbnail_id($product));
print '<img src="' . $image[0] . '" alt="img"/> ';
}
}
}
}
}
add_action( 'woocommerce_single_product_summary', 'mv_variations' );
The problem:
I have a LOT of posts, and a lot of post_meta's, so it's taking an eternity to load so I was thinking to move this whole function inside and AJAX call so it's doesn't slow down the initial load. The problem is that I have no idea how to do that with wordpress
Are you simply looking to run a WP function via AJAX?
1) Add ajax actions
This needs to run inside the main plugin file. If you run this only on the public code, it will not work. WP is a little weird and all ajax uses admin-ajax.php
if ( wp_doing_ajax() ){
add_action( 'wp_ajax_yourcustomfunction', array($this, 'yourcustomfunction') );
add_action( 'wp_ajax_nopriv_yourcustomfunction', array($this, 'yourcustomfunction') );
}
function yourcustomfunction(){
echo 'success';
exit();
}
2) In JavaScript
in the backend, you have the global: ajaxurl for the ajax url
BUT in the front end you need to pass this as a variable via wp_localize_script
$datatoBePassed = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
);
wp_localize_script( 'your_javascript_script', 'plugin_display_settings', $datatoBePassed );
In JS:
var datavar = {
action: 'yourcustomfunction',
};
$.post(plugin_display_settings.ajaxurl, datavar, function(response){
//response received here. It will be 'success' which is echoed in PHP
});
3)
If you also want to run a security nonce check (to check the request truly originates from the WP website, prevents some attacks), it gets a little more complicated:
$datatoBePassed should also include 'security' => wp_create_nonce( 'yourplugin_security_nonce' ),
datavar in JS includes security: plugin_display_settings.security,
Finally, your PHP custom function begins with:
// Check security nonce.
if ( ! check_ajax_referer( 'yourplugin_security_nonce', 'security' ) ) {
wp_send_json_error( 'Invalid security token sent.' );
wp_die();
}
// If security check passed, run further
So I think you might get better performance using WP_Query. Below I converted what you have into a custom WP_Query. May need some slight adjustment but should be the right direction.
function mv_variations() {
global $post_id;
// get current post "product family"
$product_family = get_post_meta( $post_id, 'api_product_family', true );
// build related "product family" products query
$products_query_args = array(
'post_type' => 'product', // may need to update this for your case
'posts_per_page' => -1, // return all found
'post__not_in' => array($post_id), // exclude current post
'post_status' => 'publish',
// use a meta query to pull only posts with same "product family" as current post
'meta_query' => array(
array(
'key' => 'api_product_family',
'value' => $product_family,
'compare' => '='
)
)
);
$products_query = new WP_Query($products_query);
// use "the loop" to display your products
if ( $products_query->have_posts() ) :
print '<h3>Choose other variants: </h3>';
while ( $products_query->have_posts() ) : $products_query->the_post();
print ''. wp_get_attachment_image() .'';
endwhile;
// restore global post
wp_reset_postdata();
endif;
}
add_action( 'woocommerce_single_product_summary', 'mv_variations' );

woocommerce failed to load resource

add_action( 'admin_menu', array($this, 'admin_menu'), 100 );
public function admin_menu() {
$page = add_submenu_page( 'edit.php?post_type=product', __( 'ajaxmain' ), __( 'ajaxmainagain' ), apply_filters( 'woocommerce_csv_product_role', 'manage_woocommerce' ), 'ajaxmain-product', array( $this, 'output' ) );
}
public function output() {
include( 'ajaxmain.php' );
}
i have attached 2 screenshots. it goes and adds ajaxmainagain to the submenu. when i click on it, it loads ajaxmain.php. however it fails to load stylesheets, scripts. the scripts and stylesheets are in the same directory as ajaxmain.php. it is looking for scripts and stylesheets in wp-admin directory. thanks for the help. unable to find resource http://localhost/wordpress/wp-admin/ajax1.php?stateofmachine=xm234jq&q=2. the resource is in plugins directory.
You need to load your style/script like this.
wp_register_style('custom-style', plugins_url("/path/to/style.css"), '', true );
wp_enqueue_style('custom-style');
wp_register_script('custom-script', plugins_url("/path/to/script.js"), '', true );
wp_enqueue_script('custom-script');
and with this plugin_url you will get the path till your plugin directory like eg.
http://localhost/wordpress/wp-content/plugins/sample-plugin/

How to manage selected post-formats in custom post type

'supports' => array('title','author','post-formats'),
Now display all types of post-formats but i want to display only selected.
like : link,audio,video
I wants to something like this:
you can do it like this :
add_theme_support( 'post-formats', array( 'link', 'audio', 'video' ) );
By default it adds all of the registered formats, but like this, you can choose which to add
You can read about the different formats, and how to add them, in the codex : Codex
EDIT :
If you are working with a child theme, and never want to use the other formats, you can call this :
add_action( 'after_setup_theme', 'childtheme_formats', 11 );
function childtheme_formats(){
add_theme_support( 'post-formats', array( 'aside', 'gallery', 'link' ) );
}
EDIT :
According to the comment, you only want this on a single post type :
Then you can do like this :
<?php add_post_type_support( $post_type, $supports ) ?>
Where $support can be a string or an array : so in your task :
So you might be able to do something like this:
function test_add_formats_support_for_cpt() {
add_post_type_support( 'yourCustomPostType', 'post-formats', array('link', 'audio', 'video') );
}
add_action( 'init', 'test_add_formats_support_for_cpt' );
This is untested, so I am not sure if it works - let me know
You can limit or manage the custom post type formats by overwriting the default post formats.
create a function that will return an array of the post formats that our post type supports like audio, gallery, image, and video.
function customposttype_allowed_formats() {
return array( 'audio', 'gallery', 'image', 'video' );
}
We will use "theme support" system and change the theme-supported format and will limit to our post types dashboard screens so that it won’t mess with other post types
add_action( 'load-post.php', 'support_customposttype_filter' );
add_action( 'load-post-new.php', 'support_customposttype_filter' );
add_action( 'load-edit.php', 'support_customposttype_filter' );
function support_customposttype_filter() {
$screen = get_current_screen();
// Return if not customposttype screen.
if ( empty( $screen->post_type ) || $screen->post_type !== 'custom_post_type' )
return;
// Check theme supports formats.
if ( current_theme_supports( 'post-formats' ) ) {
$formats = get_theme_support( 'post-formats' );
// If we have formats, add theme support for only the allowed formats.
if ( isset( $formats[0] ) ) {
$new_formats = array_intersect( $formats[0], customposttype_allowed_formats() );
// Remove post formats support.
remove_theme_support( 'post-formats' );
// If the theme supports the allowed formats, add support for them.
if ( $new_formats )
add_theme_support( 'post-formats', $new_formats );
}
}
// Filter the default post format.
add_filter( 'option_default_post_format', 'customposttype_format_filter', 95 );
}
There is a filter on the default post format at the end here we can overwrite the default post formats if it's not one of the approved formats (audio, gallery, image, and video).
function customposttype_format_filter( $format ) {
return in_array( $format, customposttype_allowed_formats() ) ? $format : 'standard';
}

Resources