13

Up until around 3.3beta1 items in the WP_Admin_Bar Object could be accessed using this type of syntax, for example to change the CSS class of one of the existing menu items:

$wp_admin_bar->menu->{'wp-logo'}['meta']['class'] = 'new-class';

When running print_r($wp_admin_bar) the output looked something like this:

WP_Admin_Bar Object
(
    [menu] => stdClass Object
        (
            [my-account] => Array
                (

However, around version 3.3beta2 the above syntax for changing a menu item's CSS class no longer works, and the output from print_r($wp_admin_bar) reveals a different structure for that object:

WP_Admin_Bar Object
(
    [nodes:WP_Admin_Bar:private] => Array
        (
            [my-account] => stdClass Object
                (
                    [id] => my-account

                )

I realize that Wordpress may not want me fiddling with the menus this way, and if there was a more standardized way to do this I would love to use it, but as far as I know there are only two functions that are available to modify the admin bar, add_menu_item and remove_menu_item, and these do not give the flexibility to do things like changing the attributes of existing menu items.

To confirm, I looked at wp-includes/class-wp-admin-bar.php it is clear that Wordpress has changed the way they define the variables.

Old Class

class WP_Admin_Bar {
    var $menu;
    var $proto = 'http://';
    var $user;

New Class

class WP_Admin_Bar {
    private $nodes = array();
    private $root = array();

    public $proto = 'http://';
    public $user;

So my question is if I have access to the global $wp_admin_bar object, is there I way I can access the objects inside nodes:WP_Admin_Bar:private? And if not, is there another way to get to these objects, such as creating a new class that extends the WP_Admin_Bar class and then accessing the objects from there?

ps: I'm trying to overcome this challenge without changing the core Wordpress files...

Link to the file: http://phpxref.ftwr.co.uk/wordpress/nav.html?wp-includes/class-wp-admin-bar.php.source.html

0

3 Answers 3

13

If you dont want to touch the core files, then you have to use Reflection:

$adminBar = new WP_Admin_Bar();
$reflector = new ReflectionObject($adminBar);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
print_r($nodes->getValue($adminBar));

The hackish alternative would be casting the object to array and then doing:

$adminbar = (array) new WP_Admin_Bar;
$nodes = $adminbar[chr(0) . 'WP_Admin_Bar' . chr(0) . 'nodes'];
print_r($nodes);
Sign up to request clarification or add additional context in comments.

3 Comments

I will try Reflection and see if that works. Not sure if I can cast it into an array because I need to object to still be usable by the class so that it can be rendered. Thanks for a detailed answer :)
This worked great for me. The accepted answer does not answer the question! Sometimes you can't change the object without hacking into another party's code…
For the hackish version,the key can be different and found with dump, the key was "\x00*\x00id" and in fact chr(0) is equivalent to \x00 so the key is chr(0).'*'.chr(0).'id'
6

Change them to protected member variables and extend the class.

Whoever wrote the class with private members effectively made the class "final". Which goes to show that you should always write your members as protected, unless there's a really, REALLY good reason to do otherwise.

Hope that helps...

3 Comments

Added a link to the file with the class. Was hoping for a way to overcome this by extending it and not changing the core files.
Your question looks really well laid out. Perhaps you could submit a bug report with a link to this question before it gets released. They may be willing to change it to suit your needs. codex.wordpress.org/Reporting_Bugs
I think that's the best thing to do. Thanks. core.trac.wordpress.org/ticket/19371
1

If I understand correctly your question, you're asking if you can access an object's private variables, but I guess you know you can't unless there's a method for it in the class, so this may be a trivial non-useful answer, but just in case:

Look at the class' code. Does it have any method to retrieve those variables, like get_nodes(),get_root(), etc? If not you have 3 alternatives: recode the class set the vars public, recode the class and add the methods, or recode the class and set the variables protected, then create a new class extending the parent one with those methods (I recomend this one, since it has less impact on the parent class).

Anyway if you can't recode the class and it has no get methods you won't be able to access those private variables.

1 Comment

you're right I'm confusing private with protected here, edited.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.