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.