HEX
Server: nginx/1.27.1
System: Linux in-3 5.15.0-161-generic #171-Ubuntu SMP Sat Oct 11 08:17:01 UTC 2025 x86_64
User: ivenus-clone (3297)
PHP: 7.4.33
Disabled: exec,passthru,shell_exec,system,proc_open,popen,parse_ini_file,show_source
Upload Files
File: /storage/v4513/ivenusin/public_html/wp-content/plugins/object-cache-pro/src/Plugin/Settings.php
<?php
/**
 * Copyright © Rhubarb Tech Inc. All Rights Reserved.
 *
 * All information contained herein is, and remains the property of Rhubarb Tech Incorporated.
 * The intellectual and technical concepts contained herein are proprietary to Rhubarb Tech Incorporated and
 * are protected by trade secret or copyright law. Dissemination and modification of this information or
 * reproduction of this material is strictly forbidden unless prior written permission is obtained from
 * Rhubarb Tech Incorporated.
 *
 * You should have received a copy of the `LICENSE` with this file. If not, please visit:
 * https://objectcache.pro/license.txt
 */

declare(strict_types=1);

namespace RedisCachePro\Plugin;

trait Settings
{
    /**
     * Holds the plugin basename.
     *
     * @var string
     */
    protected $baseurl;

    /**
     * The settings page screen identifier.
     *
     * @var string
     */
    protected $screenId;

    /**
     * Instances of all setting pages.
     *
     * @var \RedisCachePro\Plugin\Pages\Pages
     */
    private $pages;

    /**
     * Boot settings component.
     *
     * @return void
     */
    public function bootSettings()
    {
        add_action('init', [$this, 'registerOptionsSetting']);

        add_action('rest_api_init', [new Api\Latency, 'register_routes']);
        add_action('rest_api_init', [new Api\Groups, 'register_routes']);

        add_action('admin_init', [$this, 'maybeRedirectToSettings']);
        add_action('current_screen', [$this, 'setUpSettingsScreen']);

        add_action('admin_enqueue_scripts', [$this, 'maybeEnqueuePointer']);

        add_filter('option_page_capability_objectcache', [$this, 'screenCapability']);
        add_filter('set_screen_option_objectcache_screen_options', [$this, 'sanitizeScreenOptions'], 10, 3);

        if (is_multisite()) {
            add_action('network_admin_menu', [$this, 'registerMenu']);
            add_action('network_admin_edit_objectcache-update', [$this, 'saveNetworkSettings']);

            add_action('current_screen', [$this, 'maybeRedirectToNetworkSettings'], -1);

            $this->baseurl = 'settings.php?page=objectcache';
            $this->screenId = 'settings_page_objectcache-network';
        } else {
            add_action('admin_menu', [$this, 'registerMenu']);

            $this->baseurl = 'options-general.php?page=objectcache';
            $this->screenId = 'settings_page_objectcache';
        }

        add_action('wp_ajax_objectcache-options', [$this, 'ajax_options']);
    }

    /**
     * Returns the plugin's base URL.
     *
     * @return string
     */
    public function baseurl()
    {
        return $this->baseurl;
    }

    /**
     * Returns the plugin's screen identifier.
     *
     * @return string
     */
    public function screenId()
    {
        return $this->screenId;
    }

    /**
     * Return the capability needed to access the settings page.
     *
     * @return string
     */
    public function screenCapability()
    {
        return self::Capability;
    }

    /**
     * Set up the settings page, if the current screen matches.
     *
     * @param  WP_Screen  $screen
     * @return void
     */
    public function setUpSettingsScreen($screen)
    {
        if ($screen->id !== $this->screenId) {
            return;
        }

        add_action('in_admin_header', [$this, 'renderNavbar']);
        add_action('in_admin_header', [$this, 'removeForeignNotices'], PHP_INT_MAX);
        add_action('admin_enqueue_scripts', [$this, 'enqueueAdminAssets']);

        add_filter('update_footer', [$this, 'settingsFooterUpdate'], PHP_INT_MAX);
        add_filter('admin_footer_text', [$this, 'settingsFooterText'], PHP_INT_MAX);

        $this->pages = new Pages\Pages($this);

        if (! $this->pages->current()->isEnabled()) {
            wp_die('Sorry, you are not allowed to access this page.', 403);
        }
    }

    /**
     * Register the menu item.
     *
     * @return void
     */
    public function registerMenu()
    {
        global $wp_version;

        $isMultisite = is_multisite();
        $inNetworkAdmin = is_network_admin();

        $update = get_site_transient('objectcache_update');
        $updateAvailable = version_compare($update->version ?? '', '12.0', '>');

        $parameters = [
            $isMultisite && $inNetworkAdmin
                ? 'settings.php'
                : 'options-general.php',
            'Object Cache Pro',
            sprintf(
                'Object Cache %s',
                $updateAvailable ? '<span class="update-plugins count-1"><span class="update-count">1</span></span>' : ''
            ),
            $isMultisite ? 'manage_network_options' : self::Capability,
            'objectcache',
            function () {
                $this->pages->current()->render();
            },
        ];

        if (version_compare($wp_version, '5.3', '>=')) {
            $parameters[] = 7;
        }

        add_submenu_page(...$parameters);
    }

    /**
     * Register the plugin settings.
     *
     * @return void
     */
    public function registerOptionsSetting()
    {
        register_setting(
            'objectcache',
            'objectcache_options',
            [
                'default' => $this->defaultOptions(),
                'sanitize_callback' => [$this, 'sanitizeOptions'],
            ]
        );

        add_action('update_option_objectcache_options', function ($old_value, $value) {
            $this->optionsUpdated($value, $old_value);
        }, 10, 2);

        add_action('update_site_option_objectcache_options', function ($option, $value, $old_value) {
            $this->optionsUpdated($value, $old_value);
        }, 10, 3);
    }

    /**
     * Called when the `objectcache_options` option has been changed.
     *
     * @param  array  $new
     * @param  array  $old
     * @return void
     */
    protected function optionsUpdated($new, $old)
    {
        $defaults = $this->defaultOptions();
        $new = wp_parse_args($new, $defaults);
        $old = wp_parse_args($old, $defaults);

        if ($new['channel'] !== $old['channel']) {
            wp_clean_plugins_cache();
        }
    }

    /**
     * Returns all options or their default values.
     *
     * @return array
     */
    public function options()
    {
        $defaults = $this->defaultOptions();
        $options = get_site_option('objectcache_options', $defaults);

        if (is_array($options)) {
            return wp_parse_args($options, $defaults);
        }

        return $defaults;
    }

    /**
     * Returns the option value or its default value.
     *
     * @param  string  $name
     * @return mixed
     */
    public function option($name)
    {
        return $this->options()[$name] ?? null;
    }

    /**
     * Returns the default options.
     *
     * @return array
     */
    public function defaultOptions()
    {
        $defaults = [
            'channel' => 'stable',
            'flushlog' => false,
        ];

        /**
         * Filters the default options.
         *
         * @param  array  $defaults  Array of default options.
         */
        $filteredDefaults = (array) apply_filters('objectcache_default_options', $defaults);

        return array_filter(
            wp_parse_args($filteredDefaults, $defaults),
            function ($name) use ($defaults) {
                return array_key_exists($name, $defaults);
            },
            ARRAY_FILTER_USE_KEY
        );
    }

    /**
     * Sanitize and validate options.
     *
     * @see registerOptionsSetting()
     *
     * @param  array  $input
     * @return void
     */
    public function sanitizeOptions($input)
    {
        $options = $this->options();
        $defaults = $this->defaultOptions();

        $sanitizer = new Options\Sanitizer;
        $validator = new Options\Validator($this);

        $input = array_filter((array) $input, function ($name) use ($defaults) {
            return array_key_exists($name, $defaults);
        }, ARRAY_FILTER_USE_KEY);

        array_walk($input, function (&$value, $name) use ($sanitizer, $validator, $options) {
            $value = $sanitizer->{$name}($value);
            $error = $validator->{$name}($value);

            if (is_wp_error($error)) {
                $value = $options[$name];

                add_settings_error('objectcache_options', $error->get_error_code(), $error->get_error_message());
            }
        });

        return $input;
    }

    /**
     * Sanitize the screen options before saving.
     *
     * @see set_screen_options()
     *
     * @param  false  $screen_option
     * @param  string  $option
     * @param  array  $value
     * @return void
     */
    public function sanitizeScreenOptions($screen_option, $option, $value)
    {
        return [
            'interval' => (int) $value['analytics_interval'] ?? 0,
            'refresh' => (bool) $value['analytics_refresh'] ?? false,
        ];
    }

    /**
     * Maybe redirect to the settings page if the plugin was just activated.
     *
     * @return void
     */
    public function maybeRedirectToSettings()
    {
        $nonce = \get_transient('objectcache_activated');

        if (! $nonce) {
            return;
        }

        if (! \wp_verify_nonce($nonce, 'objectcache-activated')) {
            return;
        }

        if (! \current_user_can(self::Capability)) {
            return;
        }

        \delete_transient('objectcache_activated');

        \wp_safe_redirect(\network_admin_url($this->baseurl), 302, 'Object Cache Pro');
        exit;
    }

    /**
     * In multisite environments redirect setting pages to the Network Admin.
     *
     * @param  WP_Screen  $screen
     * @return void
     */
    public function maybeRedirectToNetworkSettings($screen)
    {
        if ($screen->id !== 'settings_page_objectcache') {
            return;
        }

        wp_safe_redirect(network_admin_url($this->baseurl), 302, 'Object Cache Pro');
        exit;
    }

    /**
     * Shim for WP's missing Settings API handling in multisite environments.
     *
     * @see bootSettings()
     *
     * @return void
     */
    public function saveNetworkSettings()
    {
        check_admin_referer('objectcache-options');

        if (! current_user_can('manage_network_options')) {
            wp_die('Sorry, you are not allowed to manage options for this site.');
        }

        if (! empty($_POST['objectcache_options'])) {
            update_site_option('objectcache_options', wp_unslash($_POST['objectcache_options']));
        }

        if (! count(get_settings_errors())) {
            add_settings_error('general', 'settings_updated', 'Settings saved.', 'success');
        }

        set_transient('settings_errors', get_settings_errors(), 30);

        wp_redirect(add_query_arg('settings-updated', 'true', wp_get_referer()));
        exit;
    }

    /**
     * Enqueue the settings page stylesheet.
     *
     * @see setUpSettingsScreen()
     *
     * @return void
     */
    public function enqueueAdminAssets()
    {
        $styles = $this->asset('css/settings.css');
        $styles = false;

        if ($styles) {
            wp_enqueue_style('objectcache-settings', $styles, [], $this->version);
        } else {
            wp_add_inline_style('common', $this->inlineAsset('css/settings.css'));
        }
    }

    /**
     * Renders the settings navigation bar.
     *
     * @see setUpSettingsScreen()
     *
     * @return void
     */
    public function renderNavbar()
    {
        require __DIR__ . '/templates/navbar.phtml';
    }

    /**
     * Returns the `admin_footer_text` content.
     *
     * @see setUpSettingsScreen()
     *
     * @return string
     */
    public function settingsFooterText()
    {
        ob_start();

        require __DIR__ . '/templates/footer.phtml';

        return ob_get_clean();
    }

    /**
     * Returns the `update_footer` content.
     *
     * @see setUpSettingsScreen()
     *
     * @return string
     */
    public function settingsFooterUpdate()
    {
        return sprintf('Version %s', $this->version);
    }

    /**
     * Callback for `objectcache-options` AJAX request.
     *
     * @see Settings::bootSettings()
     *
     * @return void
     */
    public function ajax_options()
    {
        check_ajax_referer('objectcache-options', 'nonce');

        if (! current_user_can(self::Capability)) {
            wp_die('Sorry, you are not allowed to manage options for this site.');
        }

        $options = $this->options();

        $sanitizer = new Options\Sanitizer;
        $validator = new Options\Validator($this);

        foreach (array_keys($options) as $name) {
            if (isset($_POST[$name])) {
                $value = $sanitizer->{$name}(wp_unslash($_POST[$name]));

                if (! is_wp_error($validator->{$name}($value))) {
                    $options[$name] = $value;
                }
            }
        }

        update_site_option('objectcache_options', $options);
        wp_die(1);
    }

    /**
     * Maybe enqueue pointer.
     *
     * @param  string  $hook_suffix
     * @return void
     */
    public function maybeEnqueuePointer($hook_suffix)
    {
        if (! current_user_can(self::Capability)) {
            return;
        }

        if (! in_array($hook_suffix, ['index.php', 'plugins.php'], true)) {
            return;
        }

        if (is_multisite() && ! is_network_admin()) {
            return;
        }

        $current_user = get_current_user_id();
        $dismissed = explode(',', (string) get_user_meta($current_user, 'dismissed_wp_pointers', true));

        if (in_array('objectcache-setting-pointer', $dismissed, true)) {
            return;
        }

        wp_register_script('objectcache-pointer', null, ['jquery', 'wp-pointer']);
        wp_enqueue_script('objectcache-pointer');

        $content = sprintf(
            'You can now access Object Cache Pro more easily. Open %s to see cache analytics and configure the various features included in the plugin.',
            sprintf(
                '<a href="%s">%s</a>',
                network_admin_url($this->baseurl),
                'Settings > Object Cache'
            )
        );

        wp_localize_script('objectcache-pointer', 'objectcache_pointer', [
            'heading' => 'Object Cache Pro',
            'content' => wp_kses($content, ['a' => ['href' => []]]),
        ]);

        wp_add_inline_script('objectcache-pointer', $this->inlineAsset('js/pointer.js'));
    }

    /**
     * STFU!
     *
     * @return void
     */
    public function removeForeignNotices()
    {
        global $wp_filter;

        foreach ([
            'admin_notices',
            'all_admin_notices',
            'user_admin_notices',
            'network_admin_notices',
        ] as $hook) {
            foreach ($wp_filter[$hook] ?? [] as $priority => $callbacks) {
                foreach ($callbacks as $idx => $callback) {
                    if (
                        is_array($callback['function']) &&
                        is_object($callback['function'][0]) &&
                        preg_match('/^(Redis|Object)CachePro\\\/', get_class($callback['function'][0]))
                    ) {
                        continue;
                    }

                    unset($wp_filter[$hook]->callbacks[$priority][$idx]);
                }
            }
        }
    }
}