| @@ -6,8 +6,10 @@ | ||
| 6 | 6 | * @author Tobias Bäthge |
| 7 | 7 | * @since 1.0.0 |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | +declare(strict_types=1); | |
| 11 | + | |
| 10 | 12 | // Prohibit direct script loading. |
| 11 | 13 | defined( 'ABSPATH' ) || die( 'No direct script access allowed!' ); |
| 12 | 14 | |
| 13 | 15 | /** |
| @@ -26,9 +28,9 @@ | ||
| 26 | 28 | * |
| 27 | 29 | * @since 1.0.0 |
| 28 | 30 | * @const string |
| 29 | 31 | */ |
| 30 | - public const version = '3.3.4'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase | |
| 32 | + public const version = '3.4'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase | |
| 31 | 33 | |
| 32 | 34 | /** |
| 33 | 35 | * TablePress internal plugin version ("options scheme" version). |
| 34 | 36 | * |
| @@ -36,9 +38,9 @@ | ||
| 36 | 38 | * |
| 37 | 39 | * @since 1.0.0 |
| 38 | 40 | * @const int |
| 39 | 41 | */ |
| 40 | - public const db_version = 131; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase | |
| 42 | + public const db_version = 133; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase | |
| 41 | 43 | |
| 42 | 44 | /** |
| 43 | 45 | * TablePress "table scheme" (data format structure) version. |
| 44 | 46 | * |
| @@ -360,8 +362,102 @@ | ||
| 360 | 362 | return $column; |
| 361 | 363 | } |
| 362 | 364 | |
| 363 | 365 | /** |
| 366 | + * Converts a range string (e.g., "1-5" or "A-E") to an array of numbers. | |
| 367 | + * | |
| 368 | + * @since 3.4.0 | |
| 369 | + * | |
| 370 | + * @param string $value The range string. | |
| 371 | + * @param int $min_number The minimum allowed number for the range, usually 0 or 1. | |
| 372 | + * @param int $max_number The maximum allowed number for the range, usually the number of rows or columns in the table. | |
| 373 | + * @return int[] The array of numbers in the range. | |
| 374 | + */ | |
| 375 | + public static function convert_range_to_array( string $value, int $min_number, int $max_number ): array { | |
| 376 | + $parts = explode( '-', $value ); | |
| 377 | + | |
| 378 | + // Ignore invalid ranges, e.g., "1-5-10" or "A-". | |
| 379 | + if ( count( $parts ) !== 2 || '' === $parts[0] || '' === $parts[1] ) { | |
| 380 | + return array(); | |
| 381 | + } | |
| 382 | + | |
| 383 | + $start = trim( $parts[0] ); | |
| 384 | + if ( ! is_numeric( $start ) ) { | |
| 385 | + $start = self::letter_to_number( $start ); | |
| 386 | + } | |
| 387 | + | |
| 388 | + $end = trim( $parts[1] ); | |
| 389 | + if ( ! is_numeric( $end ) ) { | |
| 390 | + $end = self::letter_to_number( $end ); | |
| 391 | + } | |
| 392 | + | |
| 393 | + // Catch completely out-of-bound ranges, taking into account that the order can be reversed. | |
| 394 | + if ( ( $start < $min_number && $end < $min_number ) || ( $start > $max_number && $end > $max_number ) ) { | |
| 395 | + return array(); | |
| 396 | + } | |
| 397 | + | |
| 398 | + // Clamp the start and end values to the min and max numbers. | |
| 399 | + $start = max( $min_number, min( (int) $start, $max_number ) ); | |
| 400 | + $end = max( $min_number, min( (int) $end, $max_number ) ); | |
| 401 | + | |
| 402 | + return range( $start, $end ); | |
| 403 | + } | |
| 404 | + | |
| 405 | + /** | |
| 406 | + * Converts a comma-separated list of row/column numbers/letters/ranges to a unique and sorted array of numbers. | |
| 407 | + * | |
| 408 | + * @since 3.4.0 | |
| 409 | + * | |
| 410 | + * @param string $item_list A comma-separated list of row/column numbers/letters/ranges. | |
| 411 | + * @param int $min_number The minimum allowed number for ranges, usually 0 or 1. | |
| 412 | + * @param int $max_number The maximum allowed number for ranges, usually the number of rows or columns in the table. | |
| 413 | + * @param array{ unique?: bool, sort?: bool, zero-based?: bool } $post_processing An array of post-processing operations to apply to the resulting array. | |
| 414 | + * @return int[] The array of numbers in the list, unique and sorted. | |
| 415 | + */ | |
| 416 | + public static function convert_row_column_list_to_array( string $item_list, int $min_number, int $max_number, array $post_processing = array() ): array { | |
| 417 | + $original_item_list = explode( ',', $item_list ); | |
| 418 | + | |
| 419 | + $item_list = array(); | |
| 420 | + foreach ( $original_item_list as $value ) { | |
| 421 | + if ( str_contains( $value, '-' ) ) { | |
| 422 | + // Convert ranges. | |
| 423 | + $range = self::convert_range_to_array( $value, $min_number, $max_number ); | |
| 424 | + $item_list = array_merge( $item_list, $range ); | |
| 425 | + } else { | |
| 426 | + // Handle single values. | |
| 427 | + $value = trim( $value ); | |
| 428 | + if ( ! is_numeric( $value ) ) { | |
| 429 | + $value = self::letter_to_number( $value ); | |
| 430 | + } | |
| 431 | + if ( $value >= $min_number && $value <= $max_number ) { | |
| 432 | + $item_list[] = (int) $value; | |
| 433 | + } | |
| 434 | + } | |
| 435 | + } | |
| 436 | + | |
| 437 | + // Maybe remove duplicate entries, sort the array, or convert to zero-based numbering. | |
| 438 | + $post_processing['unique'] ??= true; | |
| 439 | + if ( $post_processing['unique'] ) { | |
| 440 | + $item_list = array_unique( $item_list, SORT_NUMERIC ); | |
| 441 | + } | |
| 442 | + | |
| 443 | + $post_processing['sort'] ??= true; | |
| 444 | + if ( $post_processing['sort'] ) { | |
| 445 | + sort( $item_list, SORT_NUMERIC ); | |
| 446 | + } | |
| 447 | + | |
| 448 | + $post_processing['zero-based'] ??= false; | |
| 449 | + if ( $post_processing['zero-based'] ) { | |
| 450 | + foreach ( $item_list as &$value ) { | |
| 451 | + --$value; | |
| 452 | + } | |
| 453 | + unset( $value ); // Unset use-by-reference parameter of foreach loop. | |
| 454 | + } | |
| 455 | + | |
| 456 | + return $item_list; | |
| 457 | + } | |
| 458 | + | |
| 459 | + /** | |
| 364 | 460 | * Get a nice looking date and time string from the mySQL format of datetime strings for output. |
| 365 | 461 | * |
| 366 | 462 | * @since 1.0.0 |
| 367 | 463 | * |
| @@ -978,8 +1074,11 @@ | ||
| 978 | 1074 | * @param string $name Name of the JS file, without extension. |
| 979 | 1075 | * @param string[] $dependencies Optional. List of names of JS scripts that this script depends on, and which need to be included before this one. |
| 980 | 1076 | * @param array<string, mixed> $script_data Optional. JS data that is printed to the page before the script is included. The array key will be used as the name, the value will be JSON encoded. |
| 981 | 1077 | * @param string $path Optional. Path to the JS file. |
| 1078 | + * | |
| 1079 | + * @phpstan-param non-empty-string $name | |
| 1080 | + * @phpstan-param non-empty-string[] $dependencies | |
| 982 | 1081 | */ |
| 983 | 1082 | public static function enqueue_script( string $name, array $dependencies = array(), array $script_data = array(), string $path = 'admin/js/build/' ): void { |
| 984 | 1083 | $js_file = "{$path}{$name}.js"; |
| 985 | 1084 | $js_url = plugins_url( $js_file, TABLEPRESS__FILE__ ); |
| @@ -1004,8 +1103,10 @@ | ||
| 1004 | 1103 | * @since 2.0.0 |
| 1005 | 1104 | * |
| 1006 | 1105 | * @param string[] $dependencies List of the dependencies that the $name script relies on. |
| 1007 | 1106 | * @param string $name Name of the JS script, without extension. |
| 1107 | + * | |
| 1108 | + * @phpstan-param non-empty-string[] $dependencies | |
| 1008 | 1109 | */ |
| 1009 | 1110 | $dependencies = apply_filters( 'tablepress_admin_page_script_dependencies', $dependencies, $name ); |
| 1010 | 1111 | |
| 1011 | 1112 | $script_name = "tablepress-{$name}"; |