Make WordPress Core


Ignore:
Timestamp:
07/02/2020 05:55:04 AM (6 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Link to the REST route for the currently queried resource.

This allows for programatically determining the REST version of the current page. The links also aid human discovery of the REST API in general.

Props dshanske, tfrommen, TimothyBlynJacobs.
Fixes #49116.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api.php

    r48242 r48273  
    235235        // Terms.
    236236        foreach ( get_taxonomies( array( 'show_in_rest' => true ), 'object' ) as $taxonomy ) {
    237                 $class = ! empty( $taxonomy->rest_controller_class ) ? $taxonomy->rest_controller_class : 'WP_REST_Terms_Controller';
    238 
    239                 if ( ! class_exists( $class ) ) {
    240                         continue;
    241                 }
    242                 $controller = new $class( $taxonomy->name );
    243                 if ( ! is_subclass_of( $controller, 'WP_REST_Controller' ) ) {
     237                $controller = $taxonomy->get_rest_controller();
     238
     239                if ( ! $controller ) {
    244240                        continue;
    245241                }
     
    874870        }
    875871
    876         echo "<link rel='https://api.w.org/' href='" . esc_url( $api_root ) . "' />\n";
     872        printf( '<link rel="https://api.w.org/" href="%s" />', esc_url( $api_root ) );
     873
     874        $resource = rest_get_queried_resource_route();
     875
     876        if ( $resource ) {
     877                printf( '<link rel="alternate" type="application/json" href="%s" />', esc_url( rest_url( $resource ) ) );
     878        }
    877879}
    878880
     
    893895        }
    894896
    895         header( 'Link: <' . esc_url_raw( $api_root ) . '>; rel="https://api.w.org/"', false );
     897        header( sprintf( 'Link: <%s>; rel="https://api.w.org/"', esc_url_raw( $api_root ) ), false );
     898
     899        $resource = rest_get_queried_resource_route();
     900
     901        if ( $resource ) {
     902                header( sprintf( 'Link: <%s>; rel="alternate"; type="application/json"', esc_url_raw( rest_url( $resource ) ) ), false );
     903        }
    896904}
    897905
     
    18241832        return $schema;
    18251833}
     1834
     1835/**
     1836 * Gets the REST API route for a post.
     1837 *
     1838 * @since 5.5.0
     1839 *
     1840 * @param int|WP_Post $post Post ID or post object.
     1841 * @return string The route path with a leading slash for the given post, or an empty string if there is not a route.
     1842 */
     1843function rest_get_route_for_post( $post ) {
     1844        $post = get_post( $post );
     1845
     1846        if ( ! $post instanceof WP_Post ) {
     1847                return '';
     1848        }
     1849
     1850        $post_type = get_post_type_object( $post->post_type );
     1851        if ( ! $post_type ) {
     1852                return '';
     1853        }
     1854
     1855        $controller = $post_type->get_rest_controller();
     1856        if ( ! $controller ) {
     1857                return '';
     1858        }
     1859
     1860        $route = '';
     1861
     1862        // The only two controllers that we can detect are the Attachments and Posts controllers.
     1863        if ( in_array( get_class( $controller ), array( 'WP_REST_Attachments_Controller', 'WP_REST_Posts_Controller' ), true ) ) {
     1864                $namespace = 'wp/v2';
     1865                $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name;
     1866                $route     = sprintf( '/%s/%s/%d', $namespace, $rest_base, $post->ID );
     1867        }
     1868
     1869        /**
     1870         * Filters the REST API route for a post.
     1871         *
     1872         * @since 5.5.0
     1873         *
     1874         * @param string  $route The route path.
     1875         * @param WP_Post $post  The post object.
     1876         */
     1877        return apply_filters( 'rest_route_for_post', $route, $post );
     1878}
     1879
     1880/**
     1881 * Gets the REST API route for a term.
     1882 *
     1883 * @since 5.5.0
     1884 *
     1885 * @param int|WP_Term $term Term ID or term object.
     1886 * @return string The route path with a leading slash for the given term, or an empty string if there is not a route.
     1887 */
     1888function rest_get_route_for_term( $term ) {
     1889        $term = get_term( $term );
     1890
     1891        if ( ! $term instanceof WP_Term ) {
     1892                return '';
     1893        }
     1894
     1895        $taxonomy = get_taxonomy( $term->taxonomy );
     1896        if ( ! $taxonomy ) {
     1897                return '';
     1898        }
     1899
     1900        $controller = $taxonomy->get_rest_controller();
     1901        if ( ! $controller ) {
     1902                return '';
     1903        }
     1904
     1905        $route = '';
     1906
     1907        // The only controller that works is the Terms controller.
     1908        if ( 'WP_REST_Terms_Controller' === get_class( $controller ) ) {
     1909                $namespace = 'wp/v2';
     1910                $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
     1911                $route     = sprintf( '/%s/%s/%d', $namespace, $rest_base, $term->term_id );
     1912        }
     1913
     1914        /**
     1915         * Filters the REST API route for a term.
     1916         *
     1917         * @since 5.5.0
     1918         *
     1919         * @param string  $route The route path.
     1920         * @param WP_Term $term  The term object.
     1921         */
     1922        return apply_filters( 'rest_route_for_term', $route, $term );
     1923}
     1924
     1925/**
     1926 * Gets the REST route for the currently queried object.
     1927 *
     1928 * @since 5.5.0
     1929 *
     1930 * @return string The REST route of the resource, or an empty string if no resource identified.
     1931 */
     1932function rest_get_queried_resource_route() {
     1933        if ( is_singular() ) {
     1934                $route = rest_get_route_for_post( get_queried_object() );
     1935        } elseif ( is_category() || is_tag() || is_tax() ) {
     1936                $route = rest_get_route_for_term( get_queried_object() );
     1937        } elseif ( is_author() ) {
     1938                $route = '/wp/v2/users/' . get_queried_object_id();
     1939        } else {
     1940                $route = '';
     1941        }
     1942
     1943        /**
     1944         * Filters the REST route for the currently queried object.
     1945         *
     1946         * @since 5.5.0
     1947         *
     1948         * @param string $link The route with a leading slash, or an empty string.
     1949         */
     1950        return apply_filters( 'rest_queried_resource_route', $route );
     1951}
Note: See TracChangeset for help on using the changeset viewer.