2

Having an issue with my plugin updating the htaccess file. The code I used to do that is:

insert_with_markers($htaccess_file, $marker, $lines);

The parameters used in that function have been previously defined properly. There error message is:

    Uncaught Error: Call to a member function switch_to_locale() on null 
in /home2/path/to/site/fstraptest/wp-includes/l10n.php:1582

I tried ensuring that various functions used by switch_to_locale() are loaded:

if (! function_exists('get_home_path')) 
        {include_once(ABSPATH . 'wp-admin/includes/file.php');}
    if (! function_exists('insert_with_markers')) 
        {include_once(ABSPATH . 'wp-admin/includes/misc.php');}
    if (! function_exists('switch_to_locale')) 
        {
        include_once(ABSPATH . 'wp-admin/includes/l10n.php');
        include_once(ABSPATH . 'wp-includes/class-wp-locale-switcher.php');
        }
    if (! function_exists('got_mod_rewrite')) 
        {include_once(ABSPATH . 'wp-admin/includes/misc.php');}
    if (! function_exists('is_multisite')) 
        {include_once(ABSPATH . 'wp-admin/includes/load.php');}

But that didn't solve the issue.

This is with WP 5.3, PHP 7.3.11 . Similar code has worked before; this may have started with WP 5.3, but not sure.

The googles have not helped with this error. The language for the site is "en-US". The plugin does not have any language files. Theme has been changed to "Twenty-Thirteen"; error also occurs in other themes, so does not appear theme-dependent.

Additional Code

At the top of the plugin file, this code initializes the settings

add_action( 'admin_init', 'CWPSO_settings_init' );  // does register_setting, add_settings_section add_settings_field, etc

The CWPSO_settings_init() does the register thing, then there are a bunch of add_settings_field() to set up the options. All of those look similar to this:

add_settings_field( 
        'CWPSO_protect_config_file',                    // field name
        __( '', 'CWPSO_namespace' ),    // message before field (not used)
        'CWPSO_protect_config_file_render',         // render function
        'pluginPage',                   // plugin page name
        'CWPSO_pluginPage_section'      // plugin section name
    );  

This code sanitizes that input field:

if (isset($_POST['CWPSO_protect_config_file'])) {
                $new_input['CWPSO_protect_config_file'] = "1";} else { $new_input['CWPSO_protect_config_file'] = "0";}

This code sets up an array of things that might happen to the htaccess file

if (($options['CWPSO_protect_config_file'])  and ($_GET['page'] == 'cellarweb_private_function')) {
     $change_htaccess[] = 'CWPSO_protect_config_file';
 }

This code checks the previous htaccess array, and builds the statements to put in the htaccess

if (in_array('CWPSO_protect_config_file', $change_htaccess) ) {
        $lines[] = '  # protect wp-config.php file from direct access';
        $lines[] = '     <files wp-config.php>';
        $lines[] = '       order allow,deny';
        $lines[] = '       deny from all';
        $lines[] = '     </files>';
    }

This code does the actual htaccess file modification ($marker has been previously set)

$success = insert_with_markers($htaccess_file, $marker, $lines);

And that insert_with_markers() line causes the error. Note that all of the settings that the plugin uses/creates/save work properly. If I comment out the insert_with_markers() line, the plugin settings display/save properly.

  • 1
    In what hook do you call insert_with_markers()? Because seems like the global $wp_locale_switcher has not been initialized, so you may have not use the proper hook. – Sally CJ Nov 20 '19 at 4:52
  • The insert_with_markers is called on plugin settings screen save (or settings screen load). The settings screen has an option to 'do' that process (modify the htaccess) via a checkbox in the settings screen.That option is stored as part of the settings options. There is an admin_init filter that is done to register/load settings at the 'top' of the plugin code. – Rick Hellewell Nov 20 '19 at 18:13
  • Can you show your code - the part which does the saving and the add_action() call which calls that part. – Sally CJ Nov 20 '19 at 22:32
  • @SallyCJ : see added info/code in the original question. – Rick Hellewell Nov 20 '19 at 23:38
  • So you're calling insert_with_markers() from inside the callback specified in the third param for register_setting()? – Sally CJ Nov 21 '19 at 0:45
1

From your comment:

Those htaccess changes don't happen as a result of an add_action. Perhaps they should?

Yes, they should.

And here's why

insert_with_markers() calls switch_to_locale() which uses $GLOBALS['wp_locale_switcher'] (or $wp_locale_switcher) which is initialized in wp-settings.php, but only after WordPress runs the setup_theme hook.

And looking at the error in question and line #1582 in wp-includes/l10n.php which is return $wp_locale_switcher->switch_to_locale( $locale );, that error occurred most likely because the global variable $wp_locale_switcher has not yet been defined or initialized. Which indicates that you called insert_with_markers() too early.

So if you want to use insert_with_markers(), make sure you use the proper hook; for example, load-{$page_hook} or update_option_{$option}:

// Example 1:
add_action( 'admin_menu', function () {
    $hookname = add_menu_page( ... );
    add_action( 'load-' . $hookname, function () {
        // Call insert_with_markers()
    } );
} );

// Example 2:
add_action( 'update_option_my_field', function ( $old_value, $value ) {
    // Call insert_with_markers()
}, 10, 2 );

Both tried & tested working on WordPress 5.2.4 and 5.3.

But it's also possible there's a plugin or custom code which is messing with $wp_locale_switcher, so if using a hook later than setup_theme doesn't work for you, you can try deactivating plugins..

0

I discovered that there was an extra '-' character just above the line that caused the error. It was hard to see in my editor (and maybe because of some dust on the screen).

The syntax checker in my editor (Rapid PHP 2018) didn't sense that error Only by looking very close did I find the extra character. Removing that fixed the problem.

The lesson learned (again) is that sometimes the reported error line is not the problem. Errors can also be caused by statements previous to the reported line.

But thanks for the assistance; learned something from them also. So, net 'win'...although very frustrating to figure it out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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