home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-includes / option.php < prev    next >
Encoding:
PHP Script  |  2017-10-24  |  66.2 KB  |  2,137 lines

  1. <?php
  2. /**
  3.  * Option API
  4.  *
  5.  * @package WordPress
  6.  * @subpackage Option
  7.  */
  8.  
  9. /**
  10.  * Retrieves an option value based on an option name.
  11.  *
  12.  * If the option does not exist or does not have a value, then the return value
  13.  * will be false. This is useful to check whether you need to install an option
  14.  * and is commonly used during installation of plugin options and to test
  15.  * whether upgrading is required.
  16.  *
  17.  * If the option was serialized then it will be unserialized when it is returned.
  18.  *
  19.  * Any scalar values will be returned as strings. You may coerce the return type of
  20.  * a given option by registering an {@see 'option_$option'} filter callback.
  21.  *
  22.  * @since 1.5.0
  23.  *
  24.  * @global wpdb $wpdb WordPress database abstraction object.
  25.  *
  26.  * @param string $option  Name of option to retrieve. Expected to not be SQL-escaped.
  27.  * @param mixed  $default Optional. Default value to return if the option does not exist.
  28.  * @return mixed Value set for the option.
  29.  */
  30. function get_option( $option, $default = false ) {
  31.     global $wpdb;
  32.  
  33.     $option = trim( $option );
  34.     if ( empty( $option ) )
  35.         return false;
  36.  
  37.     /**
  38.      * Filters the value of an existing option before it is retrieved.
  39.      *
  40.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  41.      *
  42.      * Passing a truthy value to the filter will short-circuit retrieving
  43.      * the option value, returning the passed value instead.
  44.      *
  45.      * @since 1.5.0
  46.      * @since 4.4.0 The `$option` parameter was added.
  47.      * @since 4.9.0 The `$default` parameter was added.
  48.      *
  49.      *
  50.      * @param bool|mixed $pre_option The value to return instead of the option value. This differs from
  51.      *                               `$default`, which is used as the fallback value in the event the option
  52.      *                               doesn't exist elsewhere in get_option(). Default false (to skip past the
  53.      *                               short-circuit).
  54.      * @param string     $option     Option name.
  55.      * @param mixed      $default    The fallback value to return if the option does not exist.
  56.      *                               Default is false.
  57.      */
  58.     $pre = apply_filters( "pre_option_{$option}", false, $option, $default );
  59.  
  60.     if ( false !== $pre )
  61.         return $pre;
  62.  
  63.     if ( defined( 'WP_SETUP_CONFIG' ) )
  64.         return false;
  65.  
  66.     // Distinguish between `false` as a default, and not passing one.
  67.     $passed_default = func_num_args() > 1;
  68.  
  69.     if ( ! wp_installing() ) {
  70.         // prevent non-existent options from triggering multiple queries
  71.         $notoptions = wp_cache_get( 'notoptions', 'options' );
  72.         if ( isset( $notoptions[ $option ] ) ) {
  73.             /**
  74.              * Filters the default value for an option.
  75.              *
  76.              * The dynamic portion of the hook name, `$option`, refers to the option name.
  77.              *
  78.              * @since 3.4.0
  79.              * @since 4.4.0 The `$option` parameter was added.
  80.              * @since 4.7.0 The `$passed_default` parameter was added to distinguish between a `false` value and the default parameter value.
  81.              *
  82.              * @param mixed  $default The default value to return if the option does not exist
  83.              *                        in the database.
  84.              * @param string $option  Option name.
  85.              * @param bool   $passed_default Was `get_option()` passed a default value?
  86.              */
  87.             return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
  88.         }
  89.  
  90.         $alloptions = wp_load_alloptions();
  91.  
  92.         if ( isset( $alloptions[$option] ) ) {
  93.             $value = $alloptions[$option];
  94.         } else {
  95.             $value = wp_cache_get( $option, 'options' );
  96.  
  97.             if ( false === $value ) {
  98.                 $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
  99.  
  100.                 // Has to be get_row instead of get_var because of funkiness with 0, false, null values
  101.                 if ( is_object( $row ) ) {
  102.                     $value = $row->option_value;
  103.                     wp_cache_add( $option, $value, 'options' );
  104.                 } else { // option does not exist, so we must cache its non-existence
  105.                     if ( ! is_array( $notoptions ) ) {
  106.                          $notoptions = array();
  107.                     }
  108.                     $notoptions[$option] = true;
  109.                     wp_cache_set( 'notoptions', $notoptions, 'options' );
  110.  
  111.                     /** This filter is documented in wp-includes/option.php */
  112.                     return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
  113.                 }
  114.             }
  115.         }
  116.     } else {
  117.         $suppress = $wpdb->suppress_errors();
  118.         $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
  119.         $wpdb->suppress_errors( $suppress );
  120.         if ( is_object( $row ) ) {
  121.             $value = $row->option_value;
  122.         } else {
  123.             /** This filter is documented in wp-includes/option.php */
  124.             return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
  125.         }
  126.     }
  127.  
  128.     // If home is not set use siteurl.
  129.     if ( 'home' == $option && '' == $value )
  130.         return get_option( 'siteurl' );
  131.  
  132.     if ( in_array( $option, array('siteurl', 'home', 'category_base', 'tag_base') ) )
  133.         $value = untrailingslashit( $value );
  134.  
  135.     /**
  136.      * Filters the value of an existing option.
  137.      *
  138.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  139.      *
  140.      * @since 1.5.0 As 'option_' . $setting
  141.      * @since 3.0.0
  142.      * @since 4.4.0 The `$option` parameter was added.
  143.      *
  144.      * @param mixed  $value  Value of the option. If stored serialized, it will be
  145.      *                       unserialized prior to being returned.
  146.      * @param string $option Option name.
  147.      */
  148.     return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
  149. }
  150.  
  151. /**
  152.  * Protect WordPress special option from being modified.
  153.  *
  154.  * Will die if $option is in protected list. Protected options are 'alloptions'
  155.  * and 'notoptions' options.
  156.  *
  157.  * @since 2.2.0
  158.  *
  159.  * @param string $option Option name.
  160.  */
  161. function wp_protect_special_option( $option ) {
  162.     if ( 'alloptions' === $option || 'notoptions' === $option )
  163.         wp_die( sprintf( __( '%s is a protected WP option and may not be modified' ), esc_html( $option ) ) );
  164. }
  165.  
  166. /**
  167.  * Print option value after sanitizing for forms.
  168.  *
  169.  * @since 1.5.0
  170.  *
  171.  * @param string $option Option name.
  172.  */
  173. function form_option( $option ) {
  174.     echo esc_attr( get_option( $option ) );
  175. }
  176.  
  177. /**
  178.  * Loads and caches all autoloaded options, if available or all options.
  179.  *
  180.  * @since 2.2.0
  181.  *
  182.  * @global wpdb $wpdb WordPress database abstraction object.
  183.  *
  184.  * @return array List of all options.
  185.  */
  186. function wp_load_alloptions() {
  187.     global $wpdb;
  188.  
  189.     if ( ! wp_installing() || ! is_multisite() ) {
  190.         $alloptions = wp_cache_get( 'alloptions', 'options' );
  191.     } else {
  192.         $alloptions = false;
  193.     }
  194.  
  195.     if ( ! $alloptions ) {
  196.         $suppress = $wpdb->suppress_errors();
  197.         if ( ! $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) ) {
  198.             $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
  199.         }
  200.         $wpdb->suppress_errors( $suppress );
  201.  
  202.         $alloptions = array();
  203.         foreach ( (array) $alloptions_db as $o ) {
  204.             $alloptions[$o->option_name] = $o->option_value;
  205.         }
  206.  
  207.         if ( ! wp_installing() || ! is_multisite() ) {
  208.             /**
  209.              * Filters all options before caching them.
  210.              *
  211.              * @since 4.9.0
  212.              *
  213.              * @param array $alloptions Array with all options.
  214.              */
  215.             $alloptions = apply_filters( 'pre_cache_alloptions', $alloptions );
  216.             wp_cache_add( 'alloptions', $alloptions, 'options' );
  217.         }
  218.     }
  219.  
  220.     /**
  221.      * Filters all options after retrieving them.
  222.      *
  223.      * @since 4.9.0
  224.      *
  225.      * @param array $alloptions Array with all options.
  226.      */
  227.     return apply_filters( 'alloptions', $alloptions );
  228. }
  229.  
  230. /**
  231.  * Loads and caches certain often requested site options if is_multisite() and a persistent cache is not being used.
  232.  *
  233.  * @since 3.0.0
  234.  *
  235.  * @global wpdb $wpdb WordPress database abstraction object.
  236.  *
  237.  * @param int $network_id Optional site ID for which to query the options. Defaults to the current site.
  238.  */
  239. function wp_load_core_site_options( $network_id = null ) {
  240.     global $wpdb;
  241.  
  242.     if ( ! is_multisite() || wp_using_ext_object_cache() || wp_installing() )
  243.         return;
  244.  
  245.     if ( empty($network_id) )
  246.         $network_id = get_current_network_id();
  247.  
  248.     $core_options = array('site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'can_compress_scripts', 'global_terms_enabled', 'ms_files_rewriting' );
  249.  
  250.     $core_options_in = "'" . implode("', '", $core_options) . "'";
  251.     $options = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN ($core_options_in) AND site_id = %d", $network_id ) );
  252.  
  253.     foreach ( $options as $option ) {
  254.         $key = $option->meta_key;
  255.         $cache_key = "{$network_id}:$key";
  256.         $option->meta_value = maybe_unserialize( $option->meta_value );
  257.  
  258.         wp_cache_set( $cache_key, $option->meta_value, 'site-options' );
  259.     }
  260. }
  261.  
  262. /**
  263.  * Update the value of an option that was already added.
  264.  *
  265.  * You do not need to serialize values. If the value needs to be serialized, then
  266.  * it will be serialized before it is inserted into the database. Remember,
  267.  * resources can not be serialized or added as an option.
  268.  *
  269.  * If the option does not exist, then the option will be added with the option value,
  270.  * with an `$autoload` value of 'yes'.
  271.  *
  272.  * @since 1.0.0
  273.  * @since 4.2.0 The `$autoload` parameter was added.
  274.  *
  275.  * @global wpdb $wpdb WordPress database abstraction object.
  276.  *
  277.  * @param string      $option   Option name. Expected to not be SQL-escaped.
  278.  * @param mixed       $value    Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
  279.  * @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. For existing options,
  280.  *                              `$autoload` can only be updated using `update_option()` if `$value` is also changed.
  281.  *                              Accepts 'yes'|true to enable or 'no'|false to disable. For non-existent options,
  282.  *                              the default value is 'yes'. Default null.
  283.  * @return bool False if value was not updated and true if value was updated.
  284.  */
  285. function update_option( $option, $value, $autoload = null ) {
  286.     global $wpdb;
  287.  
  288.     $option = trim($option);
  289.     if ( empty($option) )
  290.         return false;
  291.  
  292.     wp_protect_special_option( $option );
  293.  
  294.     if ( is_object( $value ) )
  295.         $value = clone $value;
  296.  
  297.     $value = sanitize_option( $option, $value );
  298.     $old_value = get_option( $option );
  299.  
  300.     /**
  301.      * Filters a specific option before its value is (maybe) serialized and updated.
  302.      *
  303.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  304.      *
  305.      * @since 2.6.0
  306.      * @since 4.4.0 The `$option` parameter was added.
  307.      *
  308.      * @param mixed  $value     The new, unserialized option value.
  309.      * @param mixed  $old_value The old option value.
  310.      * @param string $option    Option name.
  311.      */
  312.     $value = apply_filters( "pre_update_option_{$option}", $value, $old_value, $option );
  313.  
  314.     /**
  315.      * Filters an option before its value is (maybe) serialized and updated.
  316.      *
  317.      * @since 3.9.0
  318.      *
  319.      * @param mixed  $value     The new, unserialized option value.
  320.      * @param string $option    Name of the option.
  321.      * @param mixed  $old_value The old option value.
  322.      */
  323.     $value = apply_filters( 'pre_update_option', $value, $option, $old_value );
  324.  
  325.     /*
  326.      * If the new and old values are the same, no need to update.
  327.      *
  328.      * Unserialized values will be adequate in most cases. If the unserialized
  329.      * data differs, the (maybe) serialized data is checked to avoid
  330.      * unnecessary database calls for otherwise identical object instances.
  331.      *
  332.      * See https://core.trac.wordpress.org/ticket/38903
  333.      */
  334.     if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
  335.         return false;
  336.     }
  337.  
  338.     /** This filter is documented in wp-includes/option.php */
  339.     if ( apply_filters( "default_option_{$option}", false, $option, false ) === $old_value ) {
  340.         // Default setting for new options is 'yes'.
  341.         if ( null === $autoload ) {
  342.             $autoload = 'yes';
  343.         }
  344.  
  345.         return add_option( $option, $value, '', $autoload );
  346.     }
  347.  
  348.     $serialized_value = maybe_serialize( $value );
  349.  
  350.     /**
  351.      * Fires immediately before an option value is updated.
  352.      *
  353.      * @since 2.9.0
  354.      *
  355.      * @param string $option    Name of the option to update.
  356.      * @param mixed  $old_value The old option value.
  357.      * @param mixed  $value     The new option value.
  358.      */
  359.     do_action( 'update_option', $option, $old_value, $value );
  360.  
  361.     $update_args = array(
  362.         'option_value' => $serialized_value,
  363.     );
  364.  
  365.     if ( null !== $autoload ) {
  366.         $update_args['autoload'] = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
  367.     }
  368.  
  369.     $result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
  370.     if ( ! $result )
  371.         return false;
  372.  
  373.     $notoptions = wp_cache_get( 'notoptions', 'options' );
  374.     if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
  375.         unset( $notoptions[$option] );
  376.         wp_cache_set( 'notoptions', $notoptions, 'options' );
  377.     }
  378.  
  379.     if ( ! wp_installing() ) {
  380.         $alloptions = wp_load_alloptions();
  381.         if ( isset( $alloptions[$option] ) ) {
  382.             $alloptions[ $option ] = $serialized_value;
  383.             wp_cache_set( 'alloptions', $alloptions, 'options' );
  384.         } else {
  385.             wp_cache_set( $option, $serialized_value, 'options' );
  386.         }
  387.     }
  388.  
  389.     /**
  390.      * Fires after the value of a specific option has been successfully updated.
  391.      *
  392.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  393.      *
  394.      * @since 2.0.1
  395.      * @since 4.4.0 The `$option` parameter was added.
  396.      *
  397.      * @param mixed  $old_value The old option value.
  398.      * @param mixed  $value     The new option value.
  399.      * @param string $option    Option name.
  400.      */
  401.     do_action( "update_option_{$option}", $old_value, $value, $option );
  402.  
  403.     /**
  404.      * Fires after the value of an option has been successfully updated.
  405.      *
  406.      * @since 2.9.0
  407.      *
  408.      * @param string $option    Name of the updated option.
  409.      * @param mixed  $old_value The old option value.
  410.      * @param mixed  $value     The new option value.
  411.      */
  412.     do_action( 'updated_option', $option, $old_value, $value );
  413.     return true;
  414. }
  415.  
  416. /**
  417.  * Add a new option.
  418.  *
  419.  * You do not need to serialize values. If the value needs to be serialized, then
  420.  * it will be serialized before it is inserted into the database. Remember,
  421.  * resources can not be serialized or added as an option.
  422.  *
  423.  * You can create options without values and then update the values later.
  424.  * Existing options will not be updated and checks are performed to ensure that you
  425.  * aren't adding a protected WordPress option. Care should be taken to not name
  426.  * options the same as the ones which are protected.
  427.  *
  428.  * @since 1.0.0
  429.  *
  430.  * @global wpdb $wpdb WordPress database abstraction object.
  431.  *
  432.  * @param string         $option      Name of option to add. Expected to not be SQL-escaped.
  433.  * @param mixed          $value       Optional. Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
  434.  * @param string         $deprecated  Optional. Description. Not used anymore.
  435.  * @param string|bool    $autoload    Optional. Whether to load the option when WordPress starts up.
  436.  *                                    Default is enabled. Accepts 'no' to disable for legacy reasons.
  437.  * @return bool False if option was not added and true if option was added.
  438.  */
  439. function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
  440.     global $wpdb;
  441.  
  442.     if ( !empty( $deprecated ) )
  443.         _deprecated_argument( __FUNCTION__, '2.3.0' );
  444.  
  445.     $option = trim($option);
  446.     if ( empty($option) )
  447.         return false;
  448.  
  449.     wp_protect_special_option( $option );
  450.  
  451.     if ( is_object($value) )
  452.         $value = clone $value;
  453.  
  454.     $value = sanitize_option( $option, $value );
  455.  
  456.     // Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
  457.     $notoptions = wp_cache_get( 'notoptions', 'options' );
  458.     if ( !is_array( $notoptions ) || !isset( $notoptions[$option] ) )
  459.         /** This filter is documented in wp-includes/option.php */
  460.         if ( apply_filters( "default_option_{$option}", false, $option, false ) !== get_option( $option ) )
  461.             return false;
  462.  
  463.     $serialized_value = maybe_serialize( $value );
  464.     $autoload = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
  465.  
  466.     /**
  467.      * Fires before an option is added.
  468.      *
  469.      * @since 2.9.0
  470.      *
  471.      * @param string $option Name of the option to add.
  472.      * @param mixed  $value  Value of the option.
  473.      */
  474.     do_action( 'add_option', $option, $value );
  475.  
  476.     $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 ) );
  477.     if ( ! $result )
  478.         return false;
  479.  
  480.     if ( ! wp_installing() ) {
  481.         if ( 'yes' == $autoload ) {
  482.             $alloptions = wp_load_alloptions();
  483.             $alloptions[ $option ] = $serialized_value;
  484.             wp_cache_set( 'alloptions', $alloptions, 'options' );
  485.         } else {
  486.             wp_cache_set( $option, $serialized_value, 'options' );
  487.         }
  488.     }
  489.  
  490.     // This option exists now
  491.     $notoptions = wp_cache_get( 'notoptions', 'options' ); // yes, again... we need it to be fresh
  492.     if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
  493.         unset( $notoptions[$option] );
  494.         wp_cache_set( 'notoptions', $notoptions, 'options' );
  495.     }
  496.  
  497.     /**
  498.      * Fires after a specific option has been added.
  499.      *
  500.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  501.      *
  502.      * @since 2.5.0 As "add_option_{$name}"
  503.      * @since 3.0.0
  504.      *
  505.      * @param string $option Name of the option to add.
  506.      * @param mixed  $value  Value of the option.
  507.      */
  508.     do_action( "add_option_{$option}", $option, $value );
  509.  
  510.     /**
  511.      * Fires after an option has been added.
  512.      *
  513.      * @since 2.9.0
  514.      *
  515.      * @param string $option Name of the added option.
  516.      * @param mixed  $value  Value of the option.
  517.      */
  518.     do_action( 'added_option', $option, $value );
  519.     return true;
  520. }
  521.  
  522. /**
  523.  * Removes option by name. Prevents removal of protected WordPress options.
  524.  *
  525.  * @since 1.2.0
  526.  *
  527.  * @global wpdb $wpdb WordPress database abstraction object.
  528.  *
  529.  * @param string $option Name of option to remove. Expected to not be SQL-escaped.
  530.  * @return bool True, if option is successfully deleted. False on failure.
  531.  */
  532. function delete_option( $option ) {
  533.     global $wpdb;
  534.  
  535.     $option = trim( $option );
  536.     if ( empty( $option ) )
  537.         return false;
  538.  
  539.     wp_protect_special_option( $option );
  540.  
  541.     // Get the ID, if no ID then return
  542.     $row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option ) );
  543.     if ( is_null( $row ) )
  544.         return false;
  545.  
  546.     /**
  547.      * Fires immediately before an option is deleted.
  548.      *
  549.      * @since 2.9.0
  550.      *
  551.      * @param string $option Name of the option to delete.
  552.      */
  553.     do_action( 'delete_option', $option );
  554.  
  555.     $result = $wpdb->delete( $wpdb->options, array( 'option_name' => $option ) );
  556.     if ( ! wp_installing() ) {
  557.         if ( 'yes' == $row->autoload ) {
  558.             $alloptions = wp_load_alloptions();
  559.             if ( is_array( $alloptions ) && isset( $alloptions[$option] ) ) {
  560.                 unset( $alloptions[$option] );
  561.                 wp_cache_set( 'alloptions', $alloptions, 'options' );
  562.             }
  563.         } else {
  564.             wp_cache_delete( $option, 'options' );
  565.         }
  566.     }
  567.     if ( $result ) {
  568.  
  569.         /**
  570.          * Fires after a specific option has been deleted.
  571.          *
  572.          * The dynamic portion of the hook name, `$option`, refers to the option name.
  573.          *
  574.          * @since 3.0.0
  575.          *
  576.          * @param string $option Name of the deleted option.
  577.          */
  578.         do_action( "delete_option_{$option}", $option );
  579.  
  580.         /**
  581.          * Fires after an option has been deleted.
  582.          *
  583.          * @since 2.9.0
  584.          *
  585.          * @param string $option Name of the deleted option.
  586.          */
  587.         do_action( 'deleted_option', $option );
  588.         return true;
  589.     }
  590.     return false;
  591. }
  592.  
  593. /**
  594.  * Delete a transient.
  595.  *
  596.  * @since 2.8.0
  597.  *
  598.  * @param string $transient Transient name. Expected to not be SQL-escaped.
  599.  * @return bool true if successful, false otherwise
  600.  */
  601. function delete_transient( $transient ) {
  602.  
  603.     /**
  604.      * Fires immediately before a specific transient is deleted.
  605.      *
  606.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  607.      *
  608.      * @since 3.0.0
  609.      *
  610.      * @param string $transient Transient name.
  611.      */
  612.     do_action( "delete_transient_{$transient}", $transient );
  613.  
  614.     if ( wp_using_ext_object_cache() ) {
  615.         $result = wp_cache_delete( $transient, 'transient' );
  616.     } else {
  617.         $option_timeout = '_transient_timeout_' . $transient;
  618.         $option = '_transient_' . $transient;
  619.         $result = delete_option( $option );
  620.         if ( $result )
  621.             delete_option( $option_timeout );
  622.     }
  623.  
  624.     if ( $result ) {
  625.  
  626.         /**
  627.          * Fires after a transient is deleted.
  628.          *
  629.          * @since 3.0.0
  630.          *
  631.          * @param string $transient Deleted transient name.
  632.          */
  633.         do_action( 'deleted_transient', $transient );
  634.     }
  635.  
  636.     return $result;
  637. }
  638.  
  639. /**
  640.  * Get the value of a transient.
  641.  *
  642.  * If the transient does not exist, does not have a value, or has expired,
  643.  * then the return value will be false.
  644.  *
  645.  * @since 2.8.0
  646.  *
  647.  * @param string $transient Transient name. Expected to not be SQL-escaped.
  648.  * @return mixed Value of transient.
  649.  */
  650. function get_transient( $transient ) {
  651.  
  652.     /**
  653.      * Filters the value of an existing transient.
  654.      *
  655.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  656.      *
  657.      * Passing a truthy value to the filter will effectively short-circuit retrieval
  658.      * of the transient, returning the passed value instead.
  659.      *
  660.      * @since 2.8.0
  661.      * @since 4.4.0 The `$transient` parameter was added
  662.      *
  663.      * @param mixed  $pre_transient The default value to return if the transient does not exist.
  664.      *                              Any value other than false will short-circuit the retrieval
  665.      *                              of the transient, and return the returned value.
  666.      * @param string $transient     Transient name.
  667.      */
  668.     $pre = apply_filters( "pre_transient_{$transient}", false, $transient );
  669.     if ( false !== $pre )
  670.         return $pre;
  671.  
  672.     if ( wp_using_ext_object_cache() ) {
  673.         $value = wp_cache_get( $transient, 'transient' );
  674.     } else {
  675.         $transient_option = '_transient_' . $transient;
  676.         if ( ! wp_installing() ) {
  677.             // If option is not in alloptions, it is not autoloaded and thus has a timeout
  678.             $alloptions = wp_load_alloptions();
  679.             if ( !isset( $alloptions[$transient_option] ) ) {
  680.                 $transient_timeout = '_transient_timeout_' . $transient;
  681.                 $timeout = get_option( $transient_timeout );
  682.                 if ( false !== $timeout && $timeout < time() ) {
  683.                     delete_option( $transient_option  );
  684.                     delete_option( $transient_timeout );
  685.                     $value = false;
  686.                 }
  687.             }
  688.         }
  689.  
  690.         if ( ! isset( $value ) )
  691.             $value = get_option( $transient_option );
  692.     }
  693.  
  694.     /**
  695.      * Filters an existing transient's value.
  696.      *
  697.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  698.      *
  699.      * @since 2.8.0
  700.      * @since 4.4.0 The `$transient` parameter was added
  701.      *
  702.      * @param mixed  $value     Value of transient.
  703.      * @param string $transient Transient name.
  704.      */
  705.     return apply_filters( "transient_{$transient}", $value, $transient );
  706. }
  707.  
  708. /**
  709.  * Set/update the value of a transient.
  710.  *
  711.  * You do not need to serialize values. If the value needs to be serialized, then
  712.  * it will be serialized before it is set.
  713.  *
  714.  * @since 2.8.0
  715.  *
  716.  * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
  717.  *                           172 characters or fewer in length.
  718.  * @param mixed  $value      Transient value. Must be serializable if non-scalar.
  719.  *                           Expected to not be SQL-escaped.
  720.  * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
  721.  * @return bool False if value was not set and true if value was set.
  722.  */
  723. function set_transient( $transient, $value, $expiration = 0 ) {
  724.  
  725.     $expiration = (int) $expiration;
  726.  
  727.     /**
  728.      * Filters a specific transient before its value is set.
  729.      *
  730.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  731.      *
  732.      * @since 3.0.0
  733.      * @since 4.2.0 The `$expiration` parameter was added.
  734.      * @since 4.4.0 The `$transient` parameter was added.
  735.      *
  736.      * @param mixed  $value      New value of transient.
  737.      * @param int    $expiration Time until expiration in seconds.
  738.      * @param string $transient  Transient name.
  739.      */
  740.     $value = apply_filters( "pre_set_transient_{$transient}", $value, $expiration, $transient );
  741.  
  742.     /**
  743.      * Filters the expiration for a transient before its value is set.
  744.      *
  745.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  746.      *
  747.      * @since 4.4.0
  748.      *
  749.      * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
  750.      * @param mixed  $value      New value of transient.
  751.      * @param string $transient  Transient name.
  752.      */
  753.     $expiration = apply_filters( "expiration_of_transient_{$transient}", $expiration, $value, $transient );
  754.  
  755.     if ( wp_using_ext_object_cache() ) {
  756.         $result = wp_cache_set( $transient, $value, 'transient', $expiration );
  757.     } else {
  758.         $transient_timeout = '_transient_timeout_' . $transient;
  759.         $transient_option = '_transient_' . $transient;
  760.         if ( false === get_option( $transient_option ) ) {
  761.             $autoload = 'yes';
  762.             if ( $expiration ) {
  763.                 $autoload = 'no';
  764.                 add_option( $transient_timeout, time() + $expiration, '', 'no' );
  765.             }
  766.             $result = add_option( $transient_option, $value, '', $autoload );
  767.         } else {
  768.             // If expiration is requested, but the transient has no timeout option,
  769.             // delete, then re-create transient rather than update.
  770.             $update = true;
  771.             if ( $expiration ) {
  772.                 if ( false === get_option( $transient_timeout ) ) {
  773.                     delete_option( $transient_option );
  774.                     add_option( $transient_timeout, time() + $expiration, '', 'no' );
  775.                     $result = add_option( $transient_option, $value, '', 'no' );
  776.                     $update = false;
  777.                 } else {
  778.                     update_option( $transient_timeout, time() + $expiration );
  779.                 }
  780.             }
  781.             if ( $update ) {
  782.                 $result = update_option( $transient_option, $value );
  783.             }
  784.         }
  785.     }
  786.  
  787.     if ( $result ) {
  788.  
  789.         /**
  790.          * Fires after the value for a specific transient has been set.
  791.          *
  792.          * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  793.          *
  794.          * @since 3.0.0
  795.          * @since 3.6.0 The `$value` and `$expiration` parameters were added.
  796.          * @since 4.4.0 The `$transient` parameter was added.
  797.          *
  798.          * @param mixed  $value      Transient value.
  799.          * @param int    $expiration Time until expiration in seconds.
  800.          * @param string $transient  The name of the transient.
  801.          */
  802.         do_action( "set_transient_{$transient}", $value, $expiration, $transient );
  803.  
  804.         /**
  805.          * Fires after the value for a transient has been set.
  806.          *
  807.          * @since 3.0.0
  808.          * @since 3.6.0 The `$value` and `$expiration` parameters were added.
  809.          *
  810.          * @param string $transient  The name of the transient.
  811.          * @param mixed  $value      Transient value.
  812.          * @param int    $expiration Time until expiration in seconds.
  813.          */
  814.         do_action( 'setted_transient', $transient, $value, $expiration );
  815.     }
  816.     return $result;
  817. }
  818.  
  819. /**
  820.  * Deletes all expired transients.
  821.  *
  822.  * The multi-table delete syntax is used to delete the transient record
  823.  * from table a, and the corresponding transient_timeout record from table b.
  824.  *
  825.  * @since 4.9.0
  826.  *
  827.  * @param bool $force_db Optional. Force cleanup to run against the database even when an external object cache is used.
  828.  */
  829. function delete_expired_transients( $force_db = false ) {
  830.     global $wpdb;
  831.  
  832.     if ( ! $force_db && wp_using_ext_object_cache() ) {
  833.         return;
  834.     }
  835.  
  836.     $wpdb->query( $wpdb->prepare(
  837.         "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
  838.             WHERE a.option_name LIKE %s
  839.             AND a.option_name NOT LIKE %s
  840.             AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
  841.             AND b.option_value < %d",
  842.         $wpdb->esc_like( '_transient_' ) . '%',
  843.         $wpdb->esc_like( '_transient_timeout_' ) . '%',
  844.         time()
  845.     ) );
  846.  
  847.     if ( ! is_multisite() ) {
  848.         // non-Multisite stores site transients in the options table.
  849.         $wpdb->query( $wpdb->prepare(
  850.             "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
  851.                 WHERE a.option_name LIKE %s
  852.                 AND a.option_name NOT LIKE %s
  853.                 AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
  854.                 AND b.option_value < %d",
  855.             $wpdb->esc_like( '_site_transient_' ) . '%',
  856.             $wpdb->esc_like( '_site_transient_timeout_' ) . '%',
  857.             time()
  858.         ) );
  859.     } elseif ( is_multisite() && is_main_site() && is_main_network() ) {
  860.         // Multisite stores site transients in the sitemeta table.
  861.         $wpdb->query( $wpdb->prepare(
  862.             "DELETE a, b FROM {$wpdb->sitemeta} a, {$wpdb->sitemeta} b
  863.                 WHERE a.meta_key LIKE %s
  864.                 AND a.meta_key NOT LIKE %s
  865.                 AND b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) )
  866.                 AND b.meta_value < %d",
  867.             $wpdb->esc_like( '_site_transient_' ) . '%',
  868.             $wpdb->esc_like( '_site_transient_timeout_' ) . '%',
  869.             time()
  870.         ) );
  871.     }
  872. }
  873.  
  874. /**
  875.  * Saves and restores user interface settings stored in a cookie.
  876.  *
  877.  * Checks if the current user-settings cookie is updated and stores it. When no
  878.  * cookie exists (different browser used), adds the last saved cookie restoring
  879.  * the settings.
  880.  *
  881.  * @since 2.7.0
  882.  */
  883. function wp_user_settings() {
  884.  
  885.     if ( ! is_admin() || wp_doing_ajax() ) {
  886.         return;
  887.     }
  888.  
  889.     if ( ! $user_id = get_current_user_id() ) {
  890.         return;
  891.     }
  892.  
  893.     if ( ! is_user_member_of_blog() ) {
  894.         return;
  895.     }
  896.  
  897.     $settings = (string) get_user_option( 'user-settings', $user_id );
  898.  
  899.     if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
  900.         $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user_id] );
  901.  
  902.         // No change or both empty
  903.         if ( $cookie == $settings )
  904.             return;
  905.  
  906.         $last_saved = (int) get_user_option( 'user-settings-time', $user_id );
  907.         $current = isset( $_COOKIE['wp-settings-time-' . $user_id]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user_id] ) : 0;
  908.  
  909.         // The cookie is newer than the saved value. Update the user_option and leave the cookie as-is
  910.         if ( $current > $last_saved ) {
  911.             update_user_option( $user_id, 'user-settings', $cookie, false );
  912.             update_user_option( $user_id, 'user-settings-time', time() - 5, false );
  913.             return;
  914.         }
  915.     }
  916.  
  917.     // The cookie is not set in the current browser or the saved value is newer.
  918.     $secure = ( 'https' === parse_url( admin_url(), PHP_URL_SCHEME ) );
  919.     setcookie( 'wp-settings-' . $user_id, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
  920.     setcookie( 'wp-settings-time-' . $user_id, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
  921.     $_COOKIE['wp-settings-' . $user_id] = $settings;
  922. }
  923.  
  924. /**
  925.  * Retrieve user interface setting value based on setting name.
  926.  *
  927.  * @since 2.7.0
  928.  *
  929.  * @param string $name    The name of the setting.
  930.  * @param string $default Optional default value to return when $name is not set.
  931.  * @return mixed the last saved user setting or the default value/false if it doesn't exist.
  932.  */
  933. function get_user_setting( $name, $default = false ) {
  934.     $all_user_settings = get_all_user_settings();
  935.  
  936.     return isset( $all_user_settings[$name] ) ? $all_user_settings[$name] : $default;
  937. }
  938.  
  939. /**
  940.  * Add or update user interface setting.
  941.  *
  942.  * Both $name and $value can contain only ASCII letters, numbers and underscores.
  943.  *
  944.  * This function has to be used before any output has started as it calls setcookie().
  945.  *
  946.  * @since 2.8.0
  947.  *
  948.  * @param string $name  The name of the setting.
  949.  * @param string $value The value for the setting.
  950.  * @return bool|null True if set successfully, false if not. Null if the current user can't be established.
  951.  */
  952. function set_user_setting( $name, $value ) {
  953.     if ( headers_sent() ) {
  954.         return false;
  955.     }
  956.  
  957.     $all_user_settings = get_all_user_settings();
  958.     $all_user_settings[$name] = $value;
  959.  
  960.     return wp_set_all_user_settings( $all_user_settings );
  961. }
  962.  
  963. /**
  964.  * Delete user interface settings.
  965.  *
  966.  * Deleting settings would reset them to the defaults.
  967.  *
  968.  * This function has to be used before any output has started as it calls setcookie().
  969.  *
  970.  * @since 2.7.0
  971.  *
  972.  * @param string $names The name or array of names of the setting to be deleted.
  973.  * @return bool|null True if deleted successfully, false if not. Null if the current user can't be established.
  974.  */
  975. function delete_user_setting( $names ) {
  976.     if ( headers_sent() ) {
  977.         return false;
  978.     }
  979.  
  980.     $all_user_settings = get_all_user_settings();
  981.     $names = (array) $names;
  982.     $deleted = false;
  983.  
  984.     foreach ( $names as $name ) {
  985.         if ( isset( $all_user_settings[$name] ) ) {
  986.             unset( $all_user_settings[$name] );
  987.             $deleted = true;
  988.         }
  989.     }
  990.  
  991.     if ( $deleted ) {
  992.         return wp_set_all_user_settings( $all_user_settings );
  993.     }
  994.  
  995.     return false;
  996. }
  997.  
  998. /**
  999.  * Retrieve all user interface settings.
  1000.  *
  1001.  * @since 2.7.0
  1002.  *
  1003.  * @global array $_updated_user_settings
  1004.  *
  1005.  * @return array the last saved user settings or empty array.
  1006.  */
  1007. function get_all_user_settings() {
  1008.     global $_updated_user_settings;
  1009.  
  1010.     if ( ! $user_id = get_current_user_id() ) {
  1011.         return array();
  1012.     }
  1013.  
  1014.     if ( isset( $_updated_user_settings ) && is_array( $_updated_user_settings ) ) {
  1015.         return $_updated_user_settings;
  1016.     }
  1017.  
  1018.     $user_settings = array();
  1019.  
  1020.     if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
  1021.         $cookie = preg_replace( '/[^A-Za-z0-9=&_-]/', '', $_COOKIE['wp-settings-' . $user_id] );
  1022.  
  1023.         if ( strpos( $cookie, '=' ) ) { // '=' cannot be 1st char
  1024.             parse_str( $cookie, $user_settings );
  1025.         }
  1026.     } else {
  1027.         $option = get_user_option( 'user-settings', $user_id );
  1028.  
  1029.         if ( $option && is_string( $option ) ) {
  1030.             parse_str( $option, $user_settings );
  1031.         }
  1032.     }
  1033.  
  1034.     $_updated_user_settings = $user_settings;
  1035.     return $user_settings;
  1036. }
  1037.  
  1038. /**
  1039.  * Private. Set all user interface settings.
  1040.  *
  1041.  * @since 2.8.0
  1042.  * @access private
  1043.  *
  1044.  * @global array $_updated_user_settings
  1045.  *
  1046.  * @param array $user_settings User settings.
  1047.  * @return bool|null False if the current user can't be found, null if the current
  1048.  *                   user is not a super admin or a member of the site, otherwise true.
  1049.  */
  1050. function wp_set_all_user_settings( $user_settings ) {
  1051.     global $_updated_user_settings;
  1052.  
  1053.     if ( ! $user_id = get_current_user_id() ) {
  1054.         return false;
  1055.     }
  1056.  
  1057.     if ( ! is_user_member_of_blog() ) {
  1058.         return;
  1059.     }
  1060.  
  1061.     $settings = '';
  1062.     foreach ( $user_settings as $name => $value ) {
  1063.         $_name = preg_replace( '/[^A-Za-z0-9_-]+/', '', $name );
  1064.         $_value = preg_replace( '/[^A-Za-z0-9_-]+/', '', $value );
  1065.  
  1066.         if ( ! empty( $_name ) ) {
  1067.             $settings .= $_name . '=' . $_value . '&';
  1068.         }
  1069.     }
  1070.  
  1071.     $settings = rtrim( $settings, '&' );
  1072.     parse_str( $settings, $_updated_user_settings );
  1073.  
  1074.     update_user_option( $user_id, 'user-settings', $settings, false );
  1075.     update_user_option( $user_id, 'user-settings-time', time(), false );
  1076.  
  1077.     return true;
  1078. }
  1079.  
  1080. /**
  1081.  * Delete the user settings of the current user.
  1082.  *
  1083.  * @since 2.7.0
  1084.  */
  1085. function delete_all_user_settings() {
  1086.     if ( ! $user_id = get_current_user_id() ) {
  1087.         return;
  1088.     }
  1089.  
  1090.     update_user_option( $user_id, 'user-settings', '', false );
  1091.     setcookie( 'wp-settings-' . $user_id, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
  1092. }
  1093.  
  1094. /**
  1095.  * Retrieve an option value for the current network based on name of option.
  1096.  *
  1097.  * @since 2.8.0
  1098.  * @since 4.4.0 The `$use_cache` parameter was deprecated.
  1099.  * @since 4.4.0 Modified into wrapper for get_network_option()
  1100.  *
  1101.  * @see get_network_option()
  1102.  *
  1103.  * @param string $option     Name of option to retrieve. Expected to not be SQL-escaped.
  1104.  * @param mixed  $default    Optional value to return if option doesn't exist. Default false.
  1105.  * @param bool   $deprecated Whether to use cache. Multisite only. Always set to true.
  1106.  * @return mixed Value set for the option.
  1107.  */
  1108. function get_site_option( $option, $default = false, $deprecated = true ) {
  1109.     return get_network_option( null, $option, $default );
  1110. }
  1111.  
  1112. /**
  1113.  * Add a new option for the current network.
  1114.  *
  1115.  * Existing options will not be updated. Note that prior to 3.3 this wasn't the case.
  1116.  *
  1117.  * @since 2.8.0
  1118.  * @since 4.4.0 Modified into wrapper for add_network_option()
  1119.  *
  1120.  * @see add_network_option()
  1121.  *
  1122.  * @param string $option Name of option to add. Expected to not be SQL-escaped.
  1123.  * @param mixed  $value  Option value, can be anything. Expected to not be SQL-escaped.
  1124.  * @return bool False if the option was not added. True if the option was added.
  1125.  */
  1126. function add_site_option( $option, $value ) {
  1127.     return add_network_option( null, $option, $value );
  1128. }
  1129.  
  1130. /**
  1131.  * Removes a option by name for the current network.
  1132.  *
  1133.  * @since 2.8.0
  1134.  * @since 4.4.0 Modified into wrapper for delete_network_option()
  1135.  *
  1136.  * @see delete_network_option()
  1137.  *
  1138.  * @param string $option Name of option to remove. Expected to not be SQL-escaped.
  1139.  * @return bool True, if succeed. False, if failure.
  1140.  */
  1141. function delete_site_option( $option ) {
  1142.     return delete_network_option( null, $option );
  1143. }
  1144.  
  1145. /**
  1146.  * Update the value of an option that was already added for the current network.
  1147.  *
  1148.  * @since 2.8.0
  1149.  * @since 4.4.0 Modified into wrapper for update_network_option()
  1150.  *
  1151.  * @see update_network_option()
  1152.  *
  1153.  * @param string $option Name of option. Expected to not be SQL-escaped.
  1154.  * @param mixed  $value  Option value. Expected to not be SQL-escaped.
  1155.  * @return bool False if value was not updated. True if value was updated.
  1156.  */
  1157. function update_site_option( $option, $value ) {
  1158.     return update_network_option( null, $option, $value );
  1159. }
  1160.  
  1161. /**
  1162.  * Retrieve a network's option value based on the option name.
  1163.  *
  1164.  * @since 4.4.0
  1165.  *
  1166.  * @see get_option()
  1167.  *
  1168.  * @global wpdb $wpdb
  1169.  *
  1170.  * @param int      $network_id ID of the network. Can be null to default to the current network ID.
  1171.  * @param string   $option     Name of option to retrieve. Expected to not be SQL-escaped.
  1172.  * @param mixed    $default    Optional. Value to return if the option doesn't exist. Default false.
  1173.  * @return mixed Value set for the option.
  1174.  */
  1175. function get_network_option( $network_id, $option, $default = false ) {
  1176.     global $wpdb;
  1177.  
  1178.     if ( $network_id && ! is_numeric( $network_id ) ) {
  1179.         return false;
  1180.     }
  1181.  
  1182.     $network_id = (int) $network_id;
  1183.  
  1184.     // Fallback to the current network if a network ID is not specified.
  1185.     if ( ! $network_id ) {
  1186.         $network_id = get_current_network_id();
  1187.     }
  1188.  
  1189.     /**
  1190.      * Filters an existing network option before it is retrieved.
  1191.      *
  1192.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  1193.      *
  1194.      * Passing a truthy value to the filter will effectively short-circuit retrieval,
  1195.      * returning the passed value instead.
  1196.      *
  1197.      * @since 2.9.0 As 'pre_site_option_' . $key
  1198.      * @since 3.0.0
  1199.      * @since 4.4.0 The `$option` parameter was added.
  1200.      * @since 4.7.0 The `$network_id` parameter was added.
  1201.      * @since 4.9.0 The `$default` parameter was added.
  1202.      *
  1203.      * @param mixed  $pre_option The value to return instead of the option value. This differs from
  1204.      *                           `$default`, which is used as the fallback value in the event the
  1205.      *                           option doesn't exist elsewhere in get_network_option(). Default
  1206.      *                           is false (to skip past the short-circuit).
  1207.      * @param string $option     Option name.
  1208.      * @param int    $network_id ID of the network.
  1209.      * @param mixed  $default    The fallback value to return if the option does not exist.
  1210.      *                           Default is false.
  1211.      */
  1212.     $pre = apply_filters( "pre_site_option_{$option}", false, $option, $network_id, $default );
  1213.  
  1214.     if ( false !== $pre ) {
  1215.         return $pre;
  1216.     }
  1217.  
  1218.     // prevent non-existent options from triggering multiple queries
  1219.     $notoptions_key = "$network_id:notoptions";
  1220.     $notoptions = wp_cache_get( $notoptions_key, 'site-options' );
  1221.  
  1222.     if ( isset( $notoptions[ $option ] ) ) {
  1223.  
  1224.         /**
  1225.          * Filters a specific default network option.
  1226.          *
  1227.          * The dynamic portion of the hook name, `$option`, refers to the option name.
  1228.          *
  1229.          * @since 3.4.0
  1230.          * @since 4.4.0 The `$option` parameter was added.
  1231.          * @since 4.7.0 The `$network_id` parameter was added.
  1232.          *
  1233.          * @param mixed  $default    The value to return if the site option does not exist
  1234.          *                           in the database.
  1235.          * @param string $option     Option name.
  1236.          * @param int    $network_id ID of the network.
  1237.          */
  1238.         return apply_filters( "default_site_option_{$option}", $default, $option, $network_id );
  1239.     }
  1240.  
  1241.     if ( ! is_multisite() ) {
  1242.         /** This filter is documented in wp-includes/option.php */
  1243.         $default = apply_filters( 'default_site_option_' . $option, $default, $option, $network_id );
  1244.         $value = get_option( $option, $default );
  1245.     } else {
  1246.         $cache_key = "$network_id:$option";
  1247.         $value = wp_cache_get( $cache_key, 'site-options' );
  1248.  
  1249.         if ( ! isset( $value ) || false === $value ) {
  1250.             $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
  1251.  
  1252.             // Has to be get_row instead of get_var because of funkiness with 0, false, null values
  1253.             if ( is_object( $row ) ) {
  1254.                 $value = $row->meta_value;
  1255.                 $value = maybe_unserialize( $value );
  1256.                 wp_cache_set( $cache_key, $value, 'site-options' );
  1257.             } else {
  1258.                 if ( ! is_array( $notoptions ) ) {
  1259.                     $notoptions = array();
  1260.                 }
  1261.                 $notoptions[ $option ] = true;
  1262.                 wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
  1263.  
  1264.                 /** This filter is documented in wp-includes/option.php */
  1265.                 $value = apply_filters( 'default_site_option_' . $option, $default, $option, $network_id );
  1266.             }
  1267.         }
  1268.     }
  1269.  
  1270.     /**
  1271.      * Filters the value of an existing network option.
  1272.      *
  1273.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  1274.      *
  1275.      * @since 2.9.0 As 'site_option_' . $key
  1276.      * @since 3.0.0
  1277.      * @since 4.4.0 The `$option` parameter was added.
  1278.      * @since 4.7.0 The `$network_id` parameter was added.
  1279.      *
  1280.      * @param mixed  $value      Value of network option.
  1281.      * @param string $option     Option name.
  1282.      * @param int    $network_id ID of the network.
  1283.      */
  1284.     return apply_filters( "site_option_{$option}", $value, $option, $network_id );
  1285. }
  1286.  
  1287. /**
  1288.  * Add a new network option.
  1289.  *
  1290.  * Existing options will not be updated.
  1291.  *
  1292.  * @since 4.4.0
  1293.  *
  1294.  * @see add_option()
  1295.  *
  1296.  * @global wpdb $wpdb
  1297.  *
  1298.  * @param int    $network_id ID of the network. Can be null to default to the current network ID.
  1299.  * @param string $option     Name of option to add. Expected to not be SQL-escaped.
  1300.  * @param mixed  $value      Option value, can be anything. Expected to not be SQL-escaped.
  1301.  * @return bool False if option was not added and true if option was added.
  1302.  */
  1303. function add_network_option( $network_id, $option, $value ) {
  1304.     global $wpdb;
  1305.  
  1306.     if ( $network_id && ! is_numeric( $network_id ) ) {
  1307.         return false;
  1308.     }
  1309.  
  1310.     $network_id = (int) $network_id;
  1311.  
  1312.     // Fallback to the current network if a network ID is not specified.
  1313.     if ( ! $network_id ) {
  1314.         $network_id = get_current_network_id();
  1315.     }
  1316.  
  1317.     wp_protect_special_option( $option );
  1318.  
  1319.     /**
  1320.      * Filters the value of a specific network option before it is added.
  1321.      *
  1322.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  1323.      *
  1324.      * @since 2.9.0 As 'pre_add_site_option_' . $key
  1325.      * @since 3.0.0
  1326.      * @since 4.4.0 The `$option` parameter was added.
  1327.      * @since 4.7.0 The `$network_id` parameter was added.
  1328.      *
  1329.      * @param mixed  $value      Value of network option.
  1330.      * @param string $option     Option name.
  1331.      * @param int    $network_id ID of the network.
  1332.      */
  1333.     $value = apply_filters( "pre_add_site_option_{$option}", $value, $option, $network_id );
  1334.  
  1335.     $notoptions_key = "$network_id:notoptions";
  1336.  
  1337.     if ( ! is_multisite() ) {
  1338.         $result = add_option( $option, $value, '', 'no' );
  1339.     } else {
  1340.         $cache_key = "$network_id:$option";
  1341.  
  1342.         // Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
  1343.         $notoptions = wp_cache_get( $notoptions_key, 'site-options' );
  1344.         if ( ! is_array( $notoptions ) || ! isset( $notoptions[ $option ] ) ) {
  1345.             if ( false !== get_network_option( $network_id, $option, false ) ) {
  1346.                 return false;
  1347.             }
  1348.         }
  1349.  
  1350.         $value = sanitize_option( $option, $value );
  1351.  
  1352.         $serialized_value = maybe_serialize( $value );
  1353.         $result = $wpdb->insert( $wpdb->sitemeta, array( 'site_id'    => $network_id, 'meta_key'   => $option, 'meta_value' => $serialized_value ) );
  1354.  
  1355.         if ( ! $result ) {
  1356.             return false;
  1357.         }
  1358.  
  1359.         wp_cache_set( $cache_key, $value, 'site-options' );
  1360.  
  1361.         // This option exists now
  1362.         $notoptions = wp_cache_get( $notoptions_key, 'site-options' ); // yes, again... we need it to be fresh
  1363.         if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
  1364.             unset( $notoptions[ $option ] );
  1365.             wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
  1366.         }
  1367.     }
  1368.  
  1369.     if ( $result ) {
  1370.  
  1371.         /**
  1372.          * Fires after a specific network option has been successfully added.
  1373.          *
  1374.          * The dynamic portion of the hook name, `$option`, refers to the option name.
  1375.          *
  1376.          * @since 2.9.0 As "add_site_option_{$key}"
  1377.          * @since 3.0.0
  1378.          * @since 4.7.0 The `$network_id` parameter was added.
  1379.          *
  1380.          * @param string $option     Name of the network option.
  1381.          * @param mixed  $value      Value of the network option.
  1382.          * @param int    $network_id ID of the network.
  1383.          */
  1384.         do_action( "add_site_option_{$option}", $option, $value, $network_id );
  1385.  
  1386.         /**
  1387.          * Fires after a network option has been successfully added.
  1388.          *
  1389.          * @since 3.0.0
  1390.          * @since 4.7.0 The `$network_id` parameter was added.
  1391.          *
  1392.          * @param string $option     Name of the network option.
  1393.          * @param mixed  $value      Value of the network option.
  1394.          * @param int    $network_id ID of the network.
  1395.          */
  1396.         do_action( 'add_site_option', $option, $value, $network_id );
  1397.  
  1398.         return true;
  1399.     }
  1400.  
  1401.     return false;
  1402. }
  1403.  
  1404. /**
  1405.  * Removes a network option by name.
  1406.  *
  1407.  * @since 4.4.0
  1408.  *
  1409.  * @see delete_option()
  1410.  *
  1411.  * @global wpdb $wpdb
  1412.  *
  1413.  * @param int    $network_id ID of the network. Can be null to default to the current network ID.
  1414.  * @param string $option     Name of option to remove. Expected to not be SQL-escaped.
  1415.  * @return bool True, if succeed. False, if failure.
  1416.  */
  1417. function delete_network_option( $network_id, $option ) {
  1418.     global $wpdb;
  1419.  
  1420.     if ( $network_id && ! is_numeric( $network_id ) ) {
  1421.         return false;
  1422.     }
  1423.  
  1424.     $network_id = (int) $network_id;
  1425.  
  1426.     // Fallback to the current network if a network ID is not specified.
  1427.     if ( ! $network_id ) {
  1428.         $network_id = get_current_network_id();
  1429.     }
  1430.  
  1431.     /**
  1432.      * Fires immediately before a specific network option is deleted.
  1433.      *
  1434.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  1435.      *
  1436.      * @since 3.0.0
  1437.      * @since 4.4.0 The `$option` parameter was added.
  1438.      * @since 4.7.0 The `$network_id` parameter was added.
  1439.      *
  1440.      * @param string $option     Option name.
  1441.      * @param int    $network_id ID of the network.
  1442.      */
  1443.     do_action( "pre_delete_site_option_{$option}", $option, $network_id );
  1444.  
  1445.     if ( ! is_multisite() ) {
  1446.         $result = delete_option( $option );
  1447.     } else {
  1448.         $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
  1449.         if ( is_null( $row ) || ! $row->meta_id ) {
  1450.             return false;
  1451.         }
  1452.         $cache_key = "$network_id:$option";
  1453.         wp_cache_delete( $cache_key, 'site-options' );
  1454.  
  1455.         $result = $wpdb->delete( $wpdb->sitemeta, array( 'meta_key' => $option, 'site_id' => $network_id ) );
  1456.     }
  1457.  
  1458.     if ( $result ) {
  1459.  
  1460.         /**
  1461.          * Fires after a specific network option has been deleted.
  1462.          *
  1463.          * The dynamic portion of the hook name, `$option`, refers to the option name.
  1464.          *
  1465.          * @since 2.9.0 As "delete_site_option_{$key}"
  1466.          * @since 3.0.0
  1467.          * @since 4.7.0 The `$network_id` parameter was added.
  1468.          *
  1469.          * @param string $option     Name of the network option.
  1470.          * @param int    $network_id ID of the network.
  1471.          */
  1472.         do_action( "delete_site_option_{$option}", $option, $network_id );
  1473.  
  1474.         /**
  1475.          * Fires after a network option has been deleted.
  1476.          *
  1477.          * @since 3.0.0
  1478.          * @since 4.7.0 The `$network_id` parameter was added.
  1479.          *
  1480.          * @param string $option     Name of the network option.
  1481.          * @param int    $network_id ID of the network.
  1482.          */
  1483.         do_action( 'delete_site_option', $option, $network_id );
  1484.  
  1485.         return true;
  1486.     }
  1487.  
  1488.     return false;
  1489. }
  1490.  
  1491. /**
  1492.  * Update the value of a network option that was already added.
  1493.  *
  1494.  * @since 4.4.0
  1495.  *
  1496.  * @see update_option()
  1497.  *
  1498.  * @global wpdb $wpdb
  1499.  *
  1500.  * @param int      $network_id ID of the network. Can be null to default to the current network ID.
  1501.  * @param string   $option     Name of option. Expected to not be SQL-escaped.
  1502.  * @param mixed    $value      Option value. Expected to not be SQL-escaped.
  1503.  * @return bool False if value was not updated and true if value was updated.
  1504.  */
  1505. function update_network_option( $network_id, $option, $value ) {
  1506.     global $wpdb;
  1507.  
  1508.     if ( $network_id && ! is_numeric( $network_id ) ) {
  1509.         return false;
  1510.     }
  1511.  
  1512.     $network_id = (int) $network_id;
  1513.  
  1514.     // Fallback to the current network if a network ID is not specified.
  1515.     if ( ! $network_id ) {
  1516.         $network_id = get_current_network_id();
  1517.     }
  1518.  
  1519.     wp_protect_special_option( $option );
  1520.  
  1521.     $old_value = get_network_option( $network_id, $option, false );
  1522.  
  1523.     /**
  1524.      * Filters a specific network option before its value is updated.
  1525.      *
  1526.      * The dynamic portion of the hook name, `$option`, refers to the option name.
  1527.      *
  1528.      * @since 2.9.0 As 'pre_update_site_option_' . $key
  1529.      * @since 3.0.0
  1530.      * @since 4.4.0 The `$option` parameter was added.
  1531.      * @since 4.7.0 The `$network_id` parameter was added.
  1532.      *
  1533.      * @param mixed  $value      New value of the network option.
  1534.      * @param mixed  $old_value  Old value of the network option.
  1535.      * @param string $option     Option name.
  1536.      * @param int    $network_id ID of the network.
  1537.      */
  1538.     $value = apply_filters( "pre_update_site_option_{$option}", $value, $old_value, $option, $network_id );
  1539.  
  1540.     if ( $value === $old_value ) {
  1541.         return false;
  1542.     }
  1543.  
  1544.     if ( false === $old_value ) {
  1545.         return add_network_option( $network_id, $option, $value );
  1546.     }
  1547.  
  1548.     $notoptions_key = "$network_id:notoptions";
  1549.     $notoptions = wp_cache_get( $notoptions_key, 'site-options' );
  1550.     if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
  1551.         unset( $notoptions[ $option ] );
  1552.         wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
  1553.     }
  1554.  
  1555.     if ( ! is_multisite() ) {
  1556.         $result = update_option( $option, $value, 'no' );
  1557.     } else {
  1558.         $value = sanitize_option( $option, $value );
  1559.  
  1560.         $serialized_value = maybe_serialize( $value );
  1561.         $result = $wpdb->update( $wpdb->sitemeta, array( 'meta_value' => $serialized_value ), array( 'site_id' => $network_id, 'meta_key' => $option ) );
  1562.  
  1563.         if ( $result ) {
  1564.             $cache_key = "$network_id:$option";
  1565.             wp_cache_set( $cache_key, $value, 'site-options' );
  1566.         }
  1567.     }
  1568.  
  1569.     if ( $result ) {
  1570.  
  1571.         /**
  1572.          * Fires after the value of a specific network option has been successfully updated.
  1573.          *
  1574.          * The dynamic portion of the hook name, `$option`, refers to the option name.
  1575.          *
  1576.          * @since 2.9.0 As "update_site_option_{$key}"
  1577.          * @since 3.0.0
  1578.          * @since 4.7.0 The `$network_id` parameter was added.
  1579.          *
  1580.          * @param string $option     Name of the network option.
  1581.          * @param mixed  $value      Current value of the network option.
  1582.          * @param mixed  $old_value  Old value of the network option.
  1583.          * @param int    $network_id ID of the network.
  1584.          */
  1585.         do_action( "update_site_option_{$option}", $option, $value, $old_value, $network_id );
  1586.  
  1587.         /**
  1588.          * Fires after the value of a network option has been successfully updated.
  1589.          *
  1590.          * @since 3.0.0
  1591.          * @since 4.7.0 The `$network_id` parameter was added.
  1592.          *
  1593.          * @param string $option     Name of the network option.
  1594.          * @param mixed  $value      Current value of the network option.
  1595.          * @param mixed  $old_value  Old value of the network option.
  1596.          * @param int    $network_id ID of the network.
  1597.          */
  1598.         do_action( 'update_site_option', $option, $value, $old_value, $network_id );
  1599.  
  1600.         return true;
  1601.     }
  1602.  
  1603.     return false;
  1604. }
  1605.  
  1606. /**
  1607.  * Delete a site transient.
  1608.  *
  1609.  * @since 2.9.0
  1610.  *
  1611.  * @param string $transient Transient name. Expected to not be SQL-escaped.
  1612.  * @return bool True if successful, false otherwise
  1613.  */
  1614. function delete_site_transient( $transient ) {
  1615.  
  1616.     /**
  1617.      * Fires immediately before a specific site transient is deleted.
  1618.      *
  1619.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  1620.      *
  1621.      * @since 3.0.0
  1622.      *
  1623.      * @param string $transient Transient name.
  1624.      */
  1625.     do_action( "delete_site_transient_{$transient}", $transient );
  1626.  
  1627.     if ( wp_using_ext_object_cache() ) {
  1628.         $result = wp_cache_delete( $transient, 'site-transient' );
  1629.     } else {
  1630.         $option_timeout = '_site_transient_timeout_' . $transient;
  1631.         $option = '_site_transient_' . $transient;
  1632.         $result = delete_site_option( $option );
  1633.         if ( $result )
  1634.             delete_site_option( $option_timeout );
  1635.     }
  1636.     if ( $result ) {
  1637.  
  1638.         /**
  1639.          * Fires after a transient is deleted.
  1640.          *
  1641.          * @since 3.0.0
  1642.          *
  1643.          * @param string $transient Deleted transient name.
  1644.          */
  1645.         do_action( 'deleted_site_transient', $transient );
  1646.     }
  1647.  
  1648.     return $result;
  1649. }
  1650.  
  1651. /**
  1652.  * Get the value of a site transient.
  1653.  *
  1654.  * If the transient does not exist, does not have a value, or has expired,
  1655.  * then the return value will be false.
  1656.  *
  1657.  * @since 2.9.0
  1658.  *
  1659.  * @see get_transient()
  1660.  *
  1661.  * @param string $transient Transient name. Expected to not be SQL-escaped.
  1662.  * @return mixed Value of transient.
  1663.  */
  1664. function get_site_transient( $transient ) {
  1665.  
  1666.     /**
  1667.      * Filters the value of an existing site transient.
  1668.      *
  1669.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  1670.      *
  1671.      * Passing a truthy value to the filter will effectively short-circuit retrieval,
  1672.      * returning the passed value instead.
  1673.      *
  1674.      * @since 2.9.0
  1675.      * @since 4.4.0 The `$transient` parameter was added.
  1676.      *
  1677.      * @param mixed  $pre_site_transient The default value to return if the site transient does not exist.
  1678.      *                                   Any value other than false will short-circuit the retrieval
  1679.      *                                   of the transient, and return the returned value.
  1680.      * @param string $transient          Transient name.
  1681.      */
  1682.     $pre = apply_filters( "pre_site_transient_{$transient}", false, $transient );
  1683.  
  1684.     if ( false !== $pre )
  1685.         return $pre;
  1686.  
  1687.     if ( wp_using_ext_object_cache() ) {
  1688.         $value = wp_cache_get( $transient, 'site-transient' );
  1689.     } else {
  1690.         // Core transients that do not have a timeout. Listed here so querying timeouts can be avoided.
  1691.         $no_timeout = array('update_core', 'update_plugins', 'update_themes');
  1692.         $transient_option = '_site_transient_' . $transient;
  1693.         if ( ! in_array( $transient, $no_timeout ) ) {
  1694.             $transient_timeout = '_site_transient_timeout_' . $transient;
  1695.             $timeout = get_site_option( $transient_timeout );
  1696.             if ( false !== $timeout && $timeout < time() ) {
  1697.                 delete_site_option( $transient_option  );
  1698.                 delete_site_option( $transient_timeout );
  1699.                 $value = false;
  1700.             }
  1701.         }
  1702.  
  1703.         if ( ! isset( $value ) )
  1704.             $value = get_site_option( $transient_option );
  1705.     }
  1706.  
  1707.     /**
  1708.      * Filters the value of an existing site transient.
  1709.      *
  1710.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  1711.      *
  1712.      * @since 2.9.0
  1713.      * @since 4.4.0 The `$transient` parameter was added.
  1714.      *
  1715.      * @param mixed  $value     Value of site transient.
  1716.      * @param string $transient Transient name.
  1717.      */
  1718.     return apply_filters( "site_transient_{$transient}", $value, $transient );
  1719. }
  1720.  
  1721. /**
  1722.  * Set/update the value of a site transient.
  1723.  *
  1724.  * You do not need to serialize values, if the value needs to be serialize, then
  1725.  * it will be serialized before it is set.
  1726.  *
  1727.  * @since 2.9.0
  1728.  *
  1729.  * @see set_transient()
  1730.  *
  1731.  * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
  1732.  *                           167 characters or fewer in length.
  1733.  * @param mixed  $value      Transient value. Expected to not be SQL-escaped.
  1734.  * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
  1735.  * @return bool False if value was not set and true if value was set.
  1736.  */
  1737. function set_site_transient( $transient, $value, $expiration = 0 ) {
  1738.  
  1739.     /**
  1740.      * Filters the value of a specific site transient before it is set.
  1741.      *
  1742.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  1743.      *
  1744.      * @since 3.0.0
  1745.      * @since 4.4.0 The `$transient` parameter was added.
  1746.      *
  1747.      * @param mixed  $value     New value of site transient.
  1748.      * @param string $transient Transient name.
  1749.      */
  1750.     $value = apply_filters( "pre_set_site_transient_{$transient}", $value, $transient );
  1751.  
  1752.     $expiration = (int) $expiration;
  1753.  
  1754.     /**
  1755.      * Filters the expiration for a site transient before its value is set.
  1756.      *
  1757.      * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  1758.      *
  1759.      * @since 4.4.0
  1760.      *
  1761.      * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
  1762.      * @param mixed  $value      New value of site transient.
  1763.      * @param string $transient  Transient name.
  1764.      */
  1765.     $expiration = apply_filters( "expiration_of_site_transient_{$transient}", $expiration, $value, $transient );
  1766.  
  1767.     if ( wp_using_ext_object_cache() ) {
  1768.         $result = wp_cache_set( $transient, $value, 'site-transient', $expiration );
  1769.     } else {
  1770.         $transient_timeout = '_site_transient_timeout_' . $transient;
  1771.         $option = '_site_transient_' . $transient;
  1772.         if ( false === get_site_option( $option ) ) {
  1773.             if ( $expiration )
  1774.                 add_site_option( $transient_timeout, time() + $expiration );
  1775.             $result = add_site_option( $option, $value );
  1776.         } else {
  1777.             if ( $expiration )
  1778.                 update_site_option( $transient_timeout, time() + $expiration );
  1779.             $result = update_site_option( $option, $value );
  1780.         }
  1781.     }
  1782.     if ( $result ) {
  1783.  
  1784.         /**
  1785.          * Fires after the value for a specific site transient has been set.
  1786.          *
  1787.          * The dynamic portion of the hook name, `$transient`, refers to the transient name.
  1788.          *
  1789.          * @since 3.0.0
  1790.          * @since 4.4.0 The `$transient` parameter was added
  1791.          *
  1792.          * @param mixed  $value      Site transient value.
  1793.          * @param int    $expiration Time until expiration in seconds.
  1794.          * @param string $transient  Transient name.
  1795.          */
  1796.         do_action( "set_site_transient_{$transient}", $value, $expiration, $transient );
  1797.  
  1798.         /**
  1799.          * Fires after the value for a site transient has been set.
  1800.          *
  1801.          * @since 3.0.0
  1802.          *
  1803.          * @param string $transient  The name of the site transient.
  1804.          * @param mixed  $value      Site transient value.
  1805.          * @param int    $expiration Time until expiration in seconds.
  1806.          */
  1807.         do_action( 'setted_site_transient', $transient, $value, $expiration );
  1808.     }
  1809.     return $result;
  1810. }
  1811.  
  1812. /**
  1813.  * Register default settings available in WordPress.
  1814.  *
  1815.  * The settings registered here are primarily useful for the REST API, so this
  1816.  * does not encompass all settings available in WordPress.
  1817.  *
  1818.  * @since 4.7.0
  1819.  */
  1820. function register_initial_settings() {
  1821.     register_setting( 'general', 'blogname', array(
  1822.         'show_in_rest' => array(
  1823.             'name' => 'title',
  1824.         ),
  1825.         'type'         => 'string',
  1826.         'description'  => __( 'Site title.' ),
  1827.     ) );
  1828.  
  1829.     register_setting( 'general', 'blogdescription', array(
  1830.         'show_in_rest' => array(
  1831.             'name' => 'description',
  1832.         ),
  1833.         'type'         => 'string',
  1834.         'description'  => __( 'Site tagline.' ),
  1835.     ) );
  1836.  
  1837.     if ( ! is_multisite() ) {
  1838.         register_setting( 'general', 'siteurl', array(
  1839.             'show_in_rest' => array(
  1840.                 'name'    => 'url',
  1841.                 'schema'  => array(
  1842.                     'format' => 'uri',
  1843.                 ),
  1844.             ),
  1845.             'type'         => 'string',
  1846.             'description'  => __( 'Site URL.' ),
  1847.         ) );
  1848.     }
  1849.  
  1850.     if ( ! is_multisite() ) {
  1851.         register_setting( 'general', 'admin_email', array(
  1852.             'show_in_rest' => array(
  1853.                 'name'    => 'email',
  1854.                 'schema'  => array(
  1855.                     'format' => 'email',
  1856.                 ),
  1857.             ),
  1858.             'type'         => 'string',
  1859.             'description'  => __( 'This address is used for admin purposes, like new user notification.' ),
  1860.         ) );
  1861.     }
  1862.  
  1863.     register_setting( 'general', 'timezone_string', array(
  1864.         'show_in_rest' => array(
  1865.             'name' => 'timezone',
  1866.         ),
  1867.         'type'         => 'string',
  1868.         'description'  => __( 'A city in the same timezone as you.' ),
  1869.     ) );
  1870.  
  1871.     register_setting( 'general', 'date_format', array(
  1872.         'show_in_rest' => true,
  1873.         'type'         => 'string',
  1874.         'description'  => __( 'A date format for all date strings.' ),
  1875.     ) );
  1876.  
  1877.     register_setting( 'general', 'time_format', array(
  1878.         'show_in_rest' => true,
  1879.         'type'         => 'string',
  1880.         'description'  => __( 'A time format for all time strings.' ),
  1881.     ) );
  1882.  
  1883.     register_setting( 'general', 'start_of_week', array(
  1884.         'show_in_rest' => true,
  1885.         'type'         => 'integer',
  1886.         'description'  => __( 'A day number of the week that the week should start on.' ),
  1887.     ) );
  1888.  
  1889.     register_setting( 'general', 'WPLANG', array(
  1890.         'show_in_rest' => array(
  1891.             'name' => 'language',
  1892.         ),
  1893.         'type'         => 'string',
  1894.         'description'  => __( 'WordPress locale code.' ),
  1895.         'default'      => 'en_US',
  1896.     ) );
  1897.  
  1898.     register_setting( 'writing', 'use_smilies', array(
  1899.         'show_in_rest' => true,
  1900.         'type'         => 'boolean',
  1901.         'description'  => __( 'Convert emoticons like :-) and :-P to graphics on display.' ),
  1902.         'default'      => true,
  1903.     ) );
  1904.  
  1905.     register_setting( 'writing', 'default_category', array(
  1906.         'show_in_rest' => true,
  1907.         'type'         => 'integer',
  1908.         'description'  => __( 'Default post category.' ),
  1909.     ) );
  1910.  
  1911.     register_setting( 'writing', 'default_post_format', array(
  1912.         'show_in_rest' => true,
  1913.         'type'         => 'string',
  1914.         'description'  => __( 'Default post format.' ),
  1915.     ) );
  1916.  
  1917.     register_setting( 'reading', 'posts_per_page', array(
  1918.         'show_in_rest' => true,
  1919.         'type'         => 'integer',
  1920.         'description'  => __( 'Blog pages show at most.' ),
  1921.         'default'      => 10,
  1922.     ) );
  1923.  
  1924.     register_setting( 'discussion', 'default_ping_status', array(
  1925.         'show_in_rest' => array(
  1926.             'schema'   => array(
  1927.                 'enum' => array( 'open', 'closed' ),
  1928.             ),
  1929.         ),
  1930.         'type'         => 'string',
  1931.         'description'  => __( 'Allow link notifications from other blogs (pingbacks and trackbacks) on new articles.' ),
  1932.     ) );
  1933.  
  1934.     register_setting( 'discussion', 'default_comment_status', array(
  1935.         'show_in_rest' => array(
  1936.             'schema'   => array(
  1937.                 'enum' => array( 'open', 'closed' ),
  1938.             ),
  1939.         ),
  1940.         'type'         => 'string',
  1941.         'description'  => __( 'Allow people to post comments on new articles.' ),
  1942.     ) );
  1943.  
  1944. }
  1945.  
  1946. /**
  1947.  * Register a setting and its data.
  1948.  *
  1949.  * @since 2.7.0
  1950.  * @since 4.7.0 `$args` can be passed to set flags on the setting, similar to `register_meta()`.
  1951.  *
  1952.  * @global array $new_whitelist_options
  1953.  * @global array $wp_registered_settings
  1954.  *
  1955.  * @param string $option_group A settings group name. Should correspond to a whitelisted option key name.
  1956.  *     Default whitelisted option key names include "general," "discussion," and "reading," among others.
  1957.  * @param string $option_name The name of an option to sanitize and save.
  1958.  * @param array  $args {
  1959.  *     Data used to describe the setting when registered.
  1960.  *
  1961.  *     @type string   $type              The type of data associated with this setting.
  1962.  *                                       Valid values are 'string', 'boolean', 'integer', and 'number'.
  1963.  *     @type string   $description       A description of the data attached to this setting.
  1964.  *     @type callable $sanitize_callback A callback function that sanitizes the option's value.
  1965.  *     @type bool     $show_in_rest      Whether data associated with this setting should be included in the REST API.
  1966.  *     @type mixed    $default           Default value when calling `get_option()`.
  1967.  * }
  1968.  */
  1969. function register_setting( $option_group, $option_name, $args = array() ) {
  1970.     global $new_whitelist_options, $wp_registered_settings;
  1971.  
  1972.     $defaults = array(
  1973.         'type'              => 'string',
  1974.         'group'             => $option_group,
  1975.         'description'       => '',
  1976.         'sanitize_callback' => null,
  1977.         'show_in_rest'      => false,
  1978.     );
  1979.  
  1980.     // Back-compat: old sanitize callback is added.
  1981.     if ( is_callable( $args ) ) {
  1982.         $args = array(
  1983.             'sanitize_callback' => $args,
  1984.         );
  1985.     }
  1986.  
  1987.     /**
  1988.      * Filters the registration arguments when registering a setting.
  1989.      *
  1990.      * @since 4.7.0
  1991.      *
  1992.      * @param array  $args         Array of setting registration arguments.
  1993.      * @param array  $defaults     Array of default arguments.
  1994.      * @param string $option_group Setting group.
  1995.      * @param string $option_name  Setting name.
  1996.      */
  1997.     $args = apply_filters( 'register_setting_args', $args, $defaults, $option_group, $option_name );
  1998.     $args = wp_parse_args( $args, $defaults );
  1999.  
  2000.     if ( ! is_array( $wp_registered_settings ) ) {
  2001.         $wp_registered_settings = array();
  2002.     }
  2003.  
  2004.     if ( 'misc' == $option_group ) {
  2005.         _deprecated_argument( __FUNCTION__, '3.0.0',
  2006.             /* translators: %s: misc */
  2007.             sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ),
  2008.                 'misc'
  2009.             )
  2010.         );
  2011.         $option_group = 'general';
  2012.     }
  2013.  
  2014.     if ( 'privacy' == $option_group ) {
  2015.         _deprecated_argument( __FUNCTION__, '3.5.0',
  2016.             /* translators: %s: privacy */
  2017.             sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ),
  2018.                 'privacy'
  2019.             )
  2020.         );
  2021.         $option_group = 'reading';
  2022.     }
  2023.  
  2024.     $new_whitelist_options[ $option_group ][] = $option_name;
  2025.     if ( ! empty( $args['sanitize_callback'] ) ) {
  2026.         add_filter( "sanitize_option_{$option_name}", $args['sanitize_callback'] );
  2027.     }
  2028.     if ( array_key_exists( 'default', $args ) ) {
  2029.         add_filter( "default_option_{$option_name}", 'filter_default_option', 10, 3 );
  2030.     }
  2031.  
  2032.     $wp_registered_settings[ $option_name ] = $args;
  2033. }
  2034.  
  2035. /**
  2036.  * Unregister a setting.
  2037.  *
  2038.  * @since 2.7.0
  2039.  * @since 4.7.0 `$sanitize_callback` was deprecated. The callback from `register_setting()` is now used instead.
  2040.  *
  2041.  * @global array $new_whitelist_options
  2042.  *
  2043.  * @param string   $option_group      The settings group name used during registration.
  2044.  * @param string   $option_name       The name of the option to unregister.
  2045.  * @param callable $deprecated        Deprecated.
  2046.  */
  2047. function unregister_setting( $option_group, $option_name, $deprecated = '' ) {
  2048.     global $new_whitelist_options, $wp_registered_settings;
  2049.  
  2050.     if ( 'misc' == $option_group ) {
  2051.         _deprecated_argument( __FUNCTION__, '3.0.0',
  2052.             /* translators: %s: misc */
  2053.             sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ),
  2054.                 'misc'
  2055.             )
  2056.         );
  2057.         $option_group = 'general';
  2058.     }
  2059.  
  2060.     if ( 'privacy' == $option_group ) {
  2061.         _deprecated_argument( __FUNCTION__, '3.5.0',
  2062.             /* translators: %s: privacy */
  2063.             sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ),
  2064.                 'privacy'
  2065.             )
  2066.         );
  2067.         $option_group = 'reading';
  2068.     }
  2069.  
  2070.     $pos = array_search( $option_name, (array) $new_whitelist_options[ $option_group ] );
  2071.     if ( $pos !== false ) {
  2072.         unset( $new_whitelist_options[ $option_group ][ $pos ] );
  2073.     }
  2074.     if ( '' !== $deprecated ) {
  2075.         _deprecated_argument( __FUNCTION__, '4.7.0',
  2076.             /* translators: 1: $sanitize_callback, 2: register_setting() */
  2077.             sprintf( __( '%1$s is deprecated. The callback from %2$s is used instead.' ),
  2078.                 '<code>$sanitize_callback</code>',
  2079.                 '<code>register_setting()</code>'
  2080.             )
  2081.         );
  2082.         remove_filter( "sanitize_option_{$option_name}", $deprecated );
  2083.     }
  2084.  
  2085.     if ( isset( $wp_registered_settings[ $option_name ] ) ) {
  2086.         // Remove the sanitize callback if one was set during registration.
  2087.         if ( ! empty( $wp_registered_settings[ $option_name ]['sanitize_callback'] ) ) {
  2088.             remove_filter( "sanitize_option_{$option_name}", $wp_registered_settings[ $option_name ]['sanitize_callback'] );
  2089.         }
  2090.  
  2091.         unset( $wp_registered_settings[ $option_name ] );
  2092.     }
  2093. }
  2094.  
  2095. /**
  2096.  * Retrieves an array of registered settings.
  2097.  *
  2098.  * @since 4.7.0
  2099.  *
  2100.  * @return array List of registered settings, keyed by option name.
  2101.  */
  2102. function get_registered_settings() {
  2103.     global $wp_registered_settings;
  2104.  
  2105.     if ( ! is_array( $wp_registered_settings ) ) {
  2106.         return array();
  2107.     }
  2108.  
  2109.     return $wp_registered_settings;
  2110. }
  2111.  
  2112. /**
  2113.  * Filter the default value for the option.
  2114.  *
  2115.  * For settings which register a default setting in `register_setting()`, this
  2116.  * function is added as a filter to `default_option_{$option}`.
  2117.  *
  2118.  * @since 4.7.0
  2119.  *
  2120.  * @param mixed $default Existing default value to return.
  2121.  * @param string $option Option name.
  2122.  * @param bool $passed_default Was `get_option()` passed a default value?
  2123.  * @return mixed Filtered default value.
  2124.  */
  2125. function filter_default_option( $default, $option, $passed_default ) {
  2126.     if ( $passed_default ) {
  2127.         return $default;
  2128.     }
  2129.  
  2130.     $registered = get_registered_settings();
  2131.     if ( empty( $registered[ $option ] ) ) {
  2132.         return $default;
  2133.     }
  2134.  
  2135.     return $registered[ $option ]['default'];
  2136. }
  2137.