Problem only while using require_once() within functions.php

I use add_theme_page() within my child theme’s functions.php implemented something like this…

// other functions located here that create a custom options page in the Dashboard.
// THIS IS NOT A FILE PATH ISSUE ->  THE CUSTOM PAGE IS CREATED IN BOTH CASES.

function my_menu() {
    ...
    if ( 'save' == $_REQUEST['action'] ) {
        echo '<meta http-equiv="refresh" content="0;url=themes.php?page=functions.php&saved=true">';
        die;
    }
    add_theme_page(...)
}

add_action('admin_menu', 'my_menu');

As per the WordPress docs:

Read More

NOTE: If you’re running into the »You do not have sufficient
permissions to access this page.«
message in a wp_die() screen, then
you’ve hooked too early. The hook you should use is admin_menu.

This is exactly the error I’m getting right after saving my options. However, I’ve used the correct hook as recommended.

This error only occurs if I move my function into a new file and do use a require_once within funtions.php. I was organizing my code as per this answer.

require_once('includes/functions-theme-options.php');

Why does this break simply by moving the function into an external file? I thought maybe it had to do with placement, but the require_once() is in the exact position where the original code was placed.

  • When the code is inside of functions.php, it works fine.

  • When the code is moved to an external file and reference with require_once(), it breaks (error messages upon save as per the referenced docs above).

Obviously, for now, I’m keeping it within function.php, but maybe somebody can explain why it’s breaking when I move it.


EDIT

This is not a file path issue. Every file referenced by require_once() is being found and included. The problem seems to be how it’s being executed.

Please read this answer: https://wordpress.stackexchange.com/a/1406/11092


EDIT 2 – revised 1/16/13

This is a stripped down version that was verified to fully demonstrate the issue. This code constructs a submenu page under “Appearance” called “Theme Options”. When you click the “Save Options” button, the page is supposed to reload and show a “your-theme settings saved” message. However, instead it shows the WordPress error page, “You do not have sufficient permissions to access this page.” Simply moving the last function into functions.php clears up this permissions issue. I would like to know why and how I can fix it.

in functions.php file:

<?php

require_once('includes/functions-test.php');

in my child-theme-directory, includes/functions-test.php file:

<?php

$themename = wp_get_theme();

function mytheme_admin() {

    global $themename;

    if ( $_REQUEST['saved'] ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings saved.</strong></p></div>';

    ?>

    <div class="wrap">
        <h2><?php echo $themename; ?> Options</h2>
        <div style="border-bottom: 1px dotted #000; padding-bottom: 10px; margin: 10px;">Options specfic to this theme.</div>
        <form method="post">
            <p class="submit">
                <input name="save" type="submit" class="button button-primary" value="Save Options" />    
                <input type="hidden" name="action" value="save" />
            </p>
        </form>
    </div>

<?php               
}


function wp_initialize_the_theme_load() {
    if (!function_exists("wp_initialize_the_theme")) { 
        wp_initialize_the_theme_message();
        die;
    }
}

add_action('admin_menu', 'mytheme_add_admin');


/*  move only the following function to 'functions.php' and the problem is gone
__________________________________________________________________________*/ 

function mytheme_add_admin() {
    global $themename, $shortname;  
    if ( $_GET['page'] == basename(__FILE__) ) {    
        if ( 'save' == $_REQUEST['action'] ) {
            echo '<meta http-equiv="refresh" content="0;url=themes.php?page=functions.php&saved=true">';
            die;
        } 
    }
    add_theme_page($themename." Options", "Theme Options", 'edit_theme_options', basename(__FILE__), 'mytheme_admin');
}

Related posts

1 comment

  1. I noticed the URL of the custom Dashboard page is this…

    themes.php?page=functions-test.php
    

    Notice how the page is the name of my external functions in includes/functions-test.php.

    The problem is in this line, the one that refreshes the page just before the permission error…

    echo '<meta http-equiv="refresh" content="0;url=themes.php?page=functions.php&saved=true">';
    

    Now it seems so obvious. Look at the page parameter in the URL… it’s functions.php where it should be the name of my includes file, functions-test.php.

    This is the fix…

    echo '<meta http-equiv="refresh" content="0;url=themes.php?page=functions-test.php&saved=true">';
    

    Now I wonder if there’s a more robust solution than having a hard coded file name.

    EDIT:

    And without a hard coded filename… in other words, using basename(__FILE__) instead and I could have moved this code anywhere without the headache.

    echo '<meta http-equiv="refresh" content="0;url=themes.php?page=' . basename(__FILE__) . '&saved=true">';
    

    Thank-you to troubleshooting suggestions by @ChipBennett.

    EDIT 2:

    Taking it one step further, I was able to completely remove the meta refresh; and die;, where instead I use the action of the form element as it was intended. This is the same form action as used in the default WordPress Appearance pages.

    <form action="<?php echo esc_url( add_query_arg( 'saved', true ) ) ?>" method="post">
    

    add_query_arg( 'saved', true ) means that when the page redirects back to itself, on form submission, it will have &saved=1 appended into its query string. This is the only part this code needs in order to display the "options saved" message. The very sloppy meta refresh; die with its hard coded URL, the root of the original problem, has been fully eradicated.

    FYI: This is a project where I must extract the client’s original options and functionality from their “custom” theme and move them into a child theme of Twenty Thirteen. The original broken theme that uses these sloppy coding practices is called Delicate.

Comments are closed.