I have a class sitting in my Wordpress functions.php. Eventually it's going to end up in the plugins folder but one step at a time. Below is a foreshortened version of it:
class metaboxClass {
$them_meta_boxes = array (
array (
"1a_myplugin_box_id_1",
"1b_Custom Meta Box Title 1"
),
array (
"2a_myplugin_box_id_2",
"2b_Custom Meta Box Title 2"
)
);
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
}
public function add_meta_box( $post_type ) {
$post_types = array( 'page', 'my_cpt' );
if ( in_array( $post_type, $post_types )) { // *** IF $POST_TYPE IS IN THE ARRAY $POST_TYPES
foreach ($this->them_meta_boxes as $level_1) {
add_meta_box (
foreach ($this->level_1 as $level_2) {
echo $level_1 . ",";
}
array( $this, 'render_form'),
$post_type
)
}
}
}
}
As you can see from the above, I'm trying to construct various iterations of the add_meta_boxes function using the information in the array.
I've a feeling that there are a number of issues here and I'm kind of going through them one at a time but the first is that when an object is instantiated from the class I get: "syntax error, unexpected 'foreach' ". I know this is usually caused by a missing semi-colon. In this case the semi colon is present and correct. I've a feeling it's something to do with the placement of the array but I'm getting similar problems when it's placed outside. Can anyone give me any pointers - I'm pretty new to the world of OO PHP and also to really getting my hands dirty with the wordpress backend so any pointers would be appreciated.
Thanks in advance,
Stef
You can't pass a foreach loop as a parameter to a function. Construct your argument string first and then pass the constructed string as an argument to your add_meta_box function.
Even then though, I'm not sure what you are trying to call since your add_meta_box function only takes one argument.
Got it sorted for the record... ended up something like this:
class initialise_meta_boxes {
public $meta_boxes_array = array (
array (
"1a_myplugin_box_id_1",
"1b_Custom Meta Box Title 1",
"render_dropdown"
),
array (
"2a_myplugin_box_id_2",
"2b_Custom Meta Box Title 2",
"render_dropdown"
)
);
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
add_action( 'save_post', array( $this, 'save' ) );
}
public function make_meta_box($meta_id, $meta_title, $meta_callback) {
return add_meta_box ($meta_id, $meta_title, $meta_callback, $post_type );
}
public function add_meta_box( $post_type ) { // *** $post_type is global variable!!!
$post_types = array( 'page', 'my_cpt' );
if ( in_array( $post_type, $post_types )) { // *** IF $POST_TYPE IS IN THE ARRAY $POST_TYPES
foreach ($this->meta_boxes_array as $value) {
$this->make_meta_box($value[0], $value[1], array( $this, $value[2]));
}
}
}
}
Related
Issue: How should I go for a conditional "move to trash" action? It means that delete a particular post only when a certain condition is met. Otherwise, prompt user that this can't be done.
Things I've tried: I am calling a function on pre_trash_hook and checking my condition. But I'm not sure how to stop WordPress from not moving forward with further "move to trash" action. Here's the code for reference.
public function register_pre_trash_handler( $product_post_type, $product_comparator_type_meta_key ) {
$this->product_post_type = $product_post_type;
$this->product_comparator_type_meta_key = $product_comparator_type_meta_key;
add_filter( "pre_trash_post", array( $this, "safe_comparator_trash_cb" ), 10, 2 );
}
public function safe_comparator_trash_cb( $should_trash, $post ) {
$product_posts = get_posts( array(
"post_type" => $this->product_post_type,
"meta_key" => $this->product_comparator_type_meta_key,
"meta_value" => $post->ID
) );
if ( ! empty( $product_posts ) ) { // this is the condition. If products exist, don't move the comparator to trash
$should_trash = null;
}
}
FYI, not a big fan of PHP and never used it other than tinkering WordPress themes.
Try with wp_trash_post hook.
add_action('wp_trash_post', 'prevent_from_trash');
public function prevent_from_trash($post_id) {
if (! empty( $product_posts )) { // your condition
wp_redirect(get_home_url() . "/wp-admin/edit.php?post_type=" . $custom_post_type);
die();
}
}
This solution only prevents trashing the post but does not gives any warning, nor notice that it does not want to trash the post.
Have you got an idea how to remove actions or filters in Wordpress (from a plugin in my case) when those are defined like so:
add_action('action_tag', function(){...});
or
add_filter('filter_tag', function(){...});
They are defined inside the function add_action or add_filter so I have no clue witch 'function_name' I should use to remove it.
remove_action($tag, what am I supposed to put in here?, $priority);
You are talking about anonymous functions. To remove anonymous functions from filters or actions, you have to use the same function body and priority you used when they were added like so:
// Add it.
add_filter( 'tag', function ( $param ) {
return $param;
}, 10, 1 );
// Remove it.
remove_filter( 'tag', function ( $param ) {
return $param;
}, 10 );
try this.. This will delete all hooks that are anonymous functions
global $wp_filter;
foreach ( $wp_filter as $filter_name => $filter_properties ):
foreach ( $filter_properties->callbacks as $priority ):
foreach( $priority as $function ):
if( is_object( $function["function"] ) == true ):
unset( $wp_filter[ $filter_name ] );
endif;
endforeach;
endforeach;
endforeach;
I'm trying to override a plugin class on a WordPress plugin.
Here is the original plugin class :
class WCV_Vendor_Dashboard
{
/**
* __construct()
*/
function __construct()
{
add_shortcode( 'wcv_shop_settings', array( $this, 'display_vendor_settings' ) );
add_shortcode( 'wcv_vendor_dashboard', array( $this, 'display_vendor_products' ) );
add_action( 'template_redirect', array( $this, 'check_access' ) );
add_action( 'init', array( $this, 'save_vendor_settings' ) );
}
public function save_vendor_settings(){
//some codes here
}
}
Here is what I'm trying (in functions.php), but it doesn't work :
$wcv_vendor_dashboard = new WCV_Vendor_Dashboard();
global $wcv_vendor_dashboard;
remove_action( 'init', array( $wcv_vendor_dashboard , 'save_vendor_settings' ) );
How to remove it correctly and how to create the replacement?
Additional info:
I did similar thing on the WooCommerce core. When I want to override a class / function, I use this (for example):
remove_action( 'template_redirect', array( 'WC_Form_Handler', 'save_account_details' ) );
function new_save_account_details() {
//custom code here
}
add_action( 'template_redirect', 'new_save_account_details' );
It's working properly on WooCommerce core. I tried something similar on WCV_Vendor_Dashboard but it doesn't work.
Why it was working with woocommerce, but it does not work in this case?
When you attach a function on to a specific action, WoredPress creates unique id for that callback and stores that in global $wp_filter array ( in fact, it was an array before, but now it is an object ). For object method callbacks ( like array( $this, 'save_vendor_settings' ) ), the id is generated with spl_object_hash php function. For the above example,
spl_object_hash( $this ) . 'save_vendor_settings'
, and it looks like 000000001c0af63f000000006d7fe83asave_vendor_settings.
To "legally" remove the object method with remove_action() you will need to have access to the original object that was used to attach the function in the first place. If the object exists in global namespace:
global $wcv;
remove_action( 'init', array( $wcv, 'save_vendor_settings' ) );
Creating another class instance will not work because the generated id is unique for each object, even if they are instances of the same class.
In the case of WooCommerce I guess it was about static class methods. Different logic is used to generate the ids for static class methods, functions and static method callbacks are just returned as strings. For your example it would be:
'WC_Form_Handler' . '::' . 'save_account_details'
You see why it works for one case, but not for the other.
There is a hack to replace functions attached by replacing them directly in global $wp_filter object, but it's not 100% reliable. Since we do not have access to the original object, we can only filter $wp_filter by the name of the function, if there are identical names for the same action it will replace wrong handlers.
global $wp_filter;
foreach ( $wp_filter['init']->callbacks as $priority => &$callbacks ) {
foreach ( $callbacks as $id => &$callback ) {
if ( substr( $id, -strlen( 'save_vendor_settings' ) ) === 'save_vendor_settings' ) {
// replace the callback with new function
$callback['function'] = 'new_save_vendor_settings';
}
}
}
I hope it will work, greetings.
Example for child class
class WCV_Vendor_Dashboard_Child extends WCV_Vendor_Dashboard
{
/**
* __construct()
*/
function __construct()
{
parent::__construct();
}
public function new_save_vendor_settings(){
//some codes here
}
}
I'm trying to mod a wordpress plugin to take custom categories. So when the random_post_link is called, I can add the custom category by using random_post_link('Random Link',3). 3 being the category name.
How does the plugin below create a new object of class Random_Post_Link? I thought you created new objects by doing something like:
$a = new random_post_link;
But I don't see that in the plugin. I think it creates the new object in the init function by using a hook:
add_action('init', array(CLASS, 'jump'));
If that's the case, how can I add parameter to jump function?
I think I know how add_action works, the second parameter should be the function name, how does
" array(CLASS, 'jump')" work?
Here's the full code for the plugin:
function random_post_link($text = 'Random Post',$the_cat = 36) {
printf('%s', get_random_post_url(), $text);
$the_category = $the_cat;
}
function get_random_post_url() {
return trailingslashit(get_bloginfo('url')) . '?' . Random_Post_Link::query_var;
}
class Random_Post_Link {
const query_var = 'random';
const name = 'wp_random_posts';
public $the_category;
function init() {
add_action('init', array(__CLASS__, 'jump'));
// Fire just after post selection
add_action('wp', array(__CLASS__, 'manage_cookie'));
}
// Jump to a random post
function jump() {
if ( ! isset($_GET[self::query_var]) )
return;
$args = apply_filters('random_post_args', array(
'post__not_in' => self::read_cookie(),
));
$args = array_merge($args, array(
'orderby' => 'rand',
'cat' => $the_category,
'showposts' => 1,
));
$posts = get_posts($args);
if ( empty($posts) ) {
self::update_cookie(array());
unset($args['post__not_in']);
$posts = get_posts($args);
}
if ( empty($posts) )
wp_redirect(get_bloginfo('url'));
$id = $posts[0]->ID;
wp_redirect(get_permalink($id));
die;
}
// Collect post ids that the user has already seen
function manage_cookie() {
if ( ! is_single() )
return;
$ids = self::read_cookie();
$id = $GLOBALS['posts'][0]->ID;
if ( count($ids) > 200 )
$ids = array($id);
elseif ( ! in_array($id, $ids) )
$ids[] = $id;
self::update_cookie($ids);
}
private function read_cookie() {
return explode(' ', #$_COOKIE[self::name]);
}
private function update_cookie($ids) {
setcookie(self::name, trim(implode(' ', $ids)), 0, '/');
}
}
Random_Post_Link::init();
Some WordPress authors use the Class structure in PHP to basically reduce global vars. The class is meant as a 'singleton' of sorts, and so it isn't usually instantiated (that code calls Random_Post_Link::init(); at the bottom instead). The class functions are treated as Class members, not instance members, sort of like Math.max() in other languages, for example.
The __CLASS__ php keyword is simply a token for the current class, so when passed, the callable becomes Random_Post_Link::method() or array( 'Random_Post_Link', 'method' )
If you need to unhook, try remove_action( 'init', array( 'Random_Post_Link, 'jump' ) );
(Also note, that methods used that way should be declared static function jump() {...})
P.S. To further clarify:
http://php.net/manual/en/language.types.callable.php
The array('class', 'function') syntax is a PHP thing, while WordPress actions expect a callable which could be any of the PHP callable things.
I'm trying to use a widget within a plugin in wordpress and I'm seeing this error within the widget box:
Warning: extract() [function.extract]: First argument should be an array in /nfs/c03/h04/mnt/57957/domains/rab.qbessi.com/html/wp-content/plugins/register-plus/dash_widget.php on line 24
This is the code from Line 24:
// Output the widget contents
function widget( $args ) {
extract( $args, EXTR_SKIP );
Here's the dash_widget.php code
<?php
if( !class_exists('RegisterPlusWidget') ){
class RegisterPlusWidget{
function RegisterPlusWidget() { //contructor
// Add the widget to the dashboard
add_action( 'wp_dashboard_setup', array($this, 'register_widget') );
add_filter( 'wp_dashboard_widgets', array($this, 'add_widget') );
}
function register_widget() {
wp_register_sidebar_widget( 'regplus_invite_tracking', __( 'Invitation Code Tracking', 'regplus' ), array($this, 'widget'), array( 'settings' => 'options-general.php?page=register-plus' ) );
}
// Modifies the array of dashboard widgets and adds this plugin's
function add_widget( $widgets ) {
global $wp_registered_widgets;
if ( !isset($wp_registered_widgets['regplus_invite_tracking']) ) return $widgets;
array_splice( $widgets, 2, 0, 'regplus_invite_tracking' );
return $widgets;
}
// Output the widget contents
function widget( $args ) {
extract( $args, EXTR_SKIP );
echo $before_widget;
echo $before_title;
echo $widget_name;
echo $after_title;
global $wpdb;
$regplus = get_option( 'register_plus' );
$codes = $regplus['codepass'];
$usercodes = array();
foreach($codes as $code){
$users = $wpdb->get_results( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key='invite_code' AND meta_value='$code'" );
echo '<h3>' . $code . ': <small style="font-weight:normal">' . count($users) . ' Users Registered.</small></h3>';
}
echo $after_widget;
}
}
} # End Class RegisterPlusWidget
// Start this plugin once all other plugins are fully loaded
add_action( 'plugins_loaded', create_function( '', 'global $regplus_widget; $regplus_widget = new RegisterPlusWidget();' ) );
?>
The widget() function is being called with no parameters. Why, is hard to tell without digging deeply into the plugin. You should ask the plugin's author.
You can try adding
// Output the widget contents
function widget( $args ) {
if (is_array($args)) // Add this
extract( $args, EXTR_SKIP );
and see whether the output still makes sense then. That effectively just suppresses the action that causes the warning. If it's a badly programmed plugin that was developed with warnings turned off, that already may do the trick.
google launched new plugin called site kit, it will make analyzing work much more easier.
https://wordifact.com/google-site-kit/