• Resolved Jack

    (@jack1132132)


    Hello,

    I was trying to filter plugins depending on if the user was logged in or not. Unfortunately by the time I could get that information with wp_get_current_user() the plugins would have already loaded.

    So I was trying to figure out how to get around this and I found the function in /mu-plugins/plf-filter.php:

    function wp_get_current_user() {
            if ( ! function_exists( 'wp_set_current_user' ) ){
            
            if ( defined( 'LOGGED_IN_COOKIE' ) && !empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) {
                $cookie_elements = explode( '|', $_COOKIE[ LOGGED_IN_COOKIE ] );
                if ( count( $cookie_elements ) === 4 ) {
                    list( $username, $expiration, $token, $hmac ) = $cookie_elements;
                            if ( $expiration > time() ) {
                        $user = get_user_by( 'login', $username );
                            if ( $user ) {
                            $pass_frag = substr( $user->user_pass, 8, 4 );
    
                            $key = plf_logged_in_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token );
    
                            // If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
                            $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
                            $hash = hash_hmac( $algo, $username . '|' . $expiration . '|' . $token, $key );
    
                            if ( hash_equals( $hash, $hmac ) ) {
                                $manager = WP_Session_Tokens::get_instance( $user->ID );
                                if ( $manager->verify( $token ) ) {
                                    return $user;
                                }
                            }
                        }
                    }
                }
            }
                    return 0;
    
        } else {
            return _wp_get_current_user();
        }
    }

    Which does exactly what I want.

    Why is this function commented out and never used? Was it meant to allow for filtering based on user but given up on? Are there any security issues around it?

    Thank you.

Viewing 15 replies - 1 through 15 (of 17 total)
  • Plugin Author enomoto celtislab

    (@enomoto-celtislab)

    Plugins are usually loaded regardless of whether you are logged in or not.
    Plugin Load Filter did not check for logins as well, nor did it filter based on them.

    However, sometimes I’m asked to filter by user, so I researched how to get users in WP core, implemented the code experimentally, and commented it out!

    We want to keep this plugin simple and easy to use and understand, so we have no plans to add filters for users at this time, and if we do in the future, it would be better to do it on the add-on side, but we have not decided anything about how to do it.

    Fortunately, since you seem to be able to program, you can try to make a custom version yourself!

    Thank you

    Thread Starter Jack

    (@jack1132132)

    @enomoto-celtislab Hello,

    I’ve been trying for longer than I care to admit, but every attempt at filtering plugins programmatically always ends up disabling plugins sitewide.

    Update:

    I’ve found out it’s one plugin in specific called bp-better-messages, for some reason when I disable this plugin to Page Type using the Plf admin dashboard, it disables many plugins (the ones that aren’t included in the plf_filter functions output).

    I think it has something to do with its cronjob.

    Thread Starter Jack

    (@jack1132132)

    Btw, a filter hook to filter $new_plugins just above where it gets cached a the end of the plf_filter function, would be a great place to allow custom changes to the filtered plugin list.

    Thread Starter Jack

    (@jack1132132)

    Hello, Great plugin.
    Here’s my solution for filtering based on if the user is logged in or not:

    At end of function plf_filter (it’s better here because of the caching):

    $new_plugins = exclude_plugins_filter_custom($new_plugins);
    
            self::$cache[$keyid][$option] = $new_plugins;
            foreach ($new_plugins as $key) {
                if(!empty($key)){
                    $key = self::plugin_keygen( $key, $option );
                    self::$filtered_plugins[$key] = $key;
                }
            }
            return $new_plugins;
        }
    
    }

    then add these functions under:

    function is_logged_in_custom_(){
    
            if ( defined( 'LOGGED_IN_COOKIE' ) && !empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) )
                    return true;
    
            if(@count(@preg_grep('/^wordpress_logged_in/', @array_keys($_COOKIE))) > 0)
                    return true;
    
            return false;
    }
    function exclude_plugins_filter_custom($plugins){
    
            global $request_uri;
            global $wp_query;
    
            if( empty($request_uri) || !is_array($plugins))
                    return $plugins;
    
            $is_admin = strpos($request_uri, '/wp-admin') !== false ;
    
            if($is_admin || is_admin())
                    return $plugins;
    
            $is_profile = strpos($request_uri, '/user') !== false ;
    
            $excluded_plugins = array();
    
            //visitors
            if(!is_logged_in_custom_()){ 
    
                    //exclude plugins for non logged users e.g.:
                    $excluded_plugins[] = 'mycred/mycred.php';
                    $excluded_plugins[] = 'armember/armember.php
    
            //logged in
            } else {
                    //exclude plugins for logged in users e.g.:
            }
    
            $plugins = array_values(array_diff($plugins, $excluded_plugins));
            return $plugins;
    }

    Thank you.

    • This reply was modified 2 years, 3 months ago by Jack.
    Thread Starter Jack

    (@jack1132132)

    @enomoto-celtislab I found the issue with the plugin, it’s not the plugin it self.

    The problem is with the function fs_newest_sdk_plugin_first of the popular library freemius.

    This function calls update_option( 'active_plugins', $updated_active_plugins ); specifically when I remove bp-better-messages using Plugin Load Filter. When I comment it out, I can filter the bp-better-messages plugin just fine.

    update_option( 'active_plugins', $updated_active_plugins ); shouldn’t use filtered plugins from Plugin Load Filter, otherwise it will turn the filtered plugins off for the whole website.

    There needs to be a filter like:

    function remove_plf_n_return_all_plugins($plugins){
    
            if ( has_filter( 'pre_option_active_plugins', array('Plf_filter', 'active_plugins') ) )
    		remove_filter('pre_option_active_plugins', array('Plf_filter', 'active_plugins'));
    
    	return $plugins;
    }
    
    add_filter( 'pre_update_site_option_active_plugins', array($this, 'remove_plf_n_return_all_plugins') );

    And perhaps some these too:

    add_action( 'activate_plugin', array($this, 'remove_plugin_filters_custom'), 999 );
    		add_action( 'plugins_loaded', array($this, 'remove_plugin_filters_custom'), 999 );
    		add_action( 'deactivated_plugin', array($this, 'remove_plugin_filters_custom'), 999 );
    		add_filter( 'pre_update_site_option_active_plugins', array($this, 'remove_plf_n_return_all_plugins') );
    • This reply was modified 2 years, 3 months ago by Jack.
    Thread Starter Jack

    (@jack1132132)

    @enomoto-celtislab

    The real problem is that calling update_option( 'active_plugins', $new_plugins) will most likely be with the $new_plugins containing values from get_option(‘active_plugins’) which in turn will have the wrong values due to Plugin Load Filter.

    A solution to this is by doing:

    add_filter( 'pre_update_option_active_plugins', array($this, 'remove_plf_n_return_all_plugins') );
    
    function remove_plf_n_return_all_plugins($plugins){
    		remove_filter('pre_option_active_plugins', array('Plf_filter', 'active_plugins'));
    		
    	return get_option( 'active_plugins'); 
    }

    Now, a problem this with this is that update_option just wont update active_plugins, not even from the backend, because the above code feeds update_option the old values.

    But it is impossible to know if when get_option(‘active_plugins’) is called it’s meant for an update_option function, and if that get_option should filter plugins with plf_filter or not.

    Another solution, but with is own drawbacks:

    I’ve noticed the first two times get_option is called are the only ones that are needed to filter a plugin, these times are in:

    1# /wp-includes/load.php(816): get_option()
    2# /wp-admin/includes/plugin.php(528): get_option()

    If these two calls to get_option('active_plugins') are filtered then files relating to the filtered plugin wont load, I’ve tried it with a counter and a flag, but after these two calls to get_option(‘active_plugins’) are done, and get_option(‘active_plugins’) starts returning unfiltered plugins, then code like the fremius library can execute fine.

    However, if an active plugin calls get_option(‘active_plugins’) and the result don’t match the actually loaded plugins there could also be problems.

    Best regards.

    Plugin Author enomoto celtislab

    (@enomoto-celtislab)

    In a nutshell, you are saying that if I add the plugin bp-better-messages, the filter will not work?

    I’ve never used bp-better-messages, so I’ll try to test it in a test environment, but it may take a while.

    However, if the problem is due to the plugin’s update_option( ‘active_plugins’, …) is causing the problem, then I don’t think you should run update_option( ‘active_plugins’, …) should not run.

    If you rewrite the active_plugins setting in the database directly without following the regular installation/activation/deactivation/uninstallation procedure of the plugin, there is a high possibility that the code you want to process will not be executed when the state of the plugin changes from enabled to disabled in the regular procedure, causing a bug.

    Rewriting the value of the active_plugins setting directly in the database is a very special case and should not normally be done!

    Thread Starter Jack

    (@jack1132132)

    @enomoto-celtislab Hello,

    In this case, the update_option( ‘active_plugins’, …) getting called is from the Freemius library.

    As in the screenshot bellow, it’s used in many plugins:

    View post on imgur.com

    However, the function is not actually meant to activate or deactivate plugins. It’s meant to just change the order of plugins:

    *
             * @return bool Was plugin order changed. Return false if plugin was loaded first anyways.
             *
             * @global $fs_active_plugins
             */
            function fs_newest_sdk_plugin_first() {
            global $fs_active_plugins;
    
            /**
             * @todo Multi-site network activated plugin are always loaded prior to site plugins so if there's a plugin activated in the network mode that has an older version of the SDK of another plugin which is site activated that has new>
             *
             * @link https://github.com/Freemius/wordpress-sdk/issues/26
             */
    
            $newest_sdk_plugin_path = $fs_active_plugins->newest->plugin_path;
    
            $active_plugins         = get_option( 'active_plugins', array() );
            $updated_active_plugins = array( $newest_sdk_plugin_path );
    
            $plugin_found  = false;
            $is_first_path = true;
    
            foreach ( $active_plugins as $key => $plugin_path ) {
                if ( $plugin_path === $newest_sdk_plugin_path ) {
                    if ( $is_first_path ) {
                        // if it's the first plugin already, no need to continue
                        return false;
                    }
    
                    $plugin_found = true;
    
                    // Skip the plugin (it is already added as the 1st item of $updated_active_plugins).
                    continue;
                }
    
                $updated_active_plugins[] = $plugin_path;
    
                if ( $is_first_path ) {
                    $is_first_path = false;
                }
            }
    
            if ( $plugin_found ) {
                update_option( 'active_plugins', $updated_active_plugins );
    
                return true;
            }
    
            if ( is_multisite() ) {
                // Plugin is network active.
                $network_active_plugins = get_site_option( 'active_sitewide_plugins', array() );
    
                if ( isset( $network_active_plugins[ $newest_sdk_plugin_path ] ) ) {
                    reset( $network_active_plugins );
                    if ( $newest_sdk_plugin_path === key( $network_active_plugins ) ) {
                        // Plugin is already activated first on the network level.
                        return false;
                    } else {
                        $time = $network_active_plugins[ $newest_sdk_plugin_path ];
    
                        // Remove plugin from its current position.
                        unset( $network_active_plugins[ $newest_sdk_plugin_path ] );
    
                        // Set it to be included first.
                        $network_active_plugins = array( $newest_sdk_plugin_path => $time ) + $network_active_plugins;
    
                        update_site_option( 'active_sitewide_plugins', $network_active_plugins );
    
                        return true;
                    }
                }
            }
    
            return false;
        }

    It’s just by chance, that this functions is called when bp-better-messages is activated, it could have been any other plugin with a newer sdk path.

    To get around this issue I just filter pre_update_option_active_plugins to remove plugins-load-filters hooks and return get_option(‘active_plugins’) after. But if strpos($request_uri, '/wp-admin/') !== false, then I let it run normally so it can active and deactivate plugins only in the backoffice.

    Thank you.

    Plugin Author enomoto celtislab

    (@enomoto-celtislab)

    I installed the bp-better-messages plugin in a test environment, created a page with the bp-better-messages and bp_better_messages_chat_room shortcodes and tried filtering on that page and it worked fine.

    We could not reproduce the condition you pointed out. Some other factor may have affected it.

    Also, in plugin load filter, when not using add-ons, requests to wp-admin / wp-cron / wp-json are not filtered (around plf-filter.php line 1046, 1126)

    Therefore, even if active_plugins is updated in this state, no filtering is done, so no inconsistency is expected to occur.

    Plugin Author enomoto celtislab

    (@enomoto-celtislab)

    I could not reproduce this in my environment, but I have taken measures against unintentional disabling of plugins due to updates of DB data active_plugins by other plugins.

    Please give it a try.

    Thread Starter Jack

    (@jack1132132)

    Hello,

    I seems it’s working! Now the only thing missing is this filter right here: https://i.imgur.com/J8eThVD.png

    I’d also suggest naming the file plf-filter.php to 0plf-filter.php, so it runs before other mu-plugins, so other mu-plugins can see what plugins are active.

    Thank you.

    • This reply was modified 2 years, 3 months ago by Jack.
    Plugin Author enomoto celtislab

    (@enomoto-celtislab)

    As for filter hooks, I’ll try to add them in the next update
    (We will not update just for this, so the timing is undecided. We recommend that you customize it yourself if necessary.)

    No file name changes.
    Code that relies on plugin load order is not recommended.

    If you use a filter hook, register the hook and then determine if the required function or class exists when it is actually called.

    Thread Starter Jack

    (@jack1132132)

    Hello,

    Under the new version, I’m always getting this warning:
    PHP Warning: Undefined array key "REQUEST_METHOD" in /wordpress/wp-content/plugins/helpie-faq/vendor/pauple/pluginator/src/Library/freemius/config.php on line 166

    Which means there’s still some incompatibility with freemius.

    Thank you.

    Thread Starter Jack

    (@jack1132132)

    Hello,

    I’m getting issues from other plugins using freemius: PHP Warning: Undefined array key "REQUEST_METHOD" in /bitnami/wordpress/wp-content/plugins/bp-better-messages/inc/freemius/config.php
    And it’s causing some issues with with the website.

    Here’s altered code that fixed this issue for me:
    <?php
    /*
    Plugin Name: plugin load filter [plf-filter]
    Description: Dynamically activated only plugins that you have selected in each page. [Note] plf-filter has been automatically installed / deleted by Activate / Deactivate of “load filter plugin”.
    Version: 4.0.11
    Plugin URI: https://celtislab.net/en/wp-plugin-load-filter
    Author: enomoto@celtislab
    Author URI: https://celtislab.net/
    License: GPLv2
    */
    defined( ‘ABSPATH’ ) || exit;

    /***************************************************************************
    * pluggable.php defined function overwrite
    * pluggable.php read before the query_posts () is processed by the current user undetermined
    **************************************************************************/
    /**
    * Gets hash of given string.
    *
    * @param string $data Plain text to hash.
    * @return string Hash of $data.
    */
    //wp_salt( $scheme ) を簡略化して logged_in cookie 限定
    function plf_logged_in_hash( $data ) {
    $values = array(
    ‘key’ => ”,
    ‘salt’ => ”,
    );
    foreach ( array( ‘key’, ‘salt’ ) as $type ) {
    $const = strtoupper( “logged_in_{$type}” );
    if ( defined( $const ) && constant( $const ) ) {
    $values[ $type ] = constant( $const );
    }
    }
    $salt = $values[‘key’] . $values[‘salt’];
    return hash_hmac( ‘md5’, $data, $salt );
    }

    if ( !function_exists(‘wp_get_current_user’) ) :
    /**
    * Retrieve the current user object.
    * @return WP_User Current user WP_User object
    */
    function wp_get_current_user() {
    if ( ! function_exists( ‘wp_set_current_user’ ) ){
    /*
    if ( defined( ‘LOGGED_IN_COOKIE’ ) && !empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) {
    $cookie_elements = explode( ‘|’, $_COOKIE[ LOGGED_IN_COOKIE ] );
    if ( count( $cookie_elements ) === 4 ) {
    list( $username, $expiration, $token, $hmac ) = $cookie_elements;
    if ( $expiration > time() ) {
    $user = get_user_by( ‘login’, $username );
    if ( $user ) {
    $pass_frag = substr( $user->user_pass, 8, 4 );

    $key = plf_logged_in_hash( $username . ‘|’ . $pass_frag . ‘|’ . $expiration . ‘|’ . $token );

    // If ext/hash is not present, compat.php’s hash_hmac() does not support sha256.
    $algo = function_exists( ‘hash’ ) ? ‘sha256’ : ‘sha1’;
    $hash = hash_hmac( $algo, $username . ‘|’ . $expiration . ‘|’ . $token, $key );

    if ( hash_equals( $hash, $hmac ) ) {
    $manager = WP_Session_Tokens::get_instance( $user->ID );
    if ( $manager->verify( $token ) ) {
    return $user;
    }
    }
    }
    }
    }
    }
    */
    return 0;

    } else {
    return _wp_get_current_user();
    }
    }
    endif;

    if ( !function_exists(‘get_userdata’) ) :
    /**
    * Retrieve user info by user ID.
    * @param int $user_id User ID
    * @return WP_User|bool WP_User object on success, false on failure.
    */
    function get_userdata( $user_id ) {
    return get_user_by( ‘id’, $user_id );
    }
    endif;

    if ( !function_exists(‘get_user_by’) ) :
    function get_user_by( $field, $value ) {
    $userdata = WP_User::get_data_by( $field, $value );

    if ( !$userdata )
    return false;

    $user = new WP_User;
    $user->init( $userdata );

    return $user;
    }
    endif;


    if ( !function_exists(‘is_user_logged_in’) ) :
    function is_user_logged_in() {
    if ( ! function_exists( ‘wp_set_current_user’ ) )
    return false;

    $user = wp_get_current_user();

    if ( ! $user->exists() )
    return false;

    return true;
    }
    endif;


    /***************************************************************************
    * Plugin Load Filter
    **************************************************************************/

    if(in_array( ‘plugin-load-filter/plugin-load-filter.php’, (array) get_option( ‘active_plugins’, array() ) )){
    $plugin_load_filter = new Plf_filter();
    } elseif ( is_multisite() ) {
    $plugins = get_site_option( ‘active_sitewide_plugins’);
    if ( isset($plugins[‘plugin-load-filter/plugin-load-filter.php’]) ){
    $plugin_load_filter = new Plf_filter();
    }
    }

    /*function active_plugins_custom_($plugins){
    throw new Exception(print_r( $plugins,true));
    return $plugins;
    }
    add_filter(‘pre_option_active_plugins’, ‘active_plugins_custom_’);*/

    class Plf_filter {
    static private $filter; //Plugin Load Filter Setting option data
    static private $rlocale;
    static private $url_filter;
    static private $s_url_filter;
    static private $is_filterkey;
    static private $base_plugins;
    static private $filtered_plugins;
    static private $cache;
    static private $url2id;
    static private $pre_post_id;
    static private $base_public_query_vars;

    static private $counter;
    static private $flag_stop;


    function __construct() {
    self::$rlocale = null;
    self::$cache = array();
    self::$url2id = array();
    self::$pre_post_id = 0;
    self::$base_public_query_vars = array();
    self::$url_filter = array();
    self::$s_url_filter = array();
    self::$is_filterkey = false;
    self::$base_plugins = array();
    self::$filtered_plugins = array();
    self::$filter = get_option(‘plf_option’, array());

    self::$counter = 0;
    self::$flag_stop = false;

    if(!empty(self::$filter)){

    //Addon option get
    $plugins = get_option( ‘active_plugins’, array() );
    if ( is_multisite() ) {
    $network_plugins = (array) get_site_option( ‘active_sitewide_plugins’, array() );
    $plugins = array_merge( $plugins, array_keys( $network_plugins ) );
    }
    if(!empty($plugins) && in_array( ‘plugin-load-filter-addon/plugin-load-filter-addon.php’, $plugins)){
    self::$url_filter = get_option(‘plf_addon_options’, array());
    }

    //active_plugins filter
    if ( is_multisite() ) {
    add_filter(‘pre_site_option_active_sitewide_plugins’, array(‘Plf_filter’, ‘active_sitewide_plugins’));
    add_action(‘update_site_option_active_sitewide_plugins’, array($this, ‘update_active_sitewide_plugins’), 99999, 4);
    }
    add_filter(‘pre_option_active_plugins’, array(‘Plf_filter’, ‘active_plugins’));
    add_filter(‘pre_option_jetpack_active_modules’, array(‘Plf_filter’, ‘active_jetmodules’));
    add_filter(‘pre_option_celtispack_active_modules’, array(‘Plf_filter’, ‘active_celtismodules’));

    add_action(‘update_option_active_plugins’, array($this, ‘update_active_plugins’), 99999, 3);
    add_action(‘update_option_jetpack_active_modules’, array($this, ‘update_active_jetmodules’), 99999, 3);
    add_action(‘update_option_celtispack_active_modules’, array($this, ‘update_active_celtismodules’), 99999, 3);
    add_action(‘switch_theme’, array($this, ‘switch_theme’));

    add_action(‘plugins_loaded’, array($this, ‘plugins_loaded’));
    // add_action(‘wp_loaded’, array($this, ‘cache_post_type’), 1);
    add_action(‘admin_init’, array($this, ‘cache_post_type’));
    //admin-bar filtered status
    if(!empty(self::$filter[‘admin_bar’])){
    add_action(‘admin_bar_menu’, array($this,’custom_bar_menus’), 201);
    }
    //language locale filter
    if(!empty(self::$filter[‘language’])){
    add_filter( ‘locale’, array(‘Plf_filter’, ‘post_locale’) );
    add_filter( ‘determine_locale’, array(‘Plf_filter’, ‘post_determine_locale’) );
    }
    }

    add_action( ‘activate_plugin’, array($this, ‘remove_plugin_filters_custom’), 999 );
    add_action( ‘plugins_loaded’, array($this, ‘remove_plugin_filters_custom’), 999 );
    add_action( ‘deactivated_plugin’, array($this, ‘remove_plugin_filters_custom’), 999 );
    add_filter( ‘pre_update_site_option_active_plugins’, array($this, ‘remove_plf_n_return_all_plugins’) );
    add_filter( ‘pre_update_option_active_plugins’, array($this, ‘remove_plf_n_return_all_plugins’) );

    }

    function remove_plugin_filters_custom() {

    if ( is_multisite() ) {
    remove_filter(‘pre_site_option_active_sitewide_plugins’, array(‘Plf_filter’, ‘active_sitewide_plugins’));
    remove_action(‘update_site_option_active_sitewide_plugins’, array($this, ‘update_active_sitewide_plugins’), 99999);
    }

    if ( has_filter( ‘pre_option_active_plugins’, array(‘Plf_filter’, ‘active_plugins’) ) ){
    self::$flag_stop = true;
    }

    remove_filter(‘pre_option_active_plugins’, array(‘Plf_filter’, ‘active_plugins’));
    remove_filter(‘pre_option_jetpack_active_modules’, array(‘Plf_filter’, ‘active_jetmodules’));
    remove_filter(‘pre_option_celtispack_active_modules’, array(‘Plf_filter’, ‘active_celtismodules’));

    remove_action(‘update_option_active_plugins’, array($this, ‘update_active_plugins’), 99999);
    remove_action(‘update_option_jetpack_active_modules’, array($this, ‘update_active_jetmodules’), 99999);
    remove_action(‘update_option_celtispack_active_modules’, array($this, ‘update_active_celtismodules’), 99999);
    remove_action(‘switch_theme’, array($this, ‘switch_theme’));

    remove_action(‘plugins_loaded’, array($this, ‘plugins_loaded’));

    remove_action(‘admin_init’, array($this, ‘cache_post_type’));

    if(!empty(self::$filter[‘admin_bar’])){
    remove_action(‘admin_bar_menu’, array($this,’custom_bar_menus’), 201);
    }

    if(!empty(self::$filter[‘language’])){
    remove_filter( ‘locale’, array(‘Plf_filter’, ‘post_locale’) );
    remove_filter( ‘determine_locale’, array(‘Plf_filter’, ‘post_determine_locale’) );
    }
    }

    function remove_plf_n_return_all_plugins($plugins){

    global $request_uri;

    $is_admin = strpos($request_uri, ‘/wp-admin/’) !== false ;

    if(!$is_admin){
    $this->remove_plugin_filters_custom();

    $get_plugins_ = get_option( ‘active_plugins’ );

    if(!count($plugins))
    return $get_plugins_;

    $first_plugin = $plugins[0];

    $new_plugins = array($first_plugin);

    foreach ($get_plugins_ as $plugin){
    if($plugin != $first_plugin){
    array_push($new_plugins, $plugin);
    }
    }

    return $new_plugins; //get_option( ‘active_plugins’);
    }

    return $plugins;
    }


    //Notice: scriptを使うと AMP でエラーとなるので target でオープン/クローズを行う
    static function plf_filtered_result_dialog( $text ) {
    ?>
    <style>
    #wpadminbar #wp-admin-bar-plf-statlink .ab-icon:before { content: ‘\f106’; top: 2px;}
    #plf-status { display:none;}
    #plf-status:target { display:block;}
    #plf-status .dialog-overlay{ position:fixed; left:0px; top:0px; width:100%; height:100%; background-color:rgba(0,0,0,.5); z-index:999999999;}
    #plf-status div.dialog { position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); width:66%; max-width:420px; height:auto; padding:1.5em; color:#222; background:#fff; z-index:999999999;}
    #plf-status .dialog-title { margin: 0 0 1em; font-size: 16px;}
    #plf-status textarea { font-size: 13px;}
    #plf-status .button-group { display:block; margin-top:2em; text-align:right; font-size:1em;}
    #plf-status a.button { display:inline-block; text-decoration:none; margin: 0 0 0 1em; padding: .5em 1em; color: #0071a1; background: #f5f5f5; border:solid 1px #0071a1; border-radius:3px; cursor:pointer;}
    #plf-status a.button:hover { background: #e8ffff; border-color: #016087; color: #016087;}
    </style>
    <div id=”plf-status”>
    <div class=”dialog-overlay”></div>
    <div class=”dialog”>
    <p class=”dialog-title”><strong><?php echo ‘Plugin Load Filter status’; ?></strong></p>
    <div><textarea id=”plf-filtered-result” style=”width:100%; height:320px; margin:5px 0;”><?php echo $text; ?></textarea></div>
    <div class=”button-group”>
    <a href=”#” id=”plf-status-close” class=”button” aria-label=”Close modal”><?php _e(‘Close’); ?></a>
    </div>
    </div>
    </div>
    <?php
    }

    //filtered plugins list print
    static function result_plugin_print( $e_plugins, $d_plugins ) {
    $text = PHP_EOL . “[Activate Plugins]” . PHP_EOL;
    $idx = 1;
    foreach ($e_plugins as $key) {
    if(!empty($key)){
    $key = preg_replace(‘|/.+?\.php|’, ”, $key);
    $text .= “$idx. $key” . PHP_EOL;
    $idx++;
    }
    }
    $text .= PHP_EOL . “[Deactivate Plugins]” . PHP_EOL;
    $idx = 1;
    foreach ($d_plugins as $key) {
    if(!empty($key)){
    $key = preg_replace(‘|/.+?\.php|’, ”, $key);
    $text .= “$idx. $key” . PHP_EOL;
    $idx++;
    }
    }
    return $text;
    }

    public function custom_bar_menus($wp_admin_bar) {
    if (current_user_can( ‘activate_plugins’ )) {
    $base_plugins = self::get_base_plugins();
    if(!empty($base_plugins)){
    $text = ‘==== Plugin Load Filter status ====’ . PHP_EOL;
    $is_filterkey = self::is_filterkey();
    if($is_filterkey !== false){
    $text .= ‘[Filter] ‘ . $is_filterkey . PHP_EOL;
    $e_plugins = self::get_filtered_plugins();
    $d_plugins = array_diff( $base_plugins, $e_plugins );
    } else {
    $text .= ‘[Filter] Not Used’ . PHP_EOL;
    $e_plugins = $base_plugins;
    $d_plugins = array();
    }
    ksort($e_plugins, SORT_STRING);
    ksort($d_plugins, SORT_STRING);

    $text .= self::result_plugin_print( $e_plugins, $d_plugins );
    self::plf_filtered_result_dialog( $text );
    $wp_admin_bar->add_menu( array(
    ‘id’ => ‘plf-statlink’,
    ‘title’ => ‘<span class=”ab-icon”></span>PLF’,
    ‘href’ => ‘#plf-status’,
    ));
    }
    }
    }

    //active_sitewide plugins Filter add ver2.4.0
    static function active_sitewide_plugins( $default = false) {
    return self::plf_filter( ‘active_sitewide_plugins’, $default);
    }

    //active plugins Filter
    static function active_plugins( $default = false) {
    //if(self::$counter == 1){
    if (self::$flag_stop)
    return $default;
    //}
    //self::$counter++;
    return self::plf_filter( ‘active_plugins’, $default);
    }

    //Jetpack module Filter
    static function active_jetmodules( $default = false) {
    return self::plf_filter( ‘jetpack_active_modules’, $default);
    }

    //Celtispack module Filter
    static function active_celtismodules( $default = false) {
    return self::plf_filter( ‘celtispack_active_modules’, $default);
    }

    function updated_plf_stat() {
    $default = array(
    ‘post_type_query_vars’ => array(),
    ‘queryable_post_types’ => array(),
    //’wp_post_statuses’ => array(),
    //’wp_post_types’ => array(),
    //’wp_taxonomies’ => array(),
    ‘stat_change’ => false,
    );
    $data = get_option(‘plf_queryvars’, array());
    $data = wp_parse_args( (array) $data, $default);
    //plugin bulk action repeated call
    if(empty($data[‘stat_change’])){
    $data[‘stat_change’] = true;
    update_option(‘plf_queryvars’, $data);
    }
    }

    //Plugin/Module activate or deactivate stat change
    function update_active_sitewide_plugins( $option, $value, $old_value, $network_id ) {
    $this->updated_plf_stat();
    }
    function update_active_plugins( $old_value, $value, $option ) {
    $this->updated_plf_stat();
    }
    function update_active_jetmodules( $old_value, $value, $option ) {
    $this->updated_plf_stat();
    }
    function update_active_celtismodules( $old_value, $value, $option ) {
    $this->updated_plf_stat();
    }
    function switch_theme() {
    $this->updated_plf_stat();
    }

    //Make taxonomies and posts available to ‘plugin load filter’.
    //force register_taxonomy (category, post_tag, post_format)
    static function force_initial_taxonomies(){
    global $wp_actions;
    $wp_actions[ ‘init’ ] = 1;
    create_initial_taxonomies();
    create_initial_post_types();
    unset($wp_actions[ ‘init’ ]);
    }

    //all plugins loaded
    function plugins_loaded() {
    //ver4.0.5 カスタムポストタイプのキャッシュデータを $wp_post_types グローバル変数には反映しないよう変更したのでこの処理は不要となるが、なんらかの影響があると嫌なのでとりあえず残しておく
    // woocommerce が init 後に register_post_type, register_taxonomy が実行されたか判定しているので該当データを一旦クリアして init で再登録させる
    if(post_type_exists( ‘product’ )){
    if(method_exists(‘WC_Post_Types’, ‘register_post_types’)){
    unregister_post_type( ‘product’ );
    //ver4.0.2 wc_register_order_type で登録されるタイプも一旦クリアする
    if(post_type_exists( ‘shop_order’ )){
    unregister_post_type( ‘shop_order’ );
    }
    if(post_type_exists( ‘shop_order_refund’ )){
    unregister_post_type( ‘shop_order_refund’ );
    }
    }
    }
    if ( taxonomy_exists( ‘product_type’ ) ) {
    if(method_exists(‘WC_Post_Types’, ‘register_taxonomies’)){
    unregister_taxonomy( ‘product_type’ );
    }
    }
    }

    //Post Format Type, Custom Post Type Data Cache for parse request
    function cache_post_type() {
    if (!is_admin() || self::$is_filterkey !== false || ( defined(‘DOING_AJAX’) && DOING_AJAX ))
    return;

    $default = array(
    ‘post_type_query_vars’ => array(),
    ‘queryable_post_types’ => array(),
    //’wp_post_statuses’ => array(),
    //’wp_post_types’ => array(),
    //’wp_taxonomies’ => array(),
    ‘stat_change’ => false,
    );
    $data = get_option(‘plf_queryvars’, array());
    $data = wp_parse_args( (array) $data, $default);

    global $plugin_page;
    if(isset($plugin_page) && $plugin_page === ‘plugin_load_filter_admin_manage_page’){
    $data[‘stat_change’] = true;
    }

    //init or plugin activate or deactivate stat change
    if(!empty($data[‘stat_change’])){
    global $wp;
    $public_query_vars = (!empty($wp->public_query_vars))? $wp->public_query_vars : array();;
    $post_type_query_vars = array();
    foreach ( get_post_types( array(), ‘objects’ ) as $post_type => $t ){
    if (!empty($t) && $t->query_var )
    $post_type_query_vars[$t->query_var] = $post_type;
    }
    $queryable_post_types = get_post_types( array(‘publicly_queryable’ => true) );

    //global $wp_post_types;
    //global $wp_post_statuses;
    //global $wp_taxonomies;
    //$data[‘wp_post_types’] = $wp_post_types;
    //$data[‘wp_post_statuses’] = $wp_post_statuses;
    //$data[‘wp_taxonomies’] = $wp_taxonomies;
    //$data[‘public_query_vars’] = $public_query_vars;
    //ver4.0.11 使わないデータを取り除きオプションデータを縮小化
    if(!empty($data[‘rewrite_rules’])){
    unset($data[‘rewrite_rules’]); //データの残骸があれば使わないので取り除く
    }
    if(!empty($data[‘wp_post_types’])){
    unset($data[‘wp_post_types’]);
    }
    if(!empty($data[‘wp_post_statuses’])){
    unset($data[‘wp_post_statuses’]);
    }
    if(!empty($data[‘wp_taxonomies’])){
    unset($data[‘wp_taxonomies’]);
    }
    if(!empty($data[‘public_query_vars’])){
    unset($data[‘public_query_vars’]);
    }
    $add_query_vars = array_diff( $public_query_vars, self::$base_public_query_vars );
    $data[‘add_public_query_vars’]= $add_query_vars;
    $data[‘post_type_query_vars’] = $post_type_query_vars;
    $data[‘queryable_post_types’] = $queryable_post_types;
    $data[‘stat_change’] = false;
    update_option(‘plf_queryvars’, $data);
    }
    }

    /**
    * Filters the locale for the current request.
    *
    * @param string $locale The locale.
    */
    static function post_locale( $locale ) {
    if(empty(self::$rlocale)) {
    $pid = 0;
    if(isset($_SERVER[‘REQUEST_URI’])){
    if ( strpos( $_SERVER[‘REQUEST_URI’], ‘wp-json’ ) !== false || preg_match( ‘/(admin|wc)-ajax/’, $_SERVER[‘REQUEST_URI’])) {
    $refurl = wp_get_raw_referer();
    if(!empty( $refurl )){
    if(preg_match( ‘/post=([0-9]+)?/’, $refurl, $match )){
    $pid = (int)$match[1];
    } elseif(preg_match( ‘/post_ID=([0-9]+)?/’, $refurl, $match )){
    $pid = (int)$match[1];
    } else {
    $pid = (isset(self::$url2id[$refurl]))? self::$url2id[$refurl] : url_to_postid( $refurl );
    self::$url2id[$refurl] = (int)$pid;
    }
    }
    } elseif ( strpos( $_SERVER[‘REQUEST_URI’], ‘wp-admin’ ) !== false) {
    if ( isset( $_GET[‘post’] ) ) {
    $pid = (int) $_GET[‘post’];
    } elseif ( isset( $_POST[‘post_ID’] ) ) {
    $pid = (int) $_POST[‘post_ID’];
    }
    } else {
    global $wp_query;
    if(!empty(self::$pre_post_id)){
    $pid = self::$pre_post_id;
    } elseif(is_object($wp_query->post) && !empty($wp_query->post->ID)){
    $pid = $wp_query->post->ID;
    } else {
    $refurl = wp_get_raw_referer();
    if (!empty( $refurl )) {
    $pid = (isset(self::$url2id[$refurl]))? self::$url2id[$refurl] : url_to_postid( $refurl );
    self::$url2id[$refurl] = (int)$pid;
    }
    }
    }
    }
    if(!empty($pid)){
    $c_locale = get_post_meta( $pid, ‘_locale’, true );
    if(!empty($c_locale)){
    self::$rlocale = $c_locale;
    }
    }
    }
    if(!empty(self::$rlocale)) {
    $locale = self::$rlocale;
    }
    return $locale;
    }

    static function post_determine_locale( $locale ) {
    if(!empty(self::$rlocale)) {
    $locale = self::$rlocale;
    }
    return $locale;
    }

    //プラグインロード前は bbPress等 カスタムポストタイプのデバッグモードでのエラー表示抑制
    static function exclude_trigger_error( $trigger, $function, $message, $version) {
    if (did_action( ‘plugins_loaded’ ) === 0) {
    if($function === ‘map_meta_cap’){
    $trigger = false;
    }
    }
    return $trigger;
    }
    //プラグインロード前は closed 等のカスタムステータスがまだ登録されてない状態でも取得 posts 情報がクリアされないよう抑制
    static function exclude_map_meta_cap( $caps, $cap, $user_id, $args) {
    if (did_action( ‘plugins_loaded’ ) === 0) {
    if(!empty($caps) && $caps[0] === ‘edit_others_posts’){
    $caps = array();
    }
    }
    return $caps;
    }

    //parse_request Action Hook for Custom Post Type query add
    static function parse_request( &$args ) {
    if (did_action( ‘plugins_loaded’ ) === 0) {
    $data = get_option(‘plf_queryvars’, array());
    if(!empty($data[‘post_type_query_vars’]) && !empty($data[‘queryable_post_types’]) && empty($data[‘stat_change’])){
    //ver4.0.5 グローバルのカスタムポストタイプに事前設定するとプラグイン内での登録済みチェック処理とコンフリクトするので止める
    //global $wp_post_statuses;
    //global $wp_post_types;
    //global $wp_taxonomies;
    //$wp_post_statuses = $data[‘wp_post_statuses’];
    //$wp_post_types = $data[‘wp_post_types’];
    //$wp_taxonomies = $data[‘wp_taxonomies’];

    $post_type_query_vars = $data[‘post_type_query_vars’];
    $queryable_post_types = $data[‘queryable_post_types’];

    //query_vars に query_posts() で実行するSQL用のポストタイプデータをセット
    if(isset($data[‘add_public_query_vars’])){
    //ver4.0.11 差分データにしたのでここでマージするが更新時にエラーとならないよう旧処理も残しておく
    $args->public_query_vars = array_merge(self::$base_public_query_vars, $data[‘add_public_query_vars’]);
    } else {
    $args->public_query_vars = $data[‘public_query_vars’];
    }
    if ( isset( $args->matched_query ) ) {
    parse_str($args->matched_query, $perma_query_vars);
    }
    foreach ( $args->public_query_vars as $wpvar ) {
    if ( isset( $args->extra_query_vars[$wpvar] ) ){
    $args->query_vars[$wpvar] = $args->extra_query_vars[$wpvar];
    } elseif ( isset( $_POST[$wpvar] ) ){
    $args->query_vars[$wpvar] = $_POST[$wpvar];
    } elseif ( isset( $_GET[$wpvar] ) ){
    $args->query_vars[$wpvar] = $_GET[$wpvar];
    } elseif ( isset( $perma_query_vars[$wpvar] ) ){
    $args->query_vars[$wpvar] = $perma_query_vars[$wpvar];
    }
    if ( !empty( $args->query_vars[$wpvar] ) ) {
    if ( ! is_array( $args->query_vars[$wpvar] ) ) {
    $args->query_vars[$wpvar] = (string) $args->query_vars[$wpvar];
    } else {
    foreach ( $args->query_vars[$wpvar] as $vkey => $v ) {
    if ( !is_object( $v ) ) {
    $args->query_vars[$wpvar][$vkey] = (string) $v;
    }
    }
    }
    if ( isset($post_type_query_vars[$wpvar] ) ) {
    $args->query_vars[‘post_type’] = $post_type_query_vars[$wpvar];
    $args->query_vars[‘name’] = $args->query_vars[$wpvar];
    }
    }
    }

    // Limit publicly queried post_types to those that are publicly_queryable
    if ( isset( $args->query_vars[‘post_type’]) ) {
    if ( ! is_array( $args->query_vars[‘post_type’] ) ) {
    if ( ! in_array( $args->query_vars[‘post_type’], $queryable_post_types ) )
    unset( $args->query_vars[‘post_type’] );
    } else {
    $args->query_vars[‘post_type’] = array_intersect( $args->query_vars[‘post_type’], $queryable_post_types );
    }
    }
    }
    }
    }

    //get filter name
    static function is_filterkey() {
    return self::$is_filterkey;
    }
    //base plugins (initial activated plugins & module)
    static function get_base_plugins() {
    return self::$base_plugins;
    }
    //filtered plugins (plugins & module)
    static function get_filtered_plugins() {
    return self::$filtered_plugins;
    }

    /**
    * Get URL Filter (for addon optional)
    * @param $stat : ‘active’ / ‘deactive’ / ” = all
    * @param $urltype : ‘front’ / ‘admin’ / ” = all
    * @param $device : ‘desktop’ / ‘mobile’ / ” = all
    * @return url filter data array.
    */
    static function get_url_filter( $stat=”, $urltype=”, $device=” ) {
    $frontlist = array();
    $adminlist = array();
    if(!empty(self::$url_filter)){
    foreach (self::$url_filter[‘filter’] as $slug => $v) {
    if(empty($stat) || (!empty($v[‘stat’]) && $stat === ‘active’) || (empty($v[‘stat’]) && $stat === ‘deactive’)){
    if(empty($device) || (!empty($v[‘desktop’]) && $device === ‘desktop’) || (!empty($v[‘mobile’]) && $device === ‘mobile’)){
    if(!empty($v[‘type’])){
    $item = “{$v[‘group’]}-{$v[‘slug’]}”;
    if($v[‘type’] == ‘front’){
    $frontlist[$item] = $v;
    } elseif($v[‘type’] == ‘admin’){
    $adminlist[$item] = $v;
    }
    }
    }
    }
    }
    //group 毎に slug をソート A-Za-z 順となる
    ksort($frontlist, SORT_STRING);
    ksort($adminlist, SORT_STRING);
    }
    $list = array();
    if(empty($urltype) || $urltype === ‘front’){
    foreach ($frontlist as $item => $v) {
    if(!empty($v)){
    $list[] = $v;
    }
    }
    }
    if(empty($urltype) || $urltype === ‘admin’){
    foreach ($adminlist as $item => $v) {
    if(!empty($v)){
    $list[] = $v;
    }
    }
    }
    return $list;
    }
    //active group list
    static function get_active_group() {
    $grouplist = array();
    $sluglist = self::get_url_filter( ‘active’ );
    foreach ($sluglist as $v) {
    if(!empty($v[‘group’]) && !in_array($v[‘group’], $grouplist)){
    $grouplist[] = $v[‘group’];
    }
    }
    return $grouplist;
    }
    //active slug filter data in group
    static function get_slug_filter( $group ) {
    $list = array();
    $sluglist = self::get_url_filter( ‘active’ );
    foreach ($sluglist as $v) {
    if(!empty($v[‘group’]) && $v[‘group’] == $group){
    $list[] = $v;
    }
    }
    return $list;
    }

    //Is there a term in taxonomies
    static function is_term_in_taxonomy( $post_id, $term, $taxonomies) {
    $ret = false;
    $txs = explode(‘,’, $taxonomies);
    foreach ( $txs as $slug ) {
    if(!empty($slug)){
    $names = ”;
    $terms = get_the_terms( $post_id, $slug );
    if (!empty($terms) ) {
    foreach ( $terms as $tobj ) {
    if(!empty($tobj)){
    $names .= $tobj->name . ‘,’;
    }
    }
    if(strpos($names, $term ) !== false){
    $ret = true;
    break;
    }
    }
    }
    }
    return $ret;
    }

    // url path, query parameter match check
    static function is_url_match( $req_url, $parse_url, $filter ) {
    if(empty($req_url) || empty($parse_url[‘path’]))
    return false;
    $_url[‘url_path’] = $parse_url[‘path’];
    $_url[‘url_q_and’] = $_url[‘url_q_not’] = (!empty($parse_url[‘query’]))? $parse_url[‘query’] : ”;

    $match = array();
    $keynum = array();
    foreach (array(‘url_path’, ‘url_q_and’, ‘url_q_not’) as $item) {
    $match[$item] = 0;
    $keynum[$item] = 0;
    if($item === ‘url_path’){
    $reg_before = “(/?)”;
    $reg_after = “(/?$)”;
    } else {
    $reg_before = “(^|&)”;
    $reg_after = “(=|&|$)”;
    }

    $keylist = (!empty($filter[$item])) ? $filter[$item] : ”;
    $keylist = str_replace( “*”, “.+?”, $keylist);
    $ar_key = (!empty($keylist))? array_filter( array_map(“trim”, explode(PHP_EOL, $keylist))) : array();
    $keynum[$item] = count($ar_key);
    if(empty($ar_key)) {
    if($item === ‘url_path’)
    $match[$item] += 1;
    } else {
    $ar_new = array();
    foreach ($ar_key as $key) {
    //v4.0.6 home (/) のみの指定は別判定しないとトレイルスラッシュで終わる全てのURLにマッチしてしまう
    if($item === ‘url_path’ && $key === ‘/’){
    if($_url[‘url_path’] === ‘/’){
    $match[$item] += 1;
    }
    } elseif(preg_match(“#{$reg_before}{$key}{$reg_after}#ui”, $_url[$item])){
    $match[$item] += 1;
    }
    }
    }
    }
    $group = false;
    $hit = ($match[‘url_path’] > 0 && $match[‘url_q_and’] === $keynum[‘url_q_and’] && $match[‘url_q_not’] === 0)? true : false;
    if($hit){
    if((strpos($_url[‘url_path’], ‘admin-ajax.php’ ) !== false || strpos($_url[‘url_q_and’], ‘wc-ajax’ ) !== false) && (int)$filter[‘targetpage’] === 2){
    $action = ”;
    if(isset($_REQUEST[‘action’])){
    $action = esc_attr($_REQUEST[‘action’]);
    } elseif(!empty( $_GET[‘wc-ajax’] )) {
    $action = sanitize_text_field( wp_unslash( $_GET[‘wc-ajax’] ) );
    }
    if(!empty($filter[‘ajax_action’])){
    if( $action == $filter[‘ajax_action’] ){
    $group = $filter[‘group’];
    }
    } else {
    //exclude special action : plugin_load_filter, plf_urlfilter_test
    if (! in_array( $action, array(‘plugin_load_filter’, ‘plf_urlfilter_test’)) ){
    $group = $filter[‘group’];
    }
    }
    } elseif(strpos($_url[‘url_path’], ‘post-new.php’ ) === false && (int)$filter[‘targetpage’] === 1){
    $post_id = 0;
    if ( isset( $_GET[‘post’] ) && isset( $_POST[‘post_ID’] ) && (int) $_GET[‘post’] !== (int) $_POST[‘post_ID’] ) {
    } elseif ( isset( $_GET[‘post’] ) ) {
    $post_id = (int) $_GET[‘post’];
    } elseif ( isset( $_POST[‘post_ID’] ) ) {
    $post_id = (int) $_POST[‘post_ID’];
    }
    if(empty($post_id)){
    //クエリーパラメータ形式だとポストIDが取得できないようなので、シュミレータ以外なら $wp_query->post->ID を使う
    if (isset($_REQUEST[‘action’]) && isset($_POST[‘test_url’]) ) {
    $post_id = (isset(self::$url2id[$req_url]))? self::$url2id[$req_url] : url_to_postid( $req_url );
    self::$url2id[$req_url] = (int)$post_id;
    } else {
    global $wp_query;
    if(is_object($wp_query->post) && !empty($wp_query->post->ID)) {
    $post_id = $wp_query->post->ID;
    } else {
    $post_id = (isset(self::$url2id[$req_url]))? self::$url2id[$req_url] : url_to_postid( $req_url );
    self::$url2id[$req_url] = (int)$post_id;
    }
    }
    }
    if(!empty($post_id)){
    $post = get_post( $post_id );
    if ( is_object($post) && !empty($post->post_type)) {
    if(!empty($filter[‘post_type’])){
    if(preg_match(“#{$post->post_type}#”, $filter[‘post_type’])){
    if(!empty($filter[‘taxonomies’]) && !empty($filter[‘term’])){
    if(self::is_term_in_taxonomy( $post_id, $filter[‘term’], $filter[‘taxonomies’])){
    $group = $filter[‘group’];
    }
    } else {
    $group = $filter[‘group’];
    }
    }
    } else {
    if(!empty($filter[‘taxonomies’]) && !empty($filter[‘term’])){
    if(self::is_term_in_taxonomy( $post_id, $filter[‘term’], $filter[‘taxonomies’])){
    $group = $filter[‘group’];
    }
    } else {
    $group = $filter[‘group’];
    }
    }
    }
    }
    } else {
    $group = $filter[‘group’];
    }
    }
    return($group);
    }

    static function plugin_keygen( $fname, $option ) {
    $key = false;
    if($option === ‘jetpack_active_modules’){
    $key = ‘jetpack_module/’ . $fname;
    } elseif($option === ‘celtispack_active_modules’){
    $key = ‘celtispack_module/’ . str_replace( ‘.php’, ”, basename( $fname ) );
    } else {
    $key = $fname;
    }
    return $key;
    }

    /**
    * Get valid plugins list for groupkey (for addon optional)
    * @param $groupkey : url filter group name
    * @param $filter : plf filtering setting data
    * @param $option : option data eg. ‘active_plugins’, ‘active_sitewide_plugins’, ‘jetpack_active_modules’ …
    * @param $plugins : active plugins values before filtering
    * @return data values after filtering
    */
    static function filter_to_active_plugins( $groupkey, $filter, $option, $plugins ){
    $new_plugins = array();
    foreach ( $plugins as $item ) {
    if(!empty($item)){
    $unload = false;
    $p_key = self::plugin_keygen( $item, $option );
    if(!empty($filter[‘plfurlkey’][$groupkey][‘plugins’])){
    if(false !== strpos($filter[‘plfurlkey’][$groupkey][‘plugins’], $p_key))
    $unload = true;
    }
    if(!$unload) {
    if($option === ‘active_sitewide_plugins’){
    // v4.0.6 $new_plugins[$item] = $plugins[$item];
    $new_plugins[$item] = $item;
    } else {
    $new_plugins[] = $item;
    }
    }
    }
    }
    return $new_plugins;
    }

    //Plugin Load Filter Main (active plugins/modules filtering)
    static function plf_filter( $option, $default = false) {
    if(self::$flag_stop)
    return $default;


    // v4.0.6 if ( defined( ‘WP_SETUP_CONFIG’ ) || did_action( ‘muplugins_loaded’ ) === 0)
    if ( defined( ‘WP_SETUP_CONFIG’ ) || did_action( ‘mu_plugin_loaded’ ) === 0)
    return false;

    if ( ! defined( ‘WP_INSTALLING’ ) ) {
    global $wpdb, $current_site;
    if ( is_multisite() && $option === ‘active_sitewide_plugins’ ) {
    //get_network_option() current site ID
    $network_id = $current_site->id;

    // prevent non-existent options from triggering multiple queries
    $notoptions_key = “$network_id:notoptions”;
    $notoptions = wp_cache_get( $notoptions_key, ‘site-options’ );
    if ( isset( $notoptions[ $option ] ) ) {
    return apply_filters( ‘default_site_option_’ . $option, $default, $option );
    }

    $cache_key = “$network_id:$option”;
    $opt_value = wp_cache_get( $cache_key, ‘site-options’ );

    if ( ! isset( $opt_value ) || false === $opt_value ) {
    $row = $wpdb->get_row( $wpdb->prepare( “SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d”, $option, $network_id ) );

    // Has to be get_row instead of get_var because of funkiness with 0, false, null values
    if ( is_object( $row ) ) {
    $opt_value = $row->meta_value;
    $opt_value = maybe_unserialize( $opt_value );
    wp_cache_set( $cache_key, $opt_value, ‘site-options’ );
    } else {
    if ( ! is_array( $notoptions ) ) {
    $notoptions = array();
    }
    $notoptions[ $option ] = true;
    wp_cache_set( $notoptions_key, $notoptions, ‘site-options’ );

    /** This filter is documented in wp-includes/option.php */
    $opt_value = apply_filters( ‘default_site_option_’ . $option, $default, $option );
    }
    }
    } else {
    // prevent non-existent options from triggering multiple queries
    $notoptions = wp_cache_get( ‘notoptions’, ‘options’ );
    if ( isset( $notoptions[$option] ) )
    return apply_filters( ‘default_option_’ . $option, $default );

    $alloptions = wp_load_alloptions();
    if ( isset( $alloptions[$option] ) ) {
    $opt_value = $alloptions[$option];
    } else {
    $opt_value = wp_cache_get( $option, ‘options’ );

    if ( false === $opt_value ) {
    $row = $wpdb->get_row( $wpdb->prepare( “SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1”, $option ) );

    // Has to be get_row instead of get_var because of funkiness with 0, false, null values
    if ( is_object( $row ) ) {
    $opt_value = $row->option_value;
    wp_cache_add( $option, $opt_value, ‘options’ );
    } else { // option does not exist, so we must cache its non-existence
    if ( ! is_array( $notoptions ) ) {
    $notoptions = array();
    }
    $notoptions[$option] = true;
    wp_cache_set( ‘notoptions’, $notoptions, ‘options’ );

    /** This filter is documented in wp-includes/option.php */
    return apply_filters( ‘default_option_’ . $option, $default, $option );
    }
    }
    }
    }
    } else {
    return false;
    }

    $req_url = (isset($_SERVER[‘REQUEST_URI’]))? $_SERVER[‘REQUEST_URI’] : ”;
    $req_url = str_replace( “\\”, “/”, $req_url);
    $parse_url = parse_url($req_url);
    $action = (!empty($parse_url[‘path’]) && strpos($parse_url[‘path’], ‘admin-ajax.php’ ) !== false && isset($_REQUEST[‘action’]))? esc_attr($_REQUEST[‘action’]) : ”;

    $act_plugins = ($option === ‘active_sitewide_plugins’)? array_keys( (array)$opt_value ) : maybe_unserialize( $opt_value );
    if($option === ‘celtispack_active_modules’){
    if(empty(self::$base_plugins[‘celtispack-addon/celtispack-addon.php’])){
    $opt = get_option( ‘celtis_addon_options’, array() );
    if(!empty($opt[‘active_modules’])){
    $nact_plugins = array();
    foreach ($act_plugins as $pkey) {
    if(!empty($pkey)){
    $key = str_replace( ‘.php’, ”, basename( $pkey ));
    if(!empty($opt[‘active_modules’][$key]))
    continue;
    $nact_plugins[] = $pkey;
    }
    }
    $act_plugins = $nact_plugins;
    }
    }
    }

    //Equal treatment for when the wp_is_mobile is not yet available(wp-include/vars.php wp_is_mobile)
    if ( empty($_SERVER[‘HTTP_USER_AGENT’]) ) {
    $is_mobile = false;
    } elseif ( strpos($_SERVER[‘HTTP_USER_AGENT’], ‘Mobile’) !== false // many mobile devices (all iPhone, iPad, etc.)
    || strpos($_SERVER[‘HTTP_USER_AGENT’], ‘Android’) !== false
    || strpos($_SERVER[‘HTTP_USER_AGENT’], ‘Silk/’) !== false
    || strpos($_SERVER[‘HTTP_USER_AGENT’], ‘Kindle’) !== false
    || strpos($_SERVER[‘HTTP_USER_AGENT’], ‘BlackBerry’) !== false
    || strpos($_SERVER[‘HTTP_USER_AGENT’], ‘Opera Mini’) !== false
    || strpos($_SERVER[‘HTTP_USER_AGENT’], ‘Opera Mobi’) !== false ) {
    $is_mobile = true;
    } else {
    $is_mobile = false;
    }
    $is_mobile = apply_filters( ‘custom_is_mobile’ , $is_mobile );

    //get_option is called many times, intermediate processing data to cache
    $keyid = md5(‘plf_’. (string)$is_mobile . $req_url . $action);
    if(!empty(self::$cache[$keyid][$option])){

    //self::$counter++;
    //if(self::$counter == 6)
    // throw new Exception(print_r(self::$cache[$keyid][$option], true) . self::$counter);


    return self::$cache[$keyid][$option];
    }

    //Before plugins loaded, it does not use conditional branch such as is_home, to set wp_query, wp in temporary query
    if(empty($GLOBALS[‘wp_the_query’])){
    // プラグイン無効化時等で rewrite_rule がクリアされると rewrite_rule が更新されるまでカスタムポストタイプを判定できずにカスタムポストタイプのページはホームへ飛ばされる
    // 但し、permlink structure が plain(基本) の場合は除く
    if(!empty(get_option( ‘permalink_structure’ ))){
    $rewrite_rules = get_option(‘rewrite_rules’);
    // rewrite_rule を監視して変更された場合はプラグインのフィルタリングをスキップさせていたが、
    // plugin activate / deactivate を監視するように変更したのでここでは空の場合のみチェック
    if(empty($rewrite_rules)){
    return false;
    }
    // Welcart usces_itemnew 新規商品追加時のエラー (A variable mismatch has been detected.) parse_request で発生してるので特別に回避
    if ( isset( $_GET[ ‘page’ ] ) && isset( $_POST[ ‘page’ ] ) && $_GET[ ‘page’ ] !== $_POST[ ‘page’ ] ) {
    return false;
    }
    }

    $GLOBALS[‘wp_the_query’] = new WP_Query();
    $GLOBALS[‘wp_query’] = $GLOBALS[‘wp_the_query’];
    $GLOBALS[‘wp_rewrite’] = new WP_Rewrite();
    $GLOBALS[‘wp’] = new WP();
    self::$base_public_query_vars = $GLOBALS[‘wp’]->public_query_vars;
    //register_taxonomy(category, post_tag, post_format) support for is_archive
    self::force_initial_taxonomies();
    //Post Format, Custom Post Type support
    add_action(‘parse_request’, array(‘Plf_filter’, ‘parse_request’));
    add_filter(‘doing_it_wrong_trigger_error’, array(‘Plf_filter’, ‘exclude_trigger_error’), 10, 4 );
    $GLOBALS[‘wp’]->parse_request(”);
    $GLOBALS[‘wp’]->query_posts();
    }

    //active plugin data
    foreach ($act_plugins as $key) {
    if(!empty($key)){
    $key = self::plugin_keygen( $key, $option );
    self::$base_plugins[$key] = $key;
    }
    }

    $filter = self::$filter;

    //plf Addon Extract only target data
    $devtype = ($is_mobile)? ‘mobile’ : ‘desktop’;
    $urltype = (!empty($parse_url[‘path’]) && strpos($parse_url[‘path’], ‘/wp-admin’ ) !== false)? ‘admin’ : ‘front’;
    if(!empty(self::$url_filter) && empty(self::$s_url_filter)){
    self::$s_url_filter = self::get_url_filter( ‘active’, $urltype, $devtype );
    }


    //======== The following are Admin backend page processes ========

    if($urltype === ‘admin’){
    if(!empty(self::$s_url_filter)){
    //plf Addon Admin Backend URL filtering
    foreach (self::$s_url_filter as $key => $v) {
    if(!empty($v)){
    $groupkey = self::is_url_match( $req_url, $parse_url, $v );
    if($groupkey !== false) {
    self::$is_filterkey = ‘url-group-filter : ‘ . $groupkey;
    $new_plugins = self::filter_to_active_plugins( $groupkey, $filter, $option, $act_plugins );
    self::$cache[$keyid][$option] = $new_plugins;
    foreach ($new_plugins as $key) {
    if(!empty($key)){
    $key = self::plugin_keygen( $key, $option );
    self::$filtered_plugins[$key] = $key;
    }
    }
    return $new_plugins;
    }
    }
    }
    }
    return false;
    }


    //======== The following are frontend page processes ========

    global $wp_query;
    $unknown = false;
    if( ! is_embed() ){
    if((is_home() || is_front_page() || is_archive() || is_search() || is_singular()) == false || (is_home() && !empty($_GET))) {
    //bbPress users page requests are treated the same as is_home
    //downloadmanager plugin downloadlink request [home]/?wpdmact=XXXXXX exclude home GET query
    $unknown = true;

    } elseif(is_singular() && empty($wp_query->post)){
    //documentroot special php file (wp-login.php, wp-cron.php, etc) これらはこの時点では singular とみなされるが post が設定されていないことで判別
    //フィルタリングしたい場合は urlfilter Addon を使用すること
    //但し、private (非公開)ページ時は post がこの時点ではまだ設定されていないので private でクエリー発行して再確認
    if(!empty($parse_url[‘path’]) && strpos( $parse_url[‘path’], ‘.php’ ) === false && !empty($wp_query->query)) {
    //get post for private
    $query = $wp_query->query;
    $query[‘post_status’] = ‘private’;
    $r = new WP_Query( $query );
    if ($r->have_posts()) {
    if(!empty($r->post)){
    $wp_query->posts = $r->posts;
    $wp_query->post = $r->post;
    }
    } else {
    //カスタムステータスがまだ登録されてない状態でも取得 posts 情報がクリアされないよう抑制
    add_filter( ‘map_meta_cap’, array(‘Plf_filter’, ‘exclude_map_meta_cap’), 10, 4 );
    $query[‘post_status’] = ‘any’;
    $r = new WP_Query( $query );
    if ($r->have_posts()) {
    if(!empty($r->post)){
    $wp_query->posts = $r->posts;
    $wp_query->post = $r->post;
    }
    }
    }
    }
    if(empty($wp_query->post)){
    $unknown = true;
    }
    }
    }

    $single_opt = array();
    if(is_singular() && is_object($wp_query->post)){
    self::$pre_post_id = $wp_query->post->ID; //for post_locale()
    $myfilter = get_post_meta( $wp_query->post->ID, ‘_plugin_load_filter’, true );
    $default = array( ‘filter’ => ‘default’, ‘desktop’ => ”, ‘mobile’ => ”);
    $single_opt = (!empty($myfilter))? $myfilter : $default;
    $single_opt = wp_parse_args( $single_opt, $default);
    }
    if(!empty(self::$s_url_filter)){
    //Addon frontend URL filtering
    //個別フィルター有効なシングラーは URL filtering 無効(個別フィルター優先)
    if(empty($single_opt) || $single_opt[‘filter’] === ‘default’){
    foreach (self::$s_url_filter as $key => $v) {
    if(!empty($v)){
    $groupkey = self::is_url_match( $req_url, $parse_url, $v );
    if($groupkey !== false) {
    self::$is_filterkey = ‘url-group-filter : ‘ . $groupkey;
    $new_plugins = self::filter_to_active_plugins( $groupkey, $filter, $option, $act_plugins );
    self::$cache[$keyid][$option] = $new_plugins;
    foreach ($new_plugins as $key) {
    if(!empty($key)){
    $key = self::plugin_keygen( $key, $option );
    self::$filtered_plugins[$key] = $key;
    }
    }
    return $new_plugins;
    }
    }
    }
    }
    }
    if($unknown || empty($parse_url[‘path’]) || strpos($parse_url[‘path’], ‘/wp-cron’ ) !== false || strpos($parse_url[‘path’], ‘/wp-json’ ) !== false || (!empty($parse_url[‘query’]) && strpos($parse_url[‘query’], ‘rest_route=’ ) !== false )){
    //url filter 処理後、REST api, cron, フィルター対象外の不明なリクエストはフィルタリング処理を行わない
    return false;
    }

    //plf standard filtering
    $type = false;
    if(!empty($filter[‘_pagefilter’][‘plugins’])){
    if(is_embed()){
    $type = ‘content-card’;
    } elseif(is_home() || is_front_page()){
    $type = ‘home’;
    } elseif(is_archive()) {
    $type = ‘archive’;
    } elseif(is_search()) {
    $type = ‘search’;
    } elseif(is_attachment()) {
    $type = ‘attachment’;
    } elseif(is_page()) {
    $type = ‘page’;
    } elseif(is_single()){ //Post & Custom Post
    $type = get_post_type( $wp_query->post);
    //bbPress private (非公開)ページ時のポストタイプ取得
    if($type === false && isset($wp_query->query_vars[‘post_type’])){
    $type = $wp_query->query_vars[‘post_type’];
    }
    if($type === ‘post’){
    $fmt = get_post_format( $wp_query->post);
    $type = ($fmt === ‘standard’ || $fmt == false)? ‘post’ : “post-$fmt”;
    }
    } else {
    $type = ‘unknown’;
    }
    self::$is_filterkey = ‘page-type-filter : ‘ . $type;
    if(is_singular()){
    if(!empty($single_opt) && $single_opt[‘filter’] === ‘include’){
    self::$is_filterkey = ‘page-type-filter : Single page option’;
    }
    }
    } elseif(!empty($filter[‘_admin’][‘plugins’])){
    //Page Type 未指定時は admin type 除外フィルターのみ
    self::$is_filterkey = ‘page-type-filter : admin filter’;
    }

    $new_plugins = array();
    foreach ( $act_plugins as $item ) {
    if(!empty($item)){
    $unload = false;
    $p_key = self::plugin_keygen( $item, $option );
    //admin filter
    if(!empty($filter[‘_admin’][‘plugins’])){
    if(in_array($p_key, array_map(“trim”, explode(‘,’, $filter[‘_admin’][‘plugins’])))){
    $unload = true;
    }
    }
    //page filter
    if(!$unload){
    if(!empty($filter[‘_pagefilter’][‘plugins’])){
    if(in_array($p_key, array_map(“trim”, explode(‘,’, $filter[‘_pagefilter’][‘plugins’])))){
    $unload = true;

    //desktop/mobile device disable filter
    $dis_dev = true;
    if(is_singular() && is_object($wp_query->post)){
    if(!empty($single_opt) && $single_opt[‘filter’] === ‘include’){
    if(!empty($single_opt[$devtype])){
    if(false !== strpos($single_opt[$devtype], $p_key))
    $dis_dev = false;
    elseif(strpos($p_key, ‘jetpack/’) !== false && strpos($single_opt[$devtype], ‘jetpack_module/’) !== false)
    $dis_dev = false;
    elseif(strpos($p_key, ‘celtispack/’) !== false && strpos($single_opt[$devtype], ‘celtispack_module/’) !== false)
    $dis_dev = false;
    }
    }
    }
    if(empty($single_opt) || $single_opt[‘filter’] === ‘default’){
    if(!empty($filter[‘group’][$devtype][‘plugins’])){
    if(false !== strpos($filter[‘group’][$devtype][‘plugins’], $p_key))
    $dis_dev = false;
    elseif(strpos($p_key, ‘jetpack/’) !== false && strpos($filter[‘group’][$devtype][‘plugins’], ‘jetpack_module/’) !== false)
    $dis_dev = false;
    elseif(strpos($p_key, ‘celtispack/’) !== false && strpos($filter[‘group’][$devtype][‘plugins’], ‘celtispack_module/’) !== false)
    $dis_dev = false;
    }
    }
    if(!$dis_dev){
    //oEmbed Content API
    if(is_embed()){
    if(!empty($type) && !empty($filter[‘group’][$type][‘plugins’])){
    if(false !== strpos($filter[‘group’][$type][‘plugins’], $p_key))
    $unload = false;
    elseif(strpos($p_key, ‘jetpack/’) !== false && strpos($filter[‘group’][$type][‘plugins’], ‘jetpack_module/’) !== false)
    $unload = false;
    elseif(strpos($p_key, ‘celtispack/’) !== false && strpos($filter[‘group’][$type][‘plugins’], ‘celtispack_module/’) !== false)
    $unload = false;
    }
    } else {
    $pgfopt = false;
    if(is_singular()){
    if(!empty($single_opt) && $single_opt[‘filter’] === ‘include’){
    $pgfopt = true;
    if(!empty($single_opt[$devtype])){
    if(false !== strpos($single_opt[$devtype], $p_key)){
    $unload = false;
    } else {
    //Enable plugin because plugin module is selected
    if(strpos($p_key, ‘jetpack/’) !== false && strpos($single_opt[$devtype], ‘jetpack_module/’) !== false)
    $unload = false;
    elseif(strpos($p_key, ‘celtispack/’) !== false && strpos($single_opt[$devtype], ‘celtispack_module/’) !== false)
    $unload = false;
    }
    }
    }
    }
    if($pgfopt === false){
    if(!empty($type) && !empty($filter[‘group’][$type][‘plugins’])){
    if(in_array($p_key, array_map(“trim”, explode(‘,’, $filter[‘group’][$type][‘plugins’])))){
    $unload = false;
    } else {
    if(strpos($p_key, ‘jetpack/’) !== false && strpos($filter[‘group’][$type][‘plugins’], ‘jetpack_module/’) !== false)
    $unload = false;
    else if(strpos($p_key, ‘celtispack/’) !== false && strpos($filter[‘group’][$type][‘plugins’], ‘celtispack_module/’) !== false)
    $unload = false;
    }
    }
    }
    }
    }
    }
    }
    }
    if(!$unload) {
    if($option === ‘active_sitewide_plugins’) {
    // v4.0.6 $new_plugins[$item] = $opt_value[$item];
    $new_plugins[$item] = $item;
    } else {
    $new_plugins[] = $item;
    }
    }
    }
    }

    $new_plugins = apply_filters(‘exclude_plugins_filter_custom’, $new_plugins);

    self::$cache[$keyid][$option] = $new_plugins;
    foreach ($new_plugins as $key) {
    if(!empty($key)){
    $key = self::plugin_keygen( $key, $option );
    self::$filtered_plugins[$key] = $key;
    }
    }

    //self::$counter++;
    //if(self::$counter == 6)
    // throw new Exception(print_r(self::$cache[$keyid][$option], true) . self::$counter);



    return $new_plugins;
    }


    }

    Thread Starter Jack

    (@jack1132132)

    The code basically removes all filters and actions of plf when any of these hooks are fired: ‘activate_plugin’, ‘plugins_loaded’, ‘deactivated_plugin’, ‘pre_update_site_option_active_plugins’, ‘pre_update_option_active_plugins’.

    And I add a stop_flag to make sure static function plf_filter isn’t called.


    Thank you.

Viewing 15 replies - 1 through 15 (of 17 total)
  • The topic ‘Function to retriev user before init hook is fired’ is closed to new replies.