| 1779 | |
| 1780 | |
| 1781 | /** |
| 1782 | * Outputs a header link to a REST resource |
| 1783 | * |
| 1784 | * @since 5.5.0 |
| 1785 | * |
| 1786 | * @param string $url URL. |
| 1787 | */ |
| 1788 | function rest_head_link( $url ) { |
| 1789 | if ( ! empty( $url ) ) { |
| 1790 | printf( '<link rel="alternate" type="application/json" href="%s" />', esc_url( $url ) ); |
| 1791 | } |
| 1792 | } |
| 1793 | |
| 1794 | /** |
| 1795 | * Return the rest route for a post. |
| 1796 | * |
| 1797 | * @since 5.5.0 |
| 1798 | * |
| 1799 | * @param WP_Post $post Post Object. |
| 1800 | * @return string Route. |
| 1801 | */ |
| 1802 | function rest_get_route_for_post( $post ) { |
| 1803 | if ( ! $post instanceof WP_Post ) { |
| 1804 | return ''; |
| 1805 | } |
| 1806 | |
| 1807 | $post_type = get_post_type_object( $post->post_type ); |
| 1808 | if ( ! $post_type ) { |
| 1809 | return ''; |
| 1810 | } |
| 1811 | |
| 1812 | $route = ''; |
| 1813 | $controller = $post_type->get_rest_controller(); |
| 1814 | |
| 1815 | // The only two controllers that we can detect are the Attachments and Posts controllers. |
| 1816 | if ( ! empty( $controller ) && in_array( $controller, array( 'WP_REST_Attachments_Controller', 'WP_REST_Posts_Controller' ), true ) ) { |
| 1817 | $namespace = 'wp/v2'; |
| 1818 | $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; |
| 1819 | $route = sprintf( '%s/%s/%d', $namespace, $rest_base, $post->ID ); |
| 1820 | } |
| 1821 | |
| 1822 | /** |
| 1823 | * Filters the route based on information in the post object. |
| 1824 | * |
| 1825 | * @since 5.5.0 |
| 1826 | * |
| 1827 | * @param string $route Route. |
| 1828 | * @param WP_Post $post Post Object. |
| 1829 | */ |
| 1830 | return apply_filters( 'rest_route_for_post', $route, $post ); |
| 1831 | } |
| 1832 | |
| 1833 | /** |
| 1834 | * Return the rest route for a term. |
| 1835 | * |
| 1836 | * @since 5.5.0 |
| 1837 | * |
| 1838 | * @param WP_Term $term Term. |
| 1839 | * @return string Route. |
| 1840 | */ |
| 1841 | function rest_get_route_for_term( $term ) { |
| 1842 | if ( ! $term instanceof WP_Term ) { |
| 1843 | return ''; |
| 1844 | } |
| 1845 | |
| 1846 | $taxonomy = get_taxonomy( $term->taxonomy ); |
| 1847 | if ( ! $taxonomy ) { |
| 1848 | return ''; |
| 1849 | } |
| 1850 | |
| 1851 | $route = ''; |
| 1852 | $controller = $taxonomy->get_rest_controller(); |
| 1853 | // The only controller that works is the Terms controller. |
| 1854 | if ( ! empty( $controller ) && 'WP_REST_Terms_Controller' === $controller ) { |
| 1855 | $namespace = 'wp/v2'; |
| 1856 | $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxnomomy->name; |
| 1857 | $route = sprintf( '%s/%s/%d', $namespace, $rest_base, $term->term_id ); |
| 1858 | } |
| 1859 | |
| 1860 | /** |
| 1861 | * Filters the route based on information in the term object. |
| 1862 | * |
| 1863 | * @since 5.5.0 |
| 1864 | * |
| 1865 | * @param string $route Route. |
| 1866 | * @param WP_Term $term Term Object. |
| 1867 | */ |
| 1868 | return apply_filters( 'rest_route_for_term', $route, $term ); |
| 1869 | } |
| 1870 | |
| 1871 | /** |
| 1872 | * Get a REST URL for the current object. |
| 1873 | * |
| 1874 | * @param string URL. |
| 1875 | */ |
| 1876 | function rest_get_current_resource_link() { |
| 1877 | if ( is_singular() ) { |
| 1878 | return rest_url( rest_get_route_for_post( get_post() ) ); |
| 1879 | } elseif ( is_category() || is_tag() || is_tax() ) { |
| 1880 | return rest_url( rest_get_route_for_term( get_queried_object() ); |
| 1881 | } elseif ( is_author() ) { |
| 1882 | return rest_url( 'wp/v2/users/' . get_the_author_meta( 'ID' ) ); |
| 1883 | } |
| 1884 | } |
| 1885 | |
| 1886 | /** |
| 1887 | * Add a link to the current REST API resource. |
| 1888 | * |
| 1889 | * @since 5.5.0 |
| 1890 | * |
| 1891 | */ |
| 1892 | function rest_add_resource_link() { |
| 1893 | rest_head_link( rest_get_current_resource_link() ); |
| 1894 | } |