/**
  * Handles serving an API request.
  *
  * Matches the current server URI to a route and runs the first matching
  * callback then outputs a JSON representation of the returned value.
  *
  * @since 4.4.0
  * @access public
  *
  * @see WP_REST_Server::dispatch()
  *
  * @param string $path Optional. The request route. If not set, `$_SERVER['PATH_INFO']` will be used.
  *                     Default null.
  * @return false|null Null if not served and a HEAD request, false otherwise.
  */
 public function serve_request($path = null)
 {
     $content_type = isset($_GET['_jsonp']) ? 'application/javascript' : 'application/json';
     $this->send_header('Content-Type', $content_type . '; charset=' . get_option('blog_charset'));
     $this->send_header('X-Robots-Tag', 'noindex');
     $api_root = get_rest_url();
     if (!empty($api_root)) {
         $this->send_header('Link', '<' . esc_url_raw($api_root) . '>; rel="https://api.w.org/"');
     }
     /*
      * Mitigate possible JSONP Flash attacks.
      *
      * https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
      */
     $this->send_header('X-Content-Type-Options', 'nosniff');
     $this->send_header('Access-Control-Expose-Headers', 'X-WP-Total, X-WP-TotalPages');
     $this->send_header('Access-Control-Allow-Headers', 'Authorization, Content-Type');
     /**
      * Send nocache headers on authenticated requests.
      *
      * @since 4.4.0
      *
      * @param bool $rest_send_nocache_headers Whether to send no-cache headers.
      */
     $send_no_cache_headers = apply_filters('rest_send_nocache_headers', is_user_logged_in());
     if ($send_no_cache_headers) {
         foreach (wp_get_nocache_headers() as $header => $header_value) {
             $this->send_header($header, $header_value);
         }
     }
     /**
      * Filters whether the REST API is enabled.
      *
      * @since 4.4.0
      * @deprecated 4.7.0 Use the rest_authentication_errors filter to restrict access to the API
      *
      * @param bool $rest_enabled Whether the REST API is enabled. Default true.
      */
     apply_filters_deprecated('rest_enabled', array(true), '4.7.0', 'rest_authentication_errors', __('The REST API can no longer be completely disabled, the rest_authentication_errors can be used to restrict access to the API, instead.'));
     /**
      * Filters whether jsonp is enabled.
      *
      * @since 4.4.0
      *
      * @param bool $jsonp_enabled Whether jsonp is enabled. Default true.
      */
     $jsonp_enabled = apply_filters('rest_jsonp_enabled', true);
     $jsonp_callback = null;
     if (isset($_GET['_jsonp'])) {
         if (!$jsonp_enabled) {
             echo $this->json_error('rest_callback_disabled', __('JSONP support is disabled on this site.'), 400);
             return false;
         }
         $jsonp_callback = $_GET['_jsonp'];
         if (!wp_check_jsonp_callback($jsonp_callback)) {
             echo $this->json_error('rest_callback_invalid', __('The JSONP callback function is invalid.'), 400);
             return false;
         }
     }
     if (empty($path)) {
         if (isset($_SERVER['PATH_INFO'])) {
             $path = $_SERVER['PATH_INFO'];
         } else {
             $path = '/';
         }
     }
     $request = new WP_REST_Request($_SERVER['REQUEST_METHOD'], $path);
     $request->set_query_params(wp_unslash($_GET));
     $request->set_body_params(wp_unslash($_POST));
     $request->set_file_params($_FILES);
     $request->set_headers($this->get_headers(wp_unslash($_SERVER)));
     $request->set_body($this->get_raw_data());
     /*
      * HTTP method override for clients that can't use PUT/PATCH/DELETE. First, we check
      * $_GET['_method']. If that is not set, we check for the HTTP_X_HTTP_METHOD_OVERRIDE
      * header.
      */
     if (isset($_GET['_method'])) {
         $request->set_method($_GET['_method']);
     } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
         $request->set_method($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
     }
     $result = $this->check_authentication();
     if (!is_wp_error($result)) {
         $result = $this->dispatch($request);
     }
     // Normalize to either WP_Error or WP_REST_Response...
     $result = rest_ensure_response($result);
     // ...then convert WP_Error across.
     if (is_wp_error($result)) {
         $result = $this->error_to_response($result);
     }
     /**
      * Filters the API response.
      *
      * Allows modification of the response before returning.
      *
      * @since 4.4.0
      * @since 4.5.0 Applied to embedded responses.
      *
      * @param WP_HTTP_Response $result  Result to send to the client. Usually a WP_REST_Response.
      * @param WP_REST_Server   $this    Server instance.
      * @param WP_REST_Request  $request Request used to generate the response.
      */
     $result = apply_filters('rest_post_dispatch', rest_ensure_response($result), $this, $request);
     // Wrap the response in an envelope if asked for.
     if (isset($_GET['_envelope'])) {
         $result = $this->envelope_response($result, isset($_GET['_embed']));
     }
     // Send extra data from response objects.
     $headers = $result->get_headers();
     $this->send_headers($headers);
     $code = $result->get_status();
     $this->set_status($code);
     /**
      * Filters whether the request has already been served.
      *
      * Allow sending the request manually - by returning true, the API result
      * will not be sent to the client.
      *
      * @since 4.4.0
      *
      * @param bool             $served  Whether the request has already been served.
      *                                           Default false.
      * @param WP_HTTP_Response $result  Result to send to the client. Usually a WP_REST_Response.
      * @param WP_REST_Request  $request Request used to generate the response.
      * @param WP_REST_Server   $this    Server instance.
      */
     $served = apply_filters('rest_pre_serve_request', false, $result, $request, $this);
     if (!$served) {
         if ('HEAD' === $request->get_method()) {
             return null;
         }
         // Embed links inside the request.
         $result = $this->response_to_data($result, isset($_GET['_embed']));
         $result = wp_json_encode($result);
         $json_error_message = $this->get_json_last_error();
         if ($json_error_message) {
             $json_error_obj = new WP_Error('rest_encode_error', $json_error_message, array('status' => 500));
             $result = $this->error_to_response($json_error_obj);
             $result = wp_json_encode($result->data[0]);
         }
         if ($jsonp_callback) {
             // Prepend '/**/' to mitigate possible JSONP Flash attacks.
             // https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
             echo '/**/' . $jsonp_callback . '(' . $result . ')';
         } else {
             echo $result;
         }
     }
     return null;
 }
Пример #2
0
 /**
  * @ticket 10441
  */
 public function test_apply_filters_deprecated_without_filter()
 {
     $val = 'Foobar';
     $this->assertSame($val, apply_filters_deprecated('tests_apply_filters_deprecated', array($val), '4.6'));
 }
 /**
  * Retrieves the details for this site.
  *
  * This method is used internally to lazy-load the extended properties of a site.
  *
  * @since 4.6.0
  * @access private
  *
  * @see WP_Site::__get()
  *
  * @return stdClass A raw site object with all details included.
  */
 private function get_details()
 {
     $details = wp_cache_get($this->blog_id, 'site-details');
     if (false === $details) {
         switch_to_blog($this->blog_id);
         // Create a raw copy of the object for backwards compatibility with the filter below.
         $details = new stdClass();
         foreach (get_object_vars($this) as $key => $value) {
             $details->{$key} = $value;
         }
         $details->blogname = get_option('blogname');
         $details->siteurl = get_option('siteurl');
         $details->post_count = get_option('post_count');
         $details->home = get_option('home');
         restore_current_blog();
         $cache_details = true;
         foreach (array('blogname', 'siteurl', 'post_count', 'home') as $field) {
             if (false === $details->{$field}) {
                 $cache_details = false;
                 break;
             }
         }
         if ($cache_details) {
             wp_cache_set($this->blog_id, $details, 'site-details');
         }
     }
     /** This filter is documented in wp-includes/ms-blogs.php */
     $details = apply_filters_deprecated('blog_details', array($details), '4.7.0', 'site_details');
     /**
      * Filters a site's extended properties.
      *
      * @since 4.6.0
      *
      * @param stdClass $details The site details.
      */
     $details = apply_filters('site_details', $details);
     return $details;
 }
Пример #4
0
 /**
  * @ticket 10441
  * @expectedDeprecated tests_apply_filters_deprecated
  */
 public function test_apply_filters_deprecated_with_multiple_params()
 {
     $p1 = 'Foo1';
     $p2 = 'Foo2';
     add_filter('tests_apply_filters_deprecated', array(__CLASS__, 'deprecated_filter_callback_multiple_params'), 10, 2);
     $p1 = apply_filters_deprecated('tests_apply_filters_deprecated', array($p1, $p2), '4.6');
     remove_filter('tests_apply_filters_deprecated', array(__CLASS__, 'deprecated_filter_callback_multiple_params'), 10, 2);
     $this->assertSame('Bar1', $p1);
     // Not passed by reference, so not modified.
     $this->assertSame('Foo2', $p2);
 }
/**
 * Retrieve the details for a blog from the blogs table and blog options.
 *
 * @since MU
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|string|array $fields  Optional. A blog ID, a blog slug, or an array of fields to query against.
 *                                  If not specified the current blog ID is used.
 * @param bool             $get_all Whether to retrieve all details or only the details in the blogs table.
 *                                  Default is true.
 * @return WP_Site|false Blog details on success. False on failure.
 */
function get_blog_details($fields = null, $get_all = true)
{
    global $wpdb;
    if (is_array($fields)) {
        if (isset($fields['blog_id'])) {
            $blog_id = $fields['blog_id'];
        } elseif (isset($fields['domain']) && isset($fields['path'])) {
            $key = md5($fields['domain'] . $fields['path']);
            $blog = wp_cache_get($key, 'blog-lookup');
            if (false !== $blog) {
                return $blog;
            }
            if (substr($fields['domain'], 0, 4) == 'www.') {
                $nowww = substr($fields['domain'], 4);
                $blog = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->blogs} WHERE domain IN (%s,%s) AND path = %s ORDER BY CHAR_LENGTH(domain) DESC", $nowww, $fields['domain'], $fields['path']));
            } else {
                $blog = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->blogs} WHERE domain = %s AND path = %s", $fields['domain'], $fields['path']));
            }
            if ($blog) {
                wp_cache_set($blog->blog_id . 'short', $blog, 'blog-details');
                $blog_id = $blog->blog_id;
            } else {
                return false;
            }
        } elseif (isset($fields['domain']) && is_subdomain_install()) {
            $key = md5($fields['domain']);
            $blog = wp_cache_get($key, 'blog-lookup');
            if (false !== $blog) {
                return $blog;
            }
            if (substr($fields['domain'], 0, 4) == 'www.') {
                $nowww = substr($fields['domain'], 4);
                $blog = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->blogs} WHERE domain IN (%s,%s) ORDER BY CHAR_LENGTH(domain) DESC", $nowww, $fields['domain']));
            } else {
                $blog = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->blogs} WHERE domain = %s", $fields['domain']));
            }
            if ($blog) {
                wp_cache_set($blog->blog_id . 'short', $blog, 'blog-details');
                $blog_id = $blog->blog_id;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if (!$fields) {
            $blog_id = get_current_blog_id();
        } elseif (!is_numeric($fields)) {
            $blog_id = get_id_from_blogname($fields);
        } else {
            $blog_id = $fields;
        }
    }
    $blog_id = (int) $blog_id;
    $all = $get_all == true ? '' : 'short';
    $details = wp_cache_get($blog_id . $all, 'blog-details');
    if ($details) {
        if (!is_object($details)) {
            if ($details == -1) {
                return false;
            } else {
                // Clear old pre-serialized objects. Cache clients do better with that.
                wp_cache_delete($blog_id . $all, 'blog-details');
                unset($details);
            }
        } else {
            return $details;
        }
    }
    // Try the other cache.
    if ($get_all) {
        $details = wp_cache_get($blog_id . 'short', 'blog-details');
    } else {
        $details = wp_cache_get($blog_id, 'blog-details');
        // If short was requested and full cache is set, we can return.
        if ($details) {
            if (!is_object($details)) {
                if ($details == -1) {
                    return false;
                } else {
                    // Clear old pre-serialized objects. Cache clients do better with that.
                    wp_cache_delete($blog_id, 'blog-details');
                    unset($details);
                }
            } else {
                return $details;
            }
        }
    }
    if (empty($details)) {
        $details = WP_Site::get_instance($blog_id);
        if (!$details) {
            // Set the full cache.
            wp_cache_set($blog_id, -1, 'blog-details');
            return false;
        }
    }
    if (!$details instanceof WP_Site) {
        $details = new WP_Site($details);
    }
    if (!$get_all) {
        wp_cache_set($blog_id . $all, $details, 'blog-details');
        return $details;
    }
    switch_to_blog($blog_id);
    $details->blogname = get_option('blogname');
    $details->siteurl = get_option('siteurl');
    $details->post_count = get_option('post_count');
    $details->home = get_option('home');
    restore_current_blog();
    /**
     * Filters a blog's details.
     *
     * @since MU
     * @deprecated 4.7.0 Use site_details
     *
     * @param object $details The blog details.
     */
    $details = apply_filters_deprecated('blog_details', array($details), '4.7.0', 'site_details');
    wp_cache_set($blog_id . $all, $details, 'blog-details');
    $key = md5($details->domain . $details->path);
    wp_cache_set($key, $details, 'blog-lookup');
    return $details;
}
Пример #6
0
 /**
  * Allows developers to use 'github_updater_set_options' hook to set access tokens or other settings.
  * Saves results of filter hook to self::$options.
  *
  * Hook requires return of associative element array.
  * $key === repo-name and $value === token
  * e.g.  array( 'repo-name' => 'access_token' );
  *
  * @TODO Set `Requires WP: 4.6` and only use current filter and apply_filters_deprecated
  */
 public function set_options_filter()
 {
     // Single plugin/theme should not be using both hooks.
     $config = apply_filters('github_updater_set_options', array());
     if (empty($config)) {
         $config = function_exists('apply_filters_deprecated') ? apply_filters_deprecated('github_updater_token_distribution', array(null), '6.1.0', 'github_updater_set_options') : apply_filters('github_updater_token_distribution', array());
     }
     if (!empty($config)) {
         $config = Settings::sanitize($config);
         self::$options = array_merge(get_site_option('github_updater'), $config);
         update_site_option('github_updater', self::$options);
     }
 }