Changeset 49246 for trunk/src/wp-includes/rest-api.php
- Timestamp:
- 10/20/2020 06:22:39 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api.php
r49225 r49246 1666 1666 1667 1667 /** 1668 * Formats a combining operation error into a WP_Error object. 1669 * 1670 * @since 5.6.0 1671 * 1672 * @param string $param The parameter name. 1673 * @param array $error The error details. 1674 * @return WP_Error 1675 */ 1676 function rest_format_combining_operation_error( $param, $error ) { 1677 $position = $error['index']; 1678 $reason = $error['error_object']->get_error_message(); 1679 1680 if ( isset( $error['schema']['title'] ) ) { 1681 $title = $error['schema']['title']; 1682 1683 return new WP_Error( 1684 'rest_invalid_param', 1685 /* translators: 1: Parameter, 2: Schema title, 3: Reason. */ 1686 sprintf( __( '%1$s is not a valid %2$s. Reason: %3$s' ), $param, $title, $reason ), 1687 array( 'position' => $position ) 1688 ); 1689 } 1690 1691 return new WP_Error( 1692 'rest_invalid_param', 1693 /* translators: 1: Parameter, 2: Reason. */ 1694 sprintf( __( '%1$s does not match the expected format. Reason: %2$s' ), $param, $reason ), 1695 array( 'position' => $position ) 1696 ); 1697 } 1698 1699 /** 1700 * Gets the error of combining operation. 1701 * 1702 * @since 5.6.0 1703 * 1704 * @param array $value The value to validate. 1705 * @param string $param The parameter name, used in error messages. 1706 * @param array $errors The errors array, to search for possible error. 1707 * @return WP_Error The combining operation error. 1708 */ 1709 function rest_get_combining_operation_error( $value, $param, $errors ) { 1710 // If there is only one error, simply return it. 1711 if ( 1 === count( $errors ) ) { 1712 return rest_format_combining_operation_error( $param, $errors[0] ); 1713 } 1714 1715 // Filter out all errors related to type validation. 1716 $filtered_errors = array(); 1717 foreach ( $errors as $error ) { 1718 $error_code = $error['error_object']->get_error_code(); 1719 $error_data = $error['error_object']->get_error_data(); 1720 1721 if ( 'rest_invalid_type' !== $error_code || ( isset( $error_data['param'] ) && $param !== $error_data['param'] ) ) { 1722 $filtered_errors[] = $error; 1723 } 1724 } 1725 1726 // If there is only one error left, simply return it. 1727 if ( 1 === count( $filtered_errors ) ) { 1728 return rest_format_combining_operation_error( $param, $filtered_errors[0] ); 1729 } 1730 1731 // If there are only errors related to object validation, try choosing the most appropriate one. 1732 if ( count( $filtered_errors ) > 1 && 'object' === $filtered_errors[0]['schema']['type'] ) { 1733 $result = null; 1734 $number = 0; 1735 1736 foreach ( $filtered_errors as $error ) { 1737 if ( isset( $error['schema']['properties'] ) ) { 1738 $n = count( array_intersect_key( $error['schema']['properties'], $value ) ); 1739 if ( $n > $number ) { 1740 $result = $error; 1741 $number = $n; 1742 } 1743 } 1744 } 1745 1746 if ( null !== $result ) { 1747 return rest_format_combining_operation_error( $param, $result ); 1748 } 1749 } 1750 1751 // If each schema has a title, include those titles in the error message. 1752 $schema_titles = array(); 1753 foreach ( $errors as $error ) { 1754 if ( isset( $error['schema']['title'] ) ) { 1755 $schema_titles[] = $error['schema']['title']; 1756 } 1757 } 1758 1759 if ( count( $schema_titles ) === count( $errors ) ) { 1760 /* translators: 1: Parameter, 2: Schema titles. */ 1761 return new WP_Error( 'rest_invalid_param', wp_sprintf( __( '%1$s is not a valid %2$l.' ), $param, $schema_titles ) ); 1762 } 1763 1764 /* translators: 1: Parameter. */ 1765 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s does not match any of the expected formats.' ), $param ) ); 1766 } 1767 1768 /** 1769 * Finds the matching schema among the "anyOf" schemas. 1770 * 1771 * @since 5.6.0 1772 * 1773 * @param mixed $value The value to validate. 1774 * @param array $args The schema array to use. 1775 * @param string $param The parameter name, used in error messages. 1776 * @return array|WP_Error The matching schema or WP_Error instance if all schemas do not match. 1777 */ 1778 function rest_find_any_matching_schema( $value, $args, $param ) { 1779 $errors = array(); 1780 1781 foreach ( $args['anyOf'] as $index => $schema ) { 1782 if ( ! isset( $schema['type'] ) && isset( $args['type'] ) ) { 1783 $schema['type'] = $args['type']; 1784 } 1785 1786 $is_valid = rest_validate_value_from_schema( $value, $schema, $param ); 1787 if ( ! is_wp_error( $is_valid ) ) { 1788 return $schema; 1789 } 1790 1791 $errors[] = array( 1792 'error_object' => $is_valid, 1793 'schema' => $schema, 1794 'index' => $index, 1795 ); 1796 } 1797 1798 return rest_get_combining_operation_error( $value, $param, $errors ); 1799 } 1800 1801 /** 1802 * Finds the matching schema among the "oneOf" schemas. 1803 * 1804 * @since 5.6.0 1805 * 1806 * @param mixed $value The value to validate. 1807 * @param array $args The schema array to use. 1808 * @param string $param The parameter name, used in error messages. 1809 * @param bool $stop_after_first_match Optional. Whether the process should stop after the first successful match. 1810 * @return array|WP_Error The matching schema or WP_Error instance if the number of matching schemas is not equal to one. 1811 */ 1812 function rest_find_one_matching_schema( $value, $args, $param, $stop_after_first_match = false ) { 1813 $matching_schemas = array(); 1814 $errors = array(); 1815 1816 foreach ( $args['oneOf'] as $index => $schema ) { 1817 if ( ! isset( $schema['type'] ) && isset( $args['type'] ) ) { 1818 $schema['type'] = $args['type']; 1819 } 1820 1821 $is_valid = rest_validate_value_from_schema( $value, $schema, $param ); 1822 if ( ! is_wp_error( $is_valid ) ) { 1823 if ( $stop_after_first_match ) { 1824 return $schema; 1825 } 1826 1827 $matching_schemas[] = array( 1828 'schema_object' => $schema, 1829 'index' => $index, 1830 ); 1831 } else { 1832 $errors[] = array( 1833 'error_object' => $is_valid, 1834 'schema' => $schema, 1835 'index' => $index, 1836 ); 1837 } 1838 } 1839 1840 if ( ! $matching_schemas ) { 1841 return rest_get_combining_operation_error( $value, $param, $errors ); 1842 } 1843 1844 if ( count( $matching_schemas ) > 1 ) { 1845 $schema_positions = array(); 1846 $schema_titles = array(); 1847 1848 foreach ( $matching_schemas as $schema ) { 1849 $schema_positions[] = $schema['index']; 1850 1851 if ( isset( $schema['schema_object']['title'] ) ) { 1852 $schema_titles[] = $schema['schema_object']['title']; 1853 } 1854 } 1855 1856 // If each schema has a title, include those titles in the error message. 1857 if ( count( $schema_titles ) === count( $matching_schemas ) ) { 1858 return new WP_Error( 1859 'rest_invalid_param', 1860 /* translators: 1: Parameter, 2: Schema titles. */ 1861 wp_sprintf( __( '%1$s matches %2$l, but should match only one.' ), $param, $schema_titles ), 1862 array( 'positions' => $schema_positions ) 1863 ); 1864 } 1865 1866 return new WP_Error( 1867 'rest_invalid_param', 1868 /* translators: 1: Parameter. */ 1869 sprintf( __( '%1$s matches more than one of the expected formats.' ), $param ), 1870 array( 'positions' => $schema_positions ) 1871 ); 1872 } 1873 1874 return $matching_schemas[0]['schema_object']; 1875 } 1876 1877 /** 1668 1878 * Validate a value based on a schema. 1669 1879 * … … 1680 1890 * Support the "multipleOf" keyword for numbers and integers. 1681 1891 * Support the "patternProperties" keyword for objects. 1892 * Support the "anyOf" and "oneOf" keywords. 1682 1893 * 1683 1894 * @param mixed $value The value to validate. … … 1687 1898 */ 1688 1899 function rest_validate_value_from_schema( $value, $args, $param = '' ) { 1900 if ( isset( $args['anyOf'] ) ) { 1901 $matching_schema = rest_find_any_matching_schema( $value, $args, $param ); 1902 if ( is_wp_error( $matching_schema ) ) { 1903 return $matching_schema; 1904 } 1905 1906 if ( ! isset( $args['type'] ) && isset( $matching_schema['type'] ) ) { 1907 $args['type'] = $matching_schema['type']; 1908 } 1909 } 1910 1911 if ( isset( $args['oneOf'] ) ) { 1912 $matching_schema = rest_find_one_matching_schema( $value, $args, $param ); 1913 if ( is_wp_error( $matching_schema ) ) { 1914 return $matching_schema; 1915 } 1916 1917 if ( ! isset( $args['type'] ) && isset( $matching_schema['type'] ) ) { 1918 $args['type'] = $matching_schema['type']; 1919 } 1920 } 1921 1689 1922 $allowed_types = array( 'array', 'object', 'string', 'number', 'integer', 'boolean', 'null' ); 1690 1923 … … 1698 1931 1699 1932 if ( ! $best_type ) { 1700 /* translators: 1: Parameter, 2: List of types. */ 1701 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, implode( ',', $args['type'] ) ) ); 1933 return new WP_Error( 1934 'rest_invalid_type', 1935 /* translators: 1: Parameter, 2: List of types. */ 1936 sprintf( __( '%1$s is not of type %2$s.' ), $param, implode( ',', $args['type'] ) ), 1937 array( 'param' => $param ) 1938 ); 1702 1939 } 1703 1940 … … 1716 1953 if ( 'array' === $args['type'] ) { 1717 1954 if ( ! rest_is_array( $value ) ) { 1718 /* translators: 1: Parameter, 2: Type name. */ 1719 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'array' ) ); 1955 return new WP_Error( 1956 'rest_invalid_type', 1957 /* translators: 1: Parameter, 2: Type name. */ 1958 sprintf( __( '%1$s is not of type %2$s.' ), $param, 'array' ), 1959 array( 'param' => $param ) 1960 ); 1720 1961 } 1721 1962 … … 1749 1990 if ( 'object' === $args['type'] ) { 1750 1991 if ( ! rest_is_object( $value ) ) { 1751 /* translators: 1: Parameter, 2: Type name. */ 1752 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'object' ) ); 1992 return new WP_Error( 1993 'rest_invalid_type', 1994 /* translators: 1: Parameter, 2: Type name. */ 1995 sprintf( __( '%1$s is not of type %2$s.' ), $param, 'object' ), 1996 array( 'param' => $param ) 1997 ); 1753 1998 } 1754 1999 … … 1817 2062 if ( 'null' === $args['type'] ) { 1818 2063 if ( null !== $value ) { 1819 /* translators: 1: Parameter, 2: Type name. */ 1820 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'null' ) ); 2064 return new WP_Error( 2065 'rest_invalid_type', 2066 /* translators: 1: Parameter, 2: Type name. */ 2067 sprintf( __( '%1$s is not of type %2$s.' ), $param, 'null' ), 2068 array( 'param' => $param ) 2069 ); 1821 2070 } 1822 2071 … … 1833 2082 if ( in_array( $args['type'], array( 'integer', 'number' ), true ) ) { 1834 2083 if ( ! is_numeric( $value ) ) { 1835 /* translators: 1: Parameter, 2: Type name. */ 1836 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, $args['type'] ) ); 2084 return new WP_Error( 2085 'rest_invalid_type', 2086 /* translators: 1: Parameter, 2: Type name. */ 2087 sprintf( __( '%1$s is not of type %2$s.' ), $param, $args['type'] ), 2088 array( 'param' => $param ) 2089 ); 1837 2090 } 1838 2091 … … 1844 2097 1845 2098 if ( 'integer' === $args['type'] && ! rest_is_integer( $value ) ) { 1846 /* translators: 1: Parameter, 2: Type name. */ 1847 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'integer' ) ); 2099 return new WP_Error( 2100 'rest_invalid_type', 2101 /* translators: 1: Parameter, 2: Type name. */ 2102 sprintf( __( '%1$s is not of type %2$s.' ), $param, 'integer' ), 2103 array( 'param' => $param ) 2104 ); 1848 2105 } 1849 2106 1850 2107 if ( 'boolean' === $args['type'] && ! rest_is_boolean( $value ) ) { 1851 /* translators: 1: Parameter, 2: Type name. */ 1852 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'boolean' ) ); 2108 return new WP_Error( 2109 'rest_invalid_type', 2110 /* translators: 1: Parameter, 2: Type name. */ 2111 sprintf( __( '%1$s is not of type %2$s.' ), $param, 'boolean' ), 2112 array( 'param' => $param ) 2113 ); 1853 2114 } 1854 2115 1855 2116 if ( 'string' === $args['type'] ) { 1856 2117 if ( ! is_string( $value ) ) { 1857 /* translators: 1: Parameter, 2: Type name. */ 1858 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'string' ) ); 2118 return new WP_Error( 2119 'rest_invalid_type', 2120 /* translators: 1: Parameter, 2: Type name. */ 2121 sprintf( __( '%1$s is not of type %2$s.' ), $param, 'string' ), 2122 array( 'param' => $param ) 2123 ); 1859 2124 } 1860 2125 … … 1977 2242 * @since 4.7.0 1978 2243 * @since 5.5.0 Added the `$param` parameter. 2244 * @since 5.6.0 Support the "anyOf" and "oneOf" keywords. 1979 2245 * 1980 2246 * @param mixed $value The value to sanitize. … … 1984 2250 */ 1985 2251 function rest_sanitize_value_from_schema( $value, $args, $param = '' ) { 2252 if ( isset( $args['anyOf'] ) ) { 2253 $matching_schema = rest_find_any_matching_schema( $value, $args, $param ); 2254 if ( is_wp_error( $matching_schema ) ) { 2255 return $matching_schema; 2256 } 2257 2258 if ( ! isset( $args['type'] ) ) { 2259 $args['type'] = $matching_schema['type']; 2260 } 2261 2262 $value = rest_sanitize_value_from_schema( $value, $matching_schema, $param ); 2263 } 2264 2265 if ( isset( $args['oneOf'] ) ) { 2266 $matching_schema = rest_find_one_matching_schema( $value, $args, $param ); 2267 if ( is_wp_error( $matching_schema ) ) { 2268 return $matching_schema; 2269 } 2270 2271 if ( ! isset( $args['type'] ) ) { 2272 $args['type'] = $matching_schema['type']; 2273 } 2274 2275 $value = rest_sanitize_value_from_schema( $value, $matching_schema, $param ); 2276 } 2277 1986 2278 $allowed_types = array( 'array', 'object', 'string', 'number', 'integer', 'boolean', 'null' ); 1987 2279 … … 2199 2491 * @since 5.5.0 2200 2492 * @since 5.6.0 Support the "patternProperties" keyword for objects. 2493 * Support the "anyOf" and "oneOf" keywords. 2201 2494 * 2202 2495 * @param array|object $data The response data to modify. … … 2206 2499 */ 2207 2500 function rest_filter_response_by_context( $data, $schema, $context ) { 2501 if ( isset( $schema['anyOf'] ) ) { 2502 $matching_schema = rest_find_any_matching_schema( $data, $schema, '' ); 2503 if ( ! is_wp_error( $matching_schema ) ) { 2504 if ( ! isset( $schema['type'] ) ) { 2505 $schema['type'] = $matching_schema['type']; 2506 } 2507 2508 $data = rest_filter_response_by_context( $data, $matching_schema, $context ); 2509 } 2510 } 2511 2512 if ( isset( $schema['oneOf'] ) ) { 2513 $matching_schema = rest_find_one_matching_schema( $data, $schema, '', true ); 2514 if ( ! is_wp_error( $matching_schema ) ) { 2515 if ( ! isset( $schema['type'] ) ) { 2516 $schema['type'] = $matching_schema['type']; 2517 } 2518 2519 $data = rest_filter_response_by_context( $data, $matching_schema, $context ); 2520 } 2521 } 2522 2208 2523 if ( ! is_array( $data ) && ! is_object( $data ) ) { 2209 2524 return $data; … … 2472 2787 'maxItems', 2473 2788 'uniqueItems', 2789 'anyOf', 2790 'oneOf', 2474 2791 ); 2475 2792
Note: See TracChangeset
for help on using the changeset viewer.