r( 'option_' . $this->option_name, [ $this, 'get_option' ] ); } /** * Merge an option with its default values. * * This method should *not* be called directly!!! It is only meant to filter the get_option() results. * * @param mixed $options Option value. * * @return mixed Option merged with the defaults for that option. */ public function get_option( $options = null ) { $filtered = $this->array_filter_merge( $options ); /* * If the option contains variable option keys, make sure we don't remove those settings * - even if the defaults are not complete yet. * Unfortunately this means we also won't be removing the settings for post types or taxonomies * which are no longer in the WP install, but rather that than the other way around. */ if ( isset( $this->variable_array_key_patterns ) ) { $filtered = $this->retain_variable_keys( $options, $filtered ); } return $filtered; } /* *********** METHODS influencing add_option(), update_option() and saving from admin pages. *********** */ /** * Register (whitelist) the option for the configuration pages. * The validation callback is already registered separately on the sanitize_option hook, * so no need to double register. * * @return void */ public function register_setting() { if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { return; } if ( $this->multisite_only === true ) { $network_settings_api = Yoast_Network_Settings_API::get(); if ( $network_settings_api->meets_requirements() ) { $network_settings_api->register_setting( $this->group_name, $this->option_name ); } return; } register_setting( $this->group_name, $this->option_name ); } /** * Validate the option. * * @param mixed $option_value The unvalidated new value for the option. * * @return array Validated new value for the option. */ public function validate( $option_value ) { $clean = $this->get_defaults(); /* Return the defaults if the new value is empty. */ if ( ! is_array( $option_value ) || $option_value === [] ) { return $clean; } $option_value = array_map( [ 'WPSEO_Utils', 'trim_recursive' ], $option_value ); $old = $this->get_original_option(); if ( ! is_array( $old ) ) { $old = []; } $old = array_merge( $clean, $old ); $clean = $this->validate_option( $option_value, $clean, $old ); // Prevent updates to variables that are disabled via the override option. $clean = $this->prevent_disabled_options_update( $clean, $old ); /* Retain the values for variable array keys even when the post type/taxonomy is not yet registered. */ if ( isset( $this->variable_array_key_patterns ) ) { $clean = $this->retain_variable_keys( $option_value, $clean ); } $this->remove_default_filters(); return $clean; } /** * Checks whether a specific option key is disabled. * * This is determined by whether an override option is available with a key that equals the given key prefixed * with 'allow_'. * * @param string $key Option key. * * @return bool True if option key is disabled, false otherwise. */ public function is_disabled( $key ) { $override_option = $this->get_override_option(); if ( empty( $override_option ) ) { return false; } return isset( $override_option[ self::ALLOW_KEY_PREFIX . $key ] ) && ! $override_option[ self::ALLOW_KEY_PREFIX . $key ]; } /** * All concrete classes must contain a validate_option() method which validates all * values within the option. * * @param array $dirty New value for the option. * @param array $clean Clean value for the option, normally the defaults. * @param array $old Old value of the option. */ abstract protected function validate_option( $dirty, $clean, $old ); /* *********** METHODS for ADDING/UPDATING/UPGRADING the option. *********** */ /** * Retrieve the real old value (unmerged with defaults). * * @return array|bool The original option value (which can be false if the option doesn't exist). */ protected function get_original_option() { $this->remove_default_filters(); $this->remove_option_filters(); // Get (unvalidated) array, NOT merged with defaults. if ( $this->multisite_only !== true ) { $option_value = get_option( $this->option_name ); } else { $option_value = get_site_option( $this->option_name ); } $this->add_option_filters(); $this->add_default_filters(); return $option_value; } /** * Add the option if it doesn't exist for some strange reason. * * @uses WPSEO_Option::get_original_option() * * @return void */ public function maybe_add_option() { if ( $this->get_original_option() === false ) { if ( $this->multisite_only !== true ) { update_option( $this->option_name, $this->get_defaults() ); } else { $this->update_site_option( $this->get_defaults() ); } } } /** * Update a site_option. * * {@internal This special method is only needed for multisite options, but very needed indeed there. * The order in which certain functions and hooks are run is different between * get_option() and get_site_option() which means in practice that the removing * of the default filters would be done too late and the re-adding of the default * filters might not be done at all. * Aka: use the WPSEO_Options::update_site_option() method (which calls this method) * for safely adding/updating multisite options.}} * * @param mixed $value The new value for the option. * * @return bool Whether the update was successful. */ public function update_site_option( $value ) { if ( $this->multisite_only === true && is_multisite() ) { $this->remove_default_filters(); $result = update_site_option( $this->option_name, $value ); $this->add_default_filters(); return $result; } else { return false; } } /** * Retrieve the real old value (unmerged with defaults), clean and re-save the option. * * @uses WPSEO_Option::get_original_option() * @uses WPSEO_Option::import() * * @param string|null $current_version Optional. Version from which to upgrade, if not set, * version-specific upgrades will be disregarded. * * @return void */ public function clean( $current_version = null ) { $option_value = $this->get_original_option(); $this->import( $option_value, $current_version ); } /** * Clean and re-save the option. * * @uses clean_option() method from concrete class if it exists. * * @todo [JRF/whomever] Figure out a way to show settings error during/after the upgrade - maybe * something along the lines of: * -> add them to a property in this class * -> if that property isset at the end of the routine and add_settings_error function does not exist, * save as transient (or update the transient if one already exists) * -> next time an admin is in the WP back-end, show the errors and delete the transient or only delete it * once the admin has dismissed the message (add ajax function) * Important: all validation routines which add_settings_errors would need to be changed for this to work * * @param array $option_value Option value to be imported. * @param string|null $current_version Optional. Version from which to upgrade, if not set, * version-specific upgrades will be disregarded. * @param array|null $all_old_option_values Optional. Only used when importing old options to * have access to the real old values, in contrast to * the saved ones. * * @return void */ public function import( $option_value, $current_version = null, $all_old_option_values = null ) { if ( $option_value === false ) { $option_value = $this->get_defaults(); } elseif ( is_array( $option_value ) && method_exists( $this, 'clean_option' ) ) { $option_value = $this->clean_option( $option_value, $current_version, $all_old_option_values ); } /* * Save the cleaned value - validation will take care of cleaning out array keys which * should no longer be there. */ if ( $this->multisite_only !== true ) { update_option( $this->option_name, $option_value ); } else { $this->update_site_option( $this->option_name, $option_value ); } } /** * Returns the variable array key patterns for an options class. * * @return array */ public function get_patterns() { return (array) $this->variable_array_key_patterns; } /** * Retrieves the option name. * * @return string The set option name. */ public function get_option_name() { return $this->option_name; } /* * Concrete classes *may* contain a clean_option method which will clean out old/renamed * values within the option. * * ``` * abstract public function clean_option( $option_value, $current_version = null, $all_old_option_values = null ); * ``` */ /* *********** HELPER METHODS for internal use. *********** */ /** * Helper method - Combines a fixed array of default values with an options array * while filtering out any keys which are not in the defaults array. * * @todo [JRF] - shouldn't this be a straight array merge ? at the end of the day, the validation * removes any invalid keys on save. * * @param array|null $options Optional. Current options. If not set, the option defaults * for the $option_key will be returned. * * @return array Combined and filtered options array. */ protected function array_filter_merge( $options = null ) { $defaults = $this->get_defaults(); if ( ! isset( $options ) || $options === false || $options === [] ) { return $defaults; } $options = (array) $options; /* $filtered = array(); if ( $defaults !== array() ) { foreach ( $defaults as $key => $default_value ) { // @todo should this walk through array subkeys ? $filtered[ $key ] = ( isset( $options[ $key ] ) ? $options[ $key ] : $default_value ); } } */ $filtered = array_merge( $defaults, $options ); return $filtered; } /** * Sets updated values for variables that are disabled via the override option back to their previous values. * * @param array $updated Updated option value. * @param array $old Old option value. * * @return array Updated option value, with all disabled variables set to their old values. */ protected function prevent_disabled_options_update( $updated, $old ) { $override_option = $this->get_override_option(); if ( empty( $override_option ) ) { return $updated; } /* * This loop could as well call `is_disabled( $key )` for each iteration, * however this would be worse performance-wise. */ foreach ( $old as $key => $value ) { if ( isset( $override_option[ self::ALLOW_KEY_PREFIX . $key ] ) && ! $override_option[ self::ALLOW_KEY_PREFIX . $key ] ) { $updated[ $key ] = $old[ $key ]; } } return $updated; } /** * Retrieves the value of the override option, if available. * * An override option contains values that may determine access to certain sub-variables * of this option. * * Only regular options in multisite can have override options, which in that case * would be network options. * * @return array Override option value, or empty array if unavailable. */ protected function get_override_option() { if ( empty( $this->override_option_name ) || $this->multisite_only === true || ! is_multisite() ) { return []; } return get_site_option( $this->override_option_name, [] ); } /** * Make sure that any set option values relating to post_types and/or taxonomies are retained, * even when that post_type or taxonomy may not yet have been registered. * * {@internal The wpseo_titles concrete class overrules this method. Make sure that any * changes applied here, also get ported to that version.}} * * @param array $dirty Original option as retrieved from the database. * @param array $clean Filtered option where any options which shouldn't be in our option * have already been removed and any options which weren't set * have been set to their defaults. * * @return array */ protected function retain_variable_keys( $dirty, $clean ) { if ( ( is_array( $this->variable_array_key_patterns ) && $this->variable_array_key_patterns !== [] ) && ( is_array( $dirty ) && $dirty !== [] ) ) { foreach ( $dirty as $key => $value ) { // Do nothing if already in filtered options. if ( isset( $clean[ $key ] ) ) { continue; } foreach ( $this->variable_array_key_patterns as $pattern ) { if ( strpos( $key, $pattern ) === 0 ) { $clean[ $key ] = $value; break; } } } } return $clean; } /** * Check whether a given array key conforms to one of the variable array key patterns for this option. * * @used-by validate_option() methods for options with variable array keys. * * @param string $key Array key to check. * * @return string Pattern if it conforms, original array key if it doesn't or if the option * does not have variable array keys. */ protected function get_switch_key( $key ) { if ( ! isset( $this->variable_array_key_patterns ) || ( ! is_array( $this->variable_array_key_patterns ) || $this->variable_array_key_patterns === [] ) ) { return $key; } foreach ( $this->variable_array_key_patterns as $pattern ) { if ( strpos( $key, $pattern ) === 0 ) { return $pattern; } } return $key; } } ووردبريس › خطأ

كان هناك خطأ فادح في هذا الموقع.

معرفة المزيد حول استكشاف الأخطاء في ووردبريس.