X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/11be15bd505d66a91e2c80062190b13e315a04a9..c55863f11e8589bf8d4a5698bf15752406654f1c:/wp-includes/option.php diff --git a/wp-includes/option.php b/wp-includes/option.php index 3df89c2c..ec30231d 100644 --- a/wp-includes/option.php +++ b/wp-includes/option.php @@ -165,9 +165,9 @@ function wp_load_alloptions() { * @param int $site_id Optional site ID for which to query the options. Defaults to the current site. */ function wp_load_core_site_options( $site_id = null ) { - global $wpdb, $_wp_using_ext_object_cache; + global $wpdb; - if ( !is_multisite() || $_wp_using_ext_object_cache || defined( 'WP_INSTALLING' ) ) + if ( !is_multisite() || wp_using_ext_object_cache() || defined( 'WP_INSTALLING' ) ) return; if ( empty($site_id) ) @@ -208,10 +208,10 @@ function wp_load_core_site_options( $site_id = null ) { * @uses do_action() Calls 'update_option_$option' and 'updated_option' hooks on success. * * @param string $option Option name. Expected to not be SQL-escaped. - * @param mixed $newvalue Option value. Expected to not be SQL-escaped. + * @param mixed $value Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped. * @return bool False if value was not updated and true if value was updated. */ -function update_option( $option, $newvalue ) { +function update_option( $option, $value ) { global $wpdb; $option = trim($option); @@ -220,19 +220,26 @@ function update_option( $option, $newvalue ) { wp_protect_special_option( $option ); - if ( is_object($newvalue) ) - $newvalue = clone $newvalue; + if ( is_object( $value ) ) + $value = clone $value; - $newvalue = sanitize_option( $option, $newvalue ); - $oldvalue = get_option( $option ); - $newvalue = apply_filters( 'pre_update_option_' . $option, $newvalue, $oldvalue ); + $value = sanitize_option( $option, $value ); + $old_value = get_option( $option ); + $value = apply_filters( 'pre_update_option_' . $option, $value, $old_value ); // If the new and old values are the same, no need to update. - if ( $newvalue === $oldvalue ) + if ( $value === $old_value ) return false; - if ( false === $oldvalue ) - return add_option( $option, $newvalue ); + if ( false === $old_value ) + return add_option( $option, $value ); + + $serialized_value = maybe_serialize( $value ); + + do_action( 'update_option', $option, $old_value, $value ); + $result = $wpdb->update( $wpdb->options, array( 'option_value' => $serialized_value ), array( 'option_name' => $option ) ); + if ( ! $result ) + return false; $notoptions = wp_cache_get( 'notoptions', 'options' ); if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) { @@ -240,28 +247,19 @@ function update_option( $option, $newvalue ) { wp_cache_set( 'notoptions', $notoptions, 'options' ); } - $_newvalue = $newvalue; - $newvalue = maybe_serialize( $newvalue ); - - do_action( 'update_option', $option, $oldvalue, $_newvalue ); if ( ! defined( 'WP_INSTALLING' ) ) { $alloptions = wp_load_alloptions(); if ( isset( $alloptions[$option] ) ) { - $alloptions[$option] = $newvalue; + $alloptions[ $option ] = $serialized_value; wp_cache_set( 'alloptions', $alloptions, 'options' ); } else { - wp_cache_set( $option, $newvalue, 'options' ); + wp_cache_set( $option, $serialized_value, 'options' ); } } - $result = $wpdb->update( $wpdb->options, array( 'option_value' => $newvalue ), array( 'option_name' => $option ) ); - - if ( $result ) { - do_action( "update_option_{$option}", $oldvalue, $_newvalue ); - do_action( 'updated_option', $option, $oldvalue, $_newvalue ); - return true; - } - return false; + do_action( "update_option_{$option}", $old_value, $value ); + do_action( 'updated_option', $option, $old_value, $value ); + return true; } /** @@ -284,7 +282,7 @@ function update_option( $option, $newvalue ) { * @uses do_action() Calls 'add_option_$option' and 'added_option' hooks on success. * * @param string $option Name of option to add. Expected to not be SQL-escaped. - * @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped. + * @param mixed $value Optional. Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped. * @param mixed $deprecated Optional. Description. Not used anymore. * @param bool $autoload Optional. Default is enabled. Whether to load the option when WordPress starts up. * @return bool False if option was not added and true if option was added. @@ -312,17 +310,21 @@ function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) if ( false !== get_option( $option ) ) return false; - $_value = $value; - $value = maybe_serialize( $value ); + $serialized_value = maybe_serialize( $value ); $autoload = ( 'no' === $autoload ) ? 'no' : 'yes'; - do_action( 'add_option', $option, $_value ); + do_action( 'add_option', $option, $value ); + + $result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $serialized_value, $autoload ) ); + if ( ! $result ) + return false; + if ( ! defined( 'WP_INSTALLING' ) ) { if ( 'yes' == $autoload ) { $alloptions = wp_load_alloptions(); - $alloptions[$option] = $value; + $alloptions[ $option ] = $serialized_value; wp_cache_set( 'alloptions', $alloptions, 'options' ); } else { - wp_cache_set( $option, $value, 'options' ); + wp_cache_set( $option, $serialized_value, 'options' ); } } @@ -333,14 +335,9 @@ function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) wp_cache_set( 'notoptions', $notoptions, 'options' ); } - $result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $value, $autoload ) ); - - if ( $result ) { - do_action( "add_option_{$option}", $option, $_value ); - do_action( 'added_option', $option, $_value ); - return true; - } - return false; + do_action( "add_option_{$option}", $option, $value ); + do_action( 'added_option', $option, $value ); + return true; } /** @@ -404,11 +401,9 @@ function delete_option( $option ) { * @return bool true if successful, false otherwise */ function delete_transient( $transient ) { - global $_wp_using_ext_object_cache; - do_action( 'delete_transient_' . $transient, $transient ); - if ( $_wp_using_ext_object_cache ) { + if ( wp_using_ext_object_cache() ) { $result = wp_cache_delete( $transient, 'transient' ); } else { $option_timeout = '_transient_timeout_' . $transient; @@ -443,13 +438,11 @@ function delete_transient( $transient ) { * @return mixed Value of transient */ function get_transient( $transient ) { - global $_wp_using_ext_object_cache; - $pre = apply_filters( 'pre_transient_' . $transient, false ); if ( false !== $pre ) return $pre; - if ( $_wp_using_ext_object_cache ) { + if ( wp_using_ext_object_cache() ) { $value = wp_cache_get( $transient, 'transient' ); } else { $transient_option = '_transient_' . $transient; @@ -461,12 +454,13 @@ function get_transient( $transient ) { if ( get_option( $transient_timeout ) < time() ) { delete_option( $transient_option ); delete_option( $transient_timeout ); - return false; + $value = false; } } } - $value = get_option( $transient_option ); + if ( ! isset( $value ) ) + $value = get_option( $transient_option ); } return apply_filters( 'transient_' . $transient, $value ); @@ -487,16 +481,15 @@ function get_transient( $transient ) { * @uses do_action() Calls 'set_transient_$transient' and 'setted_transient' hooks on success. * * @param string $transient Transient name. Expected to not be SQL-escaped. - * @param mixed $value Transient value. Expected to not be SQL-escaped. + * @param mixed $value Transient value. Must be serializable if non-scalar. Expected to not be SQL-escaped. * @param int $expiration Time until expiration in seconds, default 0 * @return bool False if value was not set and true if value was set. */ function set_transient( $transient, $value, $expiration = 0 ) { - global $_wp_using_ext_object_cache; - $value = apply_filters( 'pre_set_transient_' . $transient, $value ); + $expiration = (int) $expiration; - if ( $_wp_using_ext_object_cache ) { + if ( wp_using_ext_object_cache() ) { $result = wp_cache_set( $transient, $value, 'transient', $expiration ); } else { $transient_timeout = '_transient_timeout_' . $transient; @@ -540,37 +533,36 @@ function wp_user_settings() { if ( defined('DOING_AJAX') ) return; - if ( ! $user = wp_get_current_user() ) + if ( ! $user_id = get_current_user_id() ) return; - if ( is_super_admin( $user->ID ) && - ! in_array( get_current_blog_id(), array_keys( get_blogs_of_user( $user->ID ) ) ) - ) + if ( is_super_admin() && ! is_user_member_of_blog() ) return; - $settings = get_user_option( 'user-settings', $user->ID ); + $settings = (string) get_user_option( 'user-settings', $user_id ); - if ( isset( $_COOKIE['wp-settings-' . $user->ID] ) ) { - $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] ); + if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) { + $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user_id] ); - if ( ! empty( $cookie ) && strpos( $cookie, '=' ) ) { - if ( $cookie == $settings ) - return; + // No change or both empty + if ( $cookie == $settings ) + return; - $last_time = (int) get_user_option( 'user-settings-time', $user->ID ); - $saved = isset( $_COOKIE['wp-settings-time-' . $user->ID]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user->ID] ) : 0; + $last_saved = (int) get_user_option( 'user-settings-time', $user_id ); + $current = isset( $_COOKIE['wp-settings-time-' . $user_id]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user_id] ) : 0; - if ( $saved > $last_time ) { - update_user_option( $user->ID, 'user-settings', $cookie, false ); - update_user_option( $user->ID, 'user-settings-time', time() - 5, false ); - return; - } + // The cookie is newer than the saved value. Update the user_option and leave the cookie as-is + if ( $current > $last_saved ) { + update_user_option( $user_id, 'user-settings', $cookie, false ); + update_user_option( $user_id, 'user-settings-time', time() - 5, false ); + return; } } - setcookie( 'wp-settings-' . $user->ID, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH ); - setcookie( 'wp-settings-time-' . $user->ID, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH ); - $_COOKIE['wp-settings-' . $user->ID] = $settings; + // The cookie is not set in the current browser or the saved value is newer. + setcookie( 'wp-settings-' . $user_id, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH ); + setcookie( 'wp-settings-time-' . $user_id, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH ); + $_COOKIE['wp-settings-' . $user_id] = $settings; } /** @@ -585,10 +577,9 @@ function wp_user_settings() { * @return mixed the last saved user setting or the default value/false if it doesn't exist. */ function get_user_setting( $name, $default = false ) { + $all_user_settings = get_all_user_settings(); - $all = get_all_user_settings(); - - return isset($all[$name]) ? $all[$name] : $default; + return isset( $all_user_settings[$name] ) ? $all_user_settings[$name] : $default; } /** @@ -610,15 +601,10 @@ function set_user_setting( $name, $value ) { if ( headers_sent() ) return false; - $all = get_all_user_settings(); - $name = preg_replace( '/[^A-Za-z0-9_]+/', '', $name ); + $all_user_settings = get_all_user_settings(); + $all_user_settings[$name] = $value; - if ( empty($name) ) - return false; - - $all[$name] = $value; - - return wp_set_all_user_settings($all); + return wp_set_all_user_settings( $all_user_settings ); } /** @@ -639,18 +625,19 @@ function delete_user_setting( $names ) { if ( headers_sent() ) return false; - $all = get_all_user_settings(); + $all_user_settings = get_all_user_settings(); $names = (array) $names; + $deleted = false; foreach ( $names as $name ) { - if ( isset($all[$name]) ) { - unset($all[$name]); + if ( isset( $all_user_settings[$name] ) ) { + unset( $all_user_settings[$name] ); $deleted = true; } } - if ( isset($deleted) ) - return wp_set_all_user_settings($all); + if ( $deleted ) + return wp_set_all_user_settings( $all_user_settings ); return false; } @@ -667,26 +654,27 @@ function delete_user_setting( $names ) { function get_all_user_settings() { global $_updated_user_settings; - if ( ! $user = wp_get_current_user() ) + if ( ! $user_id = get_current_user_id() ) return array(); - if ( isset($_updated_user_settings) && is_array($_updated_user_settings) ) + if ( isset( $_updated_user_settings ) && is_array( $_updated_user_settings ) ) return $_updated_user_settings; - $all = array(); - if ( isset($_COOKIE['wp-settings-' . $user->ID]) ) { - $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] ); + $user_settings = array(); + if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) { + $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user_id] ); - if ( $cookie && strpos($cookie, '=') ) // the '=' cannot be 1st char - parse_str($cookie, $all); + if ( $cookie && strpos( $cookie, '=' ) ) // '=' cannot be 1st char + parse_str( $cookie, $user_settings ); } else { - $option = get_user_option('user-settings', $user->ID); + $option = get_user_option( 'user-settings', $user_id ); if ( $option && is_string($option) ) - parse_str( $option, $all ); + parse_str( $option, $user_settings ); } - return $all; + $_updated_user_settings = $user_settings; + return $user_settings; } /** @@ -696,31 +684,32 @@ function get_all_user_settings() { * @subpackage Option * @since 2.8.0 * - * @param unknown $all + * @param array $user_settings * @return bool */ -function wp_set_all_user_settings($all) { +function wp_set_all_user_settings( $user_settings ) { global $_updated_user_settings; - if ( ! $user = wp_get_current_user() ) + if ( ! $user_id = get_current_user_id() ) return false; - if ( is_super_admin( $user->ID ) && - ! in_array( get_current_blog_id(), array_keys( get_blogs_of_user( $user->ID ) ) ) - ) + if ( is_super_admin() && ! is_user_member_of_blog() ) return; - $_updated_user_settings = $all; $settings = ''; - foreach ( $all as $k => $v ) { - $v = preg_replace( '/[^A-Za-z0-9_]+/', '', $v ); - $settings .= $k . '=' . $v . '&'; + foreach ( $user_settings as $name => $value ) { + $_name = preg_replace( '/[^A-Za-z0-9_]+/', '', $name ); + $_value = preg_replace( '/[^A-Za-z0-9_]+/', '', $value ); + + if ( ! empty( $_name ) ) + $settings .= $_name . '=' . $_value . '&'; } $settings = rtrim($settings, '&'); + parse_str( $settings, $_updated_user_settings ); - update_user_option( $user->ID, 'user-settings', $settings, false ); - update_user_option( $user->ID, 'user-settings-time', time(), false ); + update_user_option( $user_id, 'user-settings', $settings, false ); + update_user_option( $user_id, 'user-settings-time', time(), false ); return true; } @@ -733,11 +722,11 @@ function wp_set_all_user_settings($all) { * @since 2.7.0 */ function delete_all_user_settings() { - if ( ! $user = wp_get_current_user() ) + if ( ! $user_id = get_current_user_id() ) return; - update_user_option( $user->ID, 'user-settings', '', false ); - setcookie('wp-settings-' . $user->ID, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH); + update_user_option( $user_id, 'user-settings', '', false ); + setcookie('wp-settings-' . $user_id, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH); } /** @@ -767,6 +756,12 @@ function get_site_option( $option, $default = false, $use_cache = true ) { if ( false !== $pre ) return $pre; + // prevent non-existent options from triggering multiple queries + $notoptions_key = "{$wpdb->siteid}:notoptions"; + $notoptions = wp_cache_get( $notoptions_key, 'site-options' ); + if ( isset( $notoptions[$option] ) ) + return apply_filters( 'default_site_option_' . $option, $default ); + if ( ! is_multisite() ) { $default = apply_filters( 'default_site_option_' . $option, $default ); $value = get_option($option, $default); @@ -784,6 +779,8 @@ function get_site_option( $option, $default = false, $use_cache = true ) { $value = maybe_unserialize( $value ); wp_cache_set( $cache_key, $value, 'site-options' ); } else { + $notoptions[$option] = true; + wp_cache_set( $notoptions_key, $notoptions, 'site-options' ); $value = apply_filters( 'default_site_option_' . $option, $default ); } } @@ -813,23 +810,38 @@ function get_site_option( $option, $default = false, $use_cache = true ) { function add_site_option( $option, $value ) { global $wpdb; + wp_protect_special_option( $option ); + $value = apply_filters( 'pre_add_site_option_' . $option, $value ); + $notoptions_key = "{$wpdb->siteid}:notoptions"; if ( !is_multisite() ) { $result = add_option( $option, $value ); } else { $cache_key = "{$wpdb->siteid}:$option"; - if ( false !== get_site_option( $option ) ) - return false; + // Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query + $notoptions = wp_cache_get( $notoptions_key, 'site-options' ); + if ( ! is_array( $notoptions ) || ! isset( $notoptions[$option] ) ) + if ( false !== get_site_option( $option ) ) + return false; $value = sanitize_option( $option, $value ); + + $serialized_value = maybe_serialize( $value ); + $result = $wpdb->insert( $wpdb->sitemeta, array('site_id' => $wpdb->siteid, 'meta_key' => $option, 'meta_value' => $serialized_value ) ); + + if ( ! $result ) + return false; + wp_cache_set( $cache_key, $value, 'site-options' ); - $_value = $value; - $value = maybe_serialize( $value ); - $result = $wpdb->insert( $wpdb->sitemeta, array('site_id' => $wpdb->siteid, 'meta_key' => $option, 'meta_value' => $value ) ); - $value = $_value; + // This option exists now + $notoptions = wp_cache_get( $notoptions_key, 'site-options' ); // yes, again... we need it to be fresh + if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) { + unset( $notoptions[$option] ); + wp_cache_set( $notoptions_key, $notoptions, 'site-options' ); + } } if ( $result ) { @@ -901,31 +913,41 @@ function delete_site_option( $option ) { function update_site_option( $option, $value ) { global $wpdb; - $oldvalue = get_site_option( $option ); - $value = apply_filters( 'pre_update_site_option_' . $option, $value, $oldvalue ); + wp_protect_special_option( $option ); - if ( $value === $oldvalue ) + $old_value = get_site_option( $option ); + $value = apply_filters( 'pre_update_site_option_' . $option, $value, $old_value ); + + if ( $value === $old_value ) return false; - if ( false === $oldvalue ) + if ( false === $old_value ) return add_site_option( $option, $value ); + $notoptions_key = "{$wpdb->siteid}:notoptions"; + $notoptions = wp_cache_get( $notoptions_key, 'site-options' ); + if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) { + unset( $notoptions[$option] ); + wp_cache_set( $notoptions_key, $notoptions, 'site-options' ); + } + if ( !is_multisite() ) { $result = update_option( $option, $value ); } else { $value = sanitize_option( $option, $value ); - $cache_key = "{$wpdb->siteid}:$option"; - wp_cache_set( $cache_key, $value, 'site-options' ); - $_value = $value; - $value = maybe_serialize( $value ); - $result = $wpdb->update( $wpdb->sitemeta, array( 'meta_value' => $value ), array( 'site_id' => $wpdb->siteid, 'meta_key' => $option ) ); - $value = $_value; + $serialized_value = maybe_serialize( $value ); + $result = $wpdb->update( $wpdb->sitemeta, array( 'meta_value' => $serialized_value ), array( 'site_id' => $wpdb->siteid, 'meta_key' => $option ) ); + + if ( $result ) { + $cache_key = "{$wpdb->siteid}:$option"; + wp_cache_set( $cache_key, $value, 'site-options' ); + } } if ( $result ) { - do_action( "update_site_option_{$option}", $option, $value, $oldvalue ); - do_action( "update_site_option", $option, $value, $oldvalue ); + do_action( "update_site_option_{$option}", $option, $value, $old_value ); + do_action( "update_site_option", $option, $value, $old_value ); return true; } return false; @@ -945,10 +967,8 @@ function update_site_option( $option, $value ) { * @return bool True if successful, false otherwise */ function delete_site_transient( $transient ) { - global $_wp_using_ext_object_cache; - do_action( 'delete_site_transient_' . $transient, $transient ); - if ( $_wp_using_ext_object_cache ) { + if ( wp_using_ext_object_cache() ) { $result = wp_cache_delete( $transient, 'site-transient' ); } else { $option_timeout = '_site_transient_timeout_' . $transient; @@ -983,13 +1003,11 @@ function delete_site_transient( $transient ) { * @return mixed Value of transient */ function get_site_transient( $transient ) { - global $_wp_using_ext_object_cache; - $pre = apply_filters( 'pre_site_transient_' . $transient, false ); if ( false !== $pre ) return $pre; - if ( $_wp_using_ext_object_cache ) { + if ( wp_using_ext_object_cache() ) { $value = wp_cache_get( $transient, 'site-transient' ); } else { // Core transients that do not have a timeout. Listed here so querying timeouts can be avoided. @@ -1001,11 +1019,12 @@ function get_site_transient( $transient ) { if ( false !== $timeout && $timeout < time() ) { delete_site_option( $transient_option ); delete_site_option( $transient_timeout ); - return false; + $value = false; } } - $value = get_site_option( $transient_option ); + if ( ! isset( $value ) ) + $value = get_site_option( $transient_option ); } return apply_filters( 'site_transient_' . $transient, $value ); @@ -1032,23 +1051,22 @@ function get_site_transient( $transient ) { * @return bool False if value was not set and true if value was set. */ function set_site_transient( $transient, $value, $expiration = 0 ) { - global $_wp_using_ext_object_cache; - $value = apply_filters( 'pre_set_site_transient_' . $transient, $value ); + $expiration = (int) $expiration; - if ( $_wp_using_ext_object_cache ) { + if ( wp_using_ext_object_cache() ) { $result = wp_cache_set( $transient, $value, 'site-transient', $expiration ); } else { $transient_timeout = '_site_transient_timeout_' . $transient; - $transient = '_site_transient_' . $transient; - if ( false === get_site_option( $transient ) ) { + $option = '_site_transient_' . $transient; + if ( false === get_site_option( $option ) ) { if ( $expiration ) add_site_option( $transient_timeout, time() + $expiration ); - $result = add_site_option( $transient, $value ); + $result = add_site_option( $option, $value ); } else { if ( $expiration ) update_site_option( $transient_timeout, time() + $expiration ); - $result = update_site_option( $transient, $value ); + $result = update_site_option( $option, $value ); } } if ( $result ) {