Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am trying to build a class to make the job off adding new settings easier. The trouble I am having is that, although I have traced the variable through all of it's stages, the string 'manage_options' doesn't seem to grant admin the right to amend and option. I keep getting "You do not have sufficient permissions to access this page." when I try access the new settings page.

Here is a heavily simplified version of the class, the creation function and its action hook.

class optionObject{
    var $user_level = 'manage_options';

    function add_page() {

        add_options_page(menu_page_title, page_title, $this->user_level, menu_slug, array(&$this, 'do_page'));

    }
    function do_page(){
        //do stuff to display page
    }
}

function test_options(){
    $options = new optionObject();

    add_action('admin_menu', $options->add_page());
}

add_action('admin_init', 'test_options' );

Unedited Version here

share|improve this question
    
for test purposed, I changed the capability to the lowest, which is 'read', I still can't access my settings page!! –  Mild Fuzz Nov 4 '10 at 16:06
    
Your callback to admin_menu is set up wrong. It should be add_action('admin_menu', array($options, 'add_page')). Currently, you immediately execute the $options->add_page() function in the admin_init hook, which might be too early. –  Jan Fabry Nov 4 '10 at 16:28
    
I have directly copied that in, now the add_page function isn't firing. –  Mild Fuzz Nov 4 '10 at 16:33
add comment

2 Answers 2

up vote 1 down vote accepted

admin_init is called after wp-admin/menu.php is included, so the access check has already been executed and the admin_menu action has fired by the time you execute test_options(). Remove the admin_init hook and call test_options() directly, or find another way of structuring your code so that the admin_menu hook is set up correctly.

You might think it could work because you see the menu option when you are on other pages. This is because the menu is drawn after the page access is checked:

The menu is drawn in:

The access check however is done in:

You see that adding menu items in admin_init is OK to be included in the drawn menu, but too late for the access check. That's your current situation, and you need to change that by adding the page in the admin_menu hook or earlier.

share|improve this answer
    
Okay, that has got the page firing after the initial code change, but still getting read permission error on access. I have put the full version on a pastebin link in the original question. –  Mild Fuzz Nov 5 '10 at 9:42
    
@Mild Fuzz: You should not add the page in the admin_init hook, but already in the admin_menu hook. So replace add_action('admin_init', array($options, 'add_page')); with a direct call to $options->add_page() (since you call it in admin_menu), and it should work. –  Jan Fabry Nov 5 '10 at 11:23
    
what is odd is that the 'admin_init' get's fired on the dashboard, but not when you go to the page, but the construct is being fired on both. –  Mild Fuzz Nov 5 '10 at 11:34
    
@Mild Fuzz: I expanded my answer with a call tree of the drawing of the menu and the access check, so you can see that you were too late with the definition of your menu item. –  Jan Fabry Nov 5 '10 at 12:43
add comment

Jan is spot on with both his answer and comment on the original question..

Here's an example of the code working, in it's most basic form...

// Either uncomment the constructor function or the line following the creation of the object, simply showing you two working methods
class test_stuff {
    var $user_level = 'manage_options';
    // PHP4 or PHP5 constructor, you choose - uncomment function line as appropriate
    //function test_stuff() {
    //function __construct() {
    //    add_action( 'admin_menu', array( $this, 'add_new_page' ) );
    //}
    function add_new_page() {
        add_options_page( 'somename', 'somename', $this->user_level, 'somepagename', array( $this, 'display_page' ) );
    }
    function display_page() {
        echo 'Hello World!';
    }
}
$test_stuff = new test_stuff();
//add_action( 'admin_menu', array( $test_stuff, 'add_new_page' ) ); // Alternative to using the constructor function

Hope that helps...

share|improve this answer
    
Or to provide PHP4+5 constructors, do something like function test_stuff() { $this->__construct(); } function __construct() { add_action(...); }. (Now it's a bit confusing as your crucial hook is commented out) –  Jan Fabry Nov 4 '10 at 18:33
    
I personally just use the PHP 5 constructor, just offered it up as an alternative.. :) –  t31os Nov 4 '10 at 18:39
    
no good still, put full version in pastebin link in original question. –  Mild Fuzz Nov 5 '10 at 9:47
    
I tested the code i posted, it worked using both methods for me. Are you using WP 3.0.1?, and do you have any plugins enabled? What version of PHP are you running? –  t31os Nov 5 '10 at 10:26
    
Your full version is still using the admin_init hook despite the advice you've been given, please re-read the answers and comments that have been provided to you. –  t31os Nov 5 '10 at 11:00
add comment

protected by Community Nov 15 '12 at 10:36

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.