Changeset 50010
 Timestamp:
 01/24/2021 04:50:39 PM (10 months ago)
 Location:
 trunk
 Files:

 2 edited
Legend:
 Unmodified
 Added
 Removed

trunk/src/wpincludes/restapi.php
r50007 r50010 1873 1873 1874 1874 return $matching_schemas[0]['schema_object']; 1875 } 1876 1877 /** 1878 * Checks the equality of two values, following JSON Schema semantics. 1879 * 1880 * Property order is ignored for objects. 1881 * 1882 * Values must have been previously sanitized/coerced to their native types. 1883 * 1884 * @since 5.7.0 1885 * 1886 * @param mixed $value1 The first value to check. 1887 * @param mixed $value2 The second value to check. 1888 * @return bool True if the values are equal or false otherwise. 1889 */ 1890 function rest_are_values_equal( $value1, $value2 ) { 1891 if ( is_array( $value1 ) && is_array( $value2 ) ) { 1892 if ( count( $value1 ) !== count( $value2 ) ) { 1893 return false; 1894 } 1895 1896 foreach ( $value1 as $index => $value ) { 1897 if ( ! array_key_exists( $index, $value2 )  ! rest_are_values_equal( $value, $value2[ $index ] ) ) { 1898 return false; 1899 } 1900 } 1901 1902 return true; 1903 } 1904 1905 return $value1 === $value2; 1906 } 1907 1908 /** 1909 * Validates that the given value is a member of the JSON Schema "enum". 1910 * 1911 * @since 5.7.0 1912 * 1913 * @param mixed $value The value to validate. 1914 * @param array $args The schema array to use. 1915 * @param string $param The parameter name, used in error messages. 1916 * @return trueWP_Error True if the "enum" contains the value or a WP_Error instance otherwise. 1917 */ 1918 function rest_validate_enum( $value, $args, $param ) { 1919 $sanitized_value = rest_sanitize_value_from_schema( $value, $args, $param ); 1920 if ( is_wp_error( $sanitized_value ) ) { 1921 return $sanitized_value; 1922 } 1923 1924 foreach ( $args['enum'] as $enum_value ) { 1925 if ( rest_are_values_equal( $sanitized_value, $enum_value ) ) { 1926 return true; 1927 } 1928 } 1929 1930 $encoded_enum_values = array(); 1931 foreach ( $args['enum'] as $enum_value ) { 1932 $encoded_enum_values[] = is_scalar( $enum_value ) ? $enum_value : wp_json_encode( $enum_value ); 1933 } 1934 1935 if ( count( $encoded_enum_values ) === 1 ) { 1936 /* translators: 1: Parameter, 2: Valid values. */ 1937 return new WP_Error( 'rest_not_in_enum', wp_sprintf( __( '%1$s is not %2$s.' ), $param, $encoded_enum_values[0] ) ); 1938 } 1939 1940 /* translators: 1: Parameter, 2: List of valid values. */ 1941 return new WP_Error( 'rest_not_in_enum', wp_sprintf( __( '%1$s is not one of %2$l.' ), $param, $encoded_enum_values ) ); 1875 1942 } 1876 1943 … … 2154 2221 } 2155 2222 2156 if ( ! empty( $args['enum'] ) ) {2157 if ( ! in_array( $value, $args['enum'], true ) ) {2158 /* translators: 1: Parameter, 2: List of valid values. */2159 return new WP_Error( 'rest_not_in_enum', sprintf( __( '%1$s is not one of %2$s.' ), $param, implode( ', ', $args['enum'] ) ) );2160 }2161 }2162 2163 2223 if ( in_array( $args['type'], array( 'integer', 'number' ), true ) ) { 2164 2224 if ( ! is_numeric( $value ) ) { … … 2232 2292 /* translators: 1: Parameter, 2: Pattern. */ 2233 2293 return new WP_Error( 'rest_invalid_pattern', sprintf( __( '%1$s does not match pattern %2$s.' ), $param, $args['pattern'] ) ); 2294 } 2295 } 2296 2297 if ( ! empty( $args['enum'] ) ) { 2298 $enum_contains_value = rest_validate_enum( $value, $args, $param ); 2299 if ( is_wp_error( $enum_contains_value ) ) { 2300 return $enum_contains_value; 2234 2301 } 2235 2302 } 
trunk/tests/phpunit/tests/restapi/restschemavalidation.php
r49246 r50010 247 247 $this>assertTrue( rest_validate_value_from_schema( 'ribs,chicken,', $schema ) ); 248 248 $this>assertTrue( rest_validate_value_from_schema( '', $schema ) ); 249 } 250 251 /** 252 * @ticket 51911 253 * 254 * @dataProvider data_different_types_of_value_and_enum_elements 255 * 256 * @param mixed $value 257 * @param array $args 258 * @param bool $expected 259 */ 260 public function test_different_types_of_value_and_enum_elements( $value, $args, $expected ) { 261 $result = rest_validate_value_from_schema( $value, $args ); 262 if ( $expected ) { 263 $this>assertTrue( $result ); 264 } else { 265 $this>assertWPError( $result ); 266 } 267 } 268 269 /** 270 * @return array 271 */ 272 public function data_different_types_of_value_and_enum_elements() { 273 return array( 274 // enum with integers 275 array( 276 0, 277 array( 278 'type' => 'integer', 279 'enum' => array( 0, 1 ), 280 ), 281 true, 282 ), 283 array( 284 0.0, 285 array( 286 'type' => 'integer', 287 'enum' => array( 0, 1 ), 288 ), 289 true, 290 ), 291 array( 292 '0', 293 array( 294 'type' => 'integer', 295 'enum' => array( 0, 1 ), 296 ), 297 true, 298 ), 299 array( 300 1, 301 array( 302 'type' => 'integer', 303 'enum' => array( 0, 1 ), 304 ), 305 true, 306 ), 307 array( 308 1.0, 309 array( 310 'type' => 'integer', 311 'enum' => array( 0, 1 ), 312 ), 313 true, 314 ), 315 array( 316 '1', 317 array( 318 'type' => 'integer', 319 'enum' => array( 0, 1 ), 320 ), 321 true, 322 ), 323 array( 324 2, 325 array( 326 'type' => 'integer', 327 'enum' => array( 0, 1 ), 328 ), 329 false, 330 ), 331 array( 332 2.0, 333 array( 334 'type' => 'integer', 335 'enum' => array( 0, 1 ), 336 ), 337 false, 338 ), 339 array( 340 '2', 341 array( 342 'type' => 'integer', 343 'enum' => array( 0, 1 ), 344 ), 345 false, 346 ), 347 348 // enum with floats 349 array( 350 0, 351 array( 352 'type' => 'number', 353 'enum' => array( 0.0, 1.0 ), 354 ), 355 true, 356 ), 357 array( 358 0.0, 359 array( 360 'type' => 'number', 361 'enum' => array( 0.0, 1.0 ), 362 ), 363 true, 364 ), 365 array( 366 '0', 367 array( 368 'type' => 'number', 369 'enum' => array( 0.0, 1.0 ), 370 ), 371 true, 372 ), 373 array( 374 1, 375 array( 376 'type' => 'number', 377 'enum' => array( 0.0, 1.0 ), 378 ), 379 true, 380 ), 381 array( 382 1.0, 383 array( 384 'type' => 'number', 385 'enum' => array( 0.0, 1.0 ), 386 ), 387 true, 388 ), 389 array( 390 '1', 391 array( 392 'type' => 'number', 393 'enum' => array( 0.0, 1.0 ), 394 ), 395 true, 396 ), 397 array( 398 2, 399 array( 400 'type' => 'number', 401 'enum' => array( 0.0, 1.0 ), 402 ), 403 false, 404 ), 405 array( 406 2.0, 407 array( 408 'type' => 'number', 409 'enum' => array( 0.0, 1.0 ), 410 ), 411 false, 412 ), 413 array( 414 '2', 415 array( 416 'type' => 'number', 417 'enum' => array( 0.0, 1.0 ), 418 ), 419 false, 420 ), 421 422 // enum with booleans 423 array( 424 true, 425 array( 426 'type' => 'boolean', 427 'enum' => array( true ), 428 ), 429 true, 430 ), 431 array( 432 1, 433 array( 434 'type' => 'boolean', 435 'enum' => array( true ), 436 ), 437 true, 438 ), 439 array( 440 'true', 441 array( 442 'type' => 'boolean', 443 'enum' => array( true ), 444 ), 445 true, 446 ), 447 array( 448 false, 449 array( 450 'type' => 'boolean', 451 'enum' => array( true ), 452 ), 453 false, 454 ), 455 array( 456 0, 457 array( 458 'type' => 'boolean', 459 'enum' => array( true ), 460 ), 461 false, 462 ), 463 array( 464 'false', 465 array( 466 'type' => 'boolean', 467 'enum' => array( true ), 468 ), 469 false, 470 ), 471 array( 472 false, 473 array( 474 'type' => 'boolean', 475 'enum' => array( false ), 476 ), 477 true, 478 ), 479 array( 480 0, 481 array( 482 'type' => 'boolean', 483 'enum' => array( false ), 484 ), 485 true, 486 ), 487 array( 488 'false', 489 array( 490 'type' => 'boolean', 491 'enum' => array( false ), 492 ), 493 true, 494 ), 495 array( 496 true, 497 array( 498 'type' => 'boolean', 499 'enum' => array( false ), 500 ), 501 false, 502 ), 503 array( 504 1, 505 array( 506 'type' => 'boolean', 507 'enum' => array( false ), 508 ), 509 false, 510 ), 511 array( 512 'true', 513 array( 514 'type' => 'boolean', 515 'enum' => array( false ), 516 ), 517 false, 518 ), 519 520 // enum with arrays 521 array( 522 array( 0, 1 ), 523 array( 524 'type' => 'array', 525 'items' => array( 'type' => 'integer' ), 526 'enum' => array( array( 0, 1 ), array( 1, 2 ) ), 527 ), 528 true, 529 ), 530 array( 531 array( '0', 1 ), 532 array( 533 'type' => 'array', 534 'items' => array( 'type' => 'integer' ), 535 'enum' => array( array( 0, 1 ), array( 1, 2 ) ), 536 ), 537 true, 538 ), 539 array( 540 array( 0, '1' ), 541 array( 542 'type' => 'array', 543 'items' => array( 'type' => 'integer' ), 544 'enum' => array( array( 0, 1 ), array( 1, 2 ) ), 545 ), 546 true, 547 ), 548 array( 549 array( '0', '1' ), 550 array( 551 'type' => 'array', 552 'items' => array( 'type' => 'integer' ), 553 'enum' => array( array( 0, 1 ), array( 1, 2 ) ), 554 ), 555 true, 556 ), 557 array( 558 array( 1, 2 ), 559 array( 560 'type' => 'array', 561 'items' => array( 'type' => 'integer' ), 562 'enum' => array( array( 0, 1 ), array( 1, 2 ) ), 563 ), 564 true, 565 ), 566 array( 567 array( 2, 3 ), 568 array( 569 'type' => 'array', 570 'items' => array( 'type' => 'integer' ), 571 'enum' => array( array( 0, 1 ), array( 1, 2 ) ), 572 ), 573 false, 574 ), 575 array( 576 array( 1, 0 ), 577 array( 578 'type' => 'array', 579 'items' => array( 'type' => 'integer' ), 580 'enum' => array( array( 0, 1 ), array( 1, 2 ) ), 581 ), 582 false, 583 ), 584 585 // enum with objects 586 array( 587 array( 588 'a' => 1, 589 'b' => 2, 590 ), 591 array( 592 'type' => 'object', 593 'additionalProperties' => array( 'type' => 'integer' ), 594 'enum' => array( 595 array( 596 'a' => 1, 597 'b' => 2, 598 ), 599 array( 600 'b' => 2, 601 'c' => 3, 602 ), 603 ), 604 ), 605 true, 606 ), 607 array( 608 array( 609 'a' => '1', 610 'b' => 2, 611 ), 612 array( 613 'type' => 'object', 614 'additionalProperties' => array( 'type' => 'integer' ), 615 'enum' => array( 616 array( 617 'a' => 1, 618 'b' => 2, 619 ), 620 array( 621 'b' => 2, 622 'c' => 3, 623 ), 624 ), 625 ), 626 true, 627 ), 628 array( 629 array( 630 'a' => 1, 631 'b' => '2', 632 ), 633 array( 634 'type' => 'object', 635 'additionalProperties' => array( 'type' => 'integer' ), 636 'enum' => array( 637 array( 638 'a' => 1, 639 'b' => 2, 640 ), 641 array( 642 'b' => 2, 643 'c' => 3, 644 ), 645 ), 646 ), 647 true, 648 ), 649 array( 650 array( 651 'a' => '1', 652 'b' => '2', 653 ), 654 array( 655 'type' => 'object', 656 'additionalProperties' => array( 'type' => 'integer' ), 657 'enum' => array( 658 array( 659 'a' => 1, 660 'b' => 2, 661 ), 662 array( 663 'b' => 2, 664 'c' => 3, 665 ), 666 ), 667 ), 668 true, 669 ), 670 array( 671 array( 672 'b' => 2, 673 'a' => 1, 674 ), 675 array( 676 'type' => 'object', 677 'additionalProperties' => array( 'type' => 'integer' ), 678 'enum' => array( 679 array( 680 'a' => 1, 681 'b' => 2, 682 ), 683 array( 684 'b' => 2, 685 'c' => 3, 686 ), 687 ), 688 ), 689 true, 690 ), 691 array( 692 array( 693 'b' => 2, 694 'c' => 3, 695 ), 696 array( 697 'type' => 'object', 698 'additionalProperties' => array( 'type' => 'integer' ), 699 'enum' => array( 700 array( 701 'a' => 1, 702 'b' => 2, 703 ), 704 array( 705 'b' => 2, 706 'c' => 3, 707 ), 708 ), 709 ), 710 true, 711 ), 712 array( 713 array( 714 'a' => 1, 715 'b' => 3, 716 ), 717 array( 718 'type' => 'object', 719 'additionalProperties' => array( 'type' => 'integer' ), 720 'enum' => array( 721 array( 722 'a' => 1, 723 'b' => 2, 724 ), 725 array( 726 'b' => 2, 727 'c' => 3, 728 ), 729 ), 730 ), 731 false, 732 ), 733 array( 734 array( 735 'c' => 3, 736 'd' => 4, 737 ), 738 array( 739 'type' => 'object', 740 'additionalProperties' => array( 'type' => 'integer' ), 741 'enum' => array( 742 array( 743 'a' => 1, 744 'b' => 2, 745 ), 746 array( 747 'b' => 2, 748 'c' => 3, 749 ), 750 ), 751 ), 752 false, 753 ), 754 ); 249 755 } 250 756
Note: See TracChangeset
for help on using the changeset viewer.