Wrapper class: How to get rid of call_user_func_array() warning?

I have several installations of wordpress and now im trying to create my own small framework so I can create and maintain my themes more efficiently. What I would like to do is to have a wrapper for the hooks that wordpress offer.

I would like to call hooks like this in my application

$_addThumb = function(){
add_theme_support('post-thumbnails');
};

 $core->registerAction(array('tag' => 'after_theme_setup', 
                             'callback' => $_redirect
                             ));

In my class I handle the logic like this (this is a snippet, the whole code is below)

    if (!empty($this -> _actions)) {
        foreach ($this->_actions as $action) {
            add_action($action[0], array($this, call_user_func($action[1])));
        }
    }

The problem is that if I add the $this keyword to the add_action call like this …

add_action($tag, array($this, $callback))  

… I get this warning:

Warning: call_user_func_array() expects parameter 1 to be a valid callback, second array member is not a valid method in Z:\Website\wp-includes\plugin.php

And if I don’t add it like this …

add_action($tag, $callback)

Then I get this notice:

Undefined offset: 0 in Z:\Website\wp-includes\plugin.php

On both scenarios everything works though. I just would like to understand why is this happening and at least get rid of the warning.

Here is my complete code:

class Core {

/**
 * theme features
 */
protected $_features = array();
private $_actions = array();


/**
 * register extra functions so you can add actions to the theme
 *@param array mixed
 */
public function registerAction($args) {

    if (!is_array($args)) {
        $args = func_get_args();
    }
    if (count($args) < 2) {
        throw new InvalidArgumentException(sprintf('Not enough arguments(registerCallback needs at least two arguments): %s.', print_r($args, true)));
    }
    $arg_list = array_values($args);

    /**
     * sets the default priority
     */
    if (!isset($arg_list[2])) {
        $arg_list[2] = 10;
    }
    /**
     * sets default args
     */
    if (!isset($arg_list[3])) {
        $arg_list[3] = 0;
    }

    if (!is_callable($arg_list[1])) {
        throw new Exception("callback not callable : Core:13");
    }

    $this -> _actions[] = $arg_list;

}

/**
 * TODO: development only
 */
public function get_actions() {
    echo "<pre>";
    print_r($this -> _actions);
    echo "</pre>";
}

/**
 * set theme features
 * 'post-formats'
 * 'post-thumbnails'
 * 'custom-background'
 * 'custom-header'
 * 'automatic-feed-links'
 * 'menus'
 * @param string (required) name of the feature to be added
 * @param array (optional) optional arguments
 */
public function set_feature($feature, $options = array()) {

    if (is_array($options) && !empty($options)) {
        $this -> _features[]['args'] = array($feature, $options);
    } else {
        $this -> _features[]['name'] = $feature;
    }
}

public function get_features() {
    return $this->_features;
}

function __construct() {

}

public function init($tag = '', $function = '') {
    add_action('after_setup_theme', array($this, 'initial_setup'));

    if (!empty($this -> _actions)) {
        foreach ($this->_actions as $action) {
            add_action($action[0], array($this, call_user_func($action[1])), $action[2], $action[3]);
        }
    }
}

public function initial_setup() {

    // check if we have ay features so we can add them to our theme
    if (!empty($this -> _features)) {
        foreach ($this->_features as $feature) {
            if (isset($feature['args'])) {
                add_theme_support($feature['args'][0], $feature['args'][1]);
            } else {
                add_theme_support($feature['name']);
            }
        }
    }
}

}

my functions.php

$core = new Core();

$core->set_feature('automatic-feed-links');

$core->set_feature('post-formats', array('aside',
                                         'image',
                                         'link',
                                         'quote',
                                         'status',
                                         'gallery',
                                         'video' ));
$_addThumb = function(){
    add_theme_support('post-thumbnails');
};

$_sidebars = function() {
    register_sidebar( array(
        'name'          => __( 'Main Widget Area', 'twentythirteen' ),
        'id'            => 'sidebar-1',
        'description'   => __( 'Appears in the footer section of the site.', 'twentythirteen' ),
        'before_widget' => '<aside id="%1$s" class="widget %2$s">',
        'after_widget'  => '</aside>',
        'before_title'  => '<h3 class="widget-title">',
        'after_title'   => '</h3>',
    ) );

    register_sidebar( array(
        'name'          => __( 'Secondary Widget Area', 'twentythirteen' ),
        'id'            => 'sidebar-2',
        'description'   => __( 'Appears on posts and pages in the sidebar.', 'twentythirteen' ),
        'before_widget' => '<aside id="%1$s" class="widget %2$s">',
        'after_widget'  => '</aside>',
        'before_title'  => '<h3 class="widget-title">',
        'after_title'   => '</h3>',
    ) );
};

$_adminHead = function(){

echo '<style>[for="wp_welcome_panel-hide"] {display: none !important; } #normal-sortables{display:none !important;}</style>';

};

/** i don't get a notiche with this **/
$core->registerAction(array('tag' => 'after_theme_setup', 'callback' => $_addThumb));

/** it works but i get this warning 
 * arning: call_user_func_array() expects parameter 1 to be a valid callback, second array member is not a valid method in Z:\Armen Website\wp-includes\plugin.php on line
 */
$core->registerAction(array('tag' =>'admin_head', 'callback' => $_adminHead));
$core->registerAction(array('tag' => 'widgets_init', 'callback' => $_sidebars));
$core->init();

2 Answers
2

As you have noticed already, $this will not work as you expected prior to PHP 5.4. You can read this in the PHP wiki. The reason:

For PHP 5.3 $this support for Closures was removed because no consensus could be reached how to implement it in a sane fashion. This RFC describes the possible roads that can be taken to implement it in the next PHP version.

An easy workaround is to simple copy $this up front, then use the new reference/ variable:

$subject = clone $this;

Leave a Comment