Make WordPress Core

Ticket #55635: 55635.0.3.diff

File 55635.0.3.diff, 23.1 KB (added by dmsnell, 4 years ago)

Updates from wordpress-develop: use of new function in Core code

  • src/wp-admin/includes/class-wp-debug-data.php

    diff --git a/src/wp-admin/includes/class-wp-debug-data.php b/src/wp-admin/includes/class-wp-debug-data.php
    index a921fc4dcb..6fb5cf1253 100644
    a b class WP_Debug_Data { 
    544544                        $post_max_size       = ini_get( 'post_max_size' );
    545545                        $upload_max_filesize = ini_get( 'upload_max_filesize' );
    546546                        $max_file_uploads    = ini_get( 'max_file_uploads' );
    547                         $effective           = min( wp_convert_hr_to_bytes( $post_max_size ), wp_convert_hr_to_bytes( $upload_max_filesize ) );
     547                        $effective           = wp_ini_lesser_quantity( $post_max_size, $upload_max_filesize );
    548548
    549549                        // Add info in Media section.
    550550                        $info['wp-media']['fields']['file_uploads']        = array(
  • src/wp-admin/includes/class-wp-site-health.php

    diff --git a/src/wp-admin/includes/class-wp-site-health.php b/src/wp-admin/includes/class-wp-site-health.php
    index 7c94e8be10..542fbc280f 100644
    a b class WP_Site_Health { 
    21632163                $post_max_size       = ini_get( 'post_max_size' );
    21642164                $upload_max_filesize = ini_get( 'upload_max_filesize' );
    21652165
    2166                 if ( wp_convert_hr_to_bytes( $post_max_size ) < wp_convert_hr_to_bytes( $upload_max_filesize ) ) {
     2166                if ( wp_ini_quantity_cmp( $post_max_size, $upload_max_filesize ) < 0 ) {
    21672167                        $result['label'] = sprintf(
    21682168                                /* translators: 1: post_max_size, 2: upload_max_filesize */
    21692169                                __( 'The "%1$s" value is smaller than "%2$s"' ),
    class WP_Site_Health { 
    21722172                        );
    21732173                        $result['status'] = 'recommended';
    21742174
    2175                         if ( 0 === wp_convert_hr_to_bytes( $post_max_size ) ) {
     2175                        if ( wp_ini_parse_quantity( $post_max_size ) <= 0 ) {
    21762176                                $result['description'] = sprintf(
    21772177                                        '<p>%s</p>',
    21782178                                        sprintf(
  • src/wp-includes/default-constants.php

    diff --git a/src/wp-includes/default-constants.php b/src/wp-includes/default-constants.php
    index 56754033a0..dff6db37aa 100644
    a b function wp_initial_constants() { 
    3939                define( 'WP_START_TIMESTAMP', microtime( true ) );
    4040        }
    4141
    42         $current_limit     = ini_get( 'memory_limit' );
    43         $current_limit_int = wp_convert_hr_to_bytes( $current_limit );
     42        $current_limit = ini_get( 'memory_limit' );
    4443
    4544        // Define memory limits.
    4645        if ( ! defined( 'WP_MEMORY_LIMIT' ) ) {
    function wp_initial_constants() { 
    5655        if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) ) {
    5756                if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) {
    5857                        define( 'WP_MAX_MEMORY_LIMIT', $current_limit );
    59                 } elseif ( -1 === $current_limit_int || $current_limit_int > 268435456 /* = 256M */ ) {
     58                } elseif ( wp_ini_quantity_cmp( $current_limit, '256M' ) > 0 ) {
    6059                        define( 'WP_MAX_MEMORY_LIMIT', $current_limit );
    6160                } else {
    6261                        define( 'WP_MAX_MEMORY_LIMIT', '256M' );
    function wp_initial_constants() { 
    6463        }
    6564
    6665        // Set memory limits.
    67         $wp_limit_int = wp_convert_hr_to_bytes( WP_MEMORY_LIMIT );
    68         if ( -1 !== $current_limit_int && ( -1 === $wp_limit_int || $wp_limit_int > $current_limit_int ) ) {
     66        if ( wp_ini_quantity_cmp( WP_MEMORY_LIMIT, $current_limit ) > 0 ) {
    6967                ini_set( 'memory_limit', WP_MEMORY_LIMIT );
    7068        }
    7169
  • src/wp-includes/functions.php

    diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php
    index 946853c361..587ec21ed9 100644
    a b function wp_raise_memory_limit( $context = 'admin' ) { 
    74547454                return false;
    74557455        }
    74567456
    7457         $current_limit     = ini_get( 'memory_limit' );
    7458         $current_limit_int = wp_convert_hr_to_bytes( $current_limit );
     7457        $current_limit = ini_get( 'memory_limit' );
    74597458
    7460         if ( -1 === $current_limit_int ) {
     7459        // If we're already set to an unlimited value there's no higher limit to set.
     7460        if ( wp_ini_parse_quantity( $current_limit ) <= 0 ) {
    74617461                return false;
    74627462        }
    74637463
    7464         $wp_max_limit     = WP_MAX_MEMORY_LIMIT;
    7465         $wp_max_limit_int = wp_convert_hr_to_bytes( $wp_max_limit );
    7466         $filtered_limit   = $wp_max_limit;
     7464        $wp_max_limit   = WP_MAX_MEMORY_LIMIT;
     7465        $filtered_limit = $wp_max_limit;
    74677466
    74687467        switch ( $context ) {
    74697468                case 'admin':
    function wp_raise_memory_limit( $context = 'admin' ) { 
    75237522                        break;
    75247523        }
    75257524
    7526         $filtered_limit_int = wp_convert_hr_to_bytes( $filtered_limit );
     7525        // Set the memory limit to the greatest of all the filtered value, the MAX limit, and the current limit.
     7526        $new_limit = wp_ini_greater_quantity( $current_limit, WP_MAX_MEMORY_LIMIT );
     7527        $new_limit = wp_ini_greater_quantity( $filtered_limit, $new_limit );
    75277528
    7528         if ( -1 === $filtered_limit_int || ( $filtered_limit_int > $wp_max_limit_int && $filtered_limit_int > $current_limit_int ) ) {
    7529                 if ( false !== ini_set( 'memory_limit', $filtered_limit ) ) {
    7530                         return $filtered_limit;
    7531                 } else {
    7532                         return false;
    7533                 }
    7534         } elseif ( -1 === $wp_max_limit_int || $wp_max_limit_int > $current_limit_int ) {
    7535                 if ( false !== ini_set( 'memory_limit', $wp_max_limit ) ) {
    7536                         return $wp_max_limit;
    7537                 } else {
    7538                         return false;
    7539                 }
     7529        // If we're already set at the greatest limit we don't need to change it.
     7530        if ( 0 === wp_ini_quantity_cmp( $new_limit, $current_limit ) ) {
     7531                return false;
    75407532        }
    75417533
    7542         return false;
     7534        // Otherwise attempt to set the new limit and return the new value if it succeeded.
     7535        return false !== ini_set( 'memory_limit', $new_limit )
     7536                ? $new_limit
     7537                : false;
    75437538}
    75447539
    75457540/**
  • src/wp-includes/load.php

    diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php
    index d4bc58b9c2..af2148b9f0 100644
    a b  
    55 * @package WordPress
    66 */
    77
     8require_once __DIR__ . '/php-compat.php';
     9
    810/**
    911 * Return the HTTP protocol sent by the server.
    1012 *
    function is_ssl() { 
    14651467 *
    14661468 * @since 2.3.0
    14671469 * @since 4.6.0 Moved from media.php to load.php.
     1470 * @deprecated 6.1.0 Use wp_ini_parse_quantity() or wp_hr_bytes() instead.
    14681471 *
    14691472 * @link https://www.php.net/manual/en/function.ini-get.php
    14701473 * @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
    function is_ssl() { 
    14731476 * @return int An integer byte value.
    14741477 */
    14751478function wp_convert_hr_to_bytes( $value ) {
     1479        _deprecated_function( __FUNCTION__, '6.1.0', 'wp_ini_parse_quantity' );
     1480        return wp_hr_bytes( $value );
     1481}
     1482
     1483/**
     1484 * Parses a "human-readable" byte value into an integer.
     1485 *
     1486 * @since 6.1.0
     1487 *
     1488 * @param string $value Human-readable description of a byte size
     1489 * @return int An integer byte value.
     1490 */
     1491function wp_hr_bytes( $value ) {
    14761492        $value = strtolower( trim( $value ) );
    14771493        $bytes = (int) $value;
    14781494
  • src/wp-includes/media.php

    diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php
    index caf8d247f5..51a6382f1e 100644
    a b function wp_expand_dimensions( $example_width, $example_height, $max_width, $max 
    37873787 * @return int Allowed upload size.
    37883788 */
    37893789function wp_max_upload_size() {
    3790         $u_bytes = wp_convert_hr_to_bytes( ini_get( 'upload_max_filesize' ) );
    3791         $p_bytes = wp_convert_hr_to_bytes( ini_get( 'post_max_size' ) );
     3790        $upload_max_filesize = ini_get( 'upload_max_filesize' );
     3791        $post_max_size       = ini_get( 'post_max_size' );
     3792        $max_upload          = wp_ini_lesser_quantity( $upload_max_filesize, $post_max_size );
    37923793
    37933794        /**
    37943795         * Filters the maximum upload size allowed in php.ini.
    function wp_max_upload_size() { 
    37993800         * @param int $u_bytes Maximum upload filesize in bytes.
    38003801         * @param int $p_bytes Maximum size of POST data in bytes.
    38013802         */
    3802         return apply_filters( 'upload_size_limit', min( $u_bytes, $p_bytes ), $u_bytes, $p_bytes );
     3803        return apply_filters(
     3804                'upload_size_limit',
     3805                wp_ini_parse_quantity( $max_upload ),
     3806                wp_ini_parse_quantity( $upload_max_filesize ),
     3807                wp_ini_parse_quantity( $post_max_size )
     3808        );
    38033809}
    38043810
    38053811/**
  • new file src/wp-includes/php-compat.php

    diff --git a/src/wp-includes/php-compat.php b/src/wp-includes/php-compat.php
    new file mode 100644
    index 0000000000..584bfa63a0
    - +  
     1<?php
     2
     3defined( 'IS_32_BIT_SYSTEM' ) || define( 'IS_32_BIT_SYSTEM', 2147483647 === PHP_INT_MAX );
     4defined( 'PHP_INT_MAX' ) || define( 'PHP_INT_MAX', IS_32_BIT_SYSTEM ? 2147483647 : 9223372036854775807 );
     5defined( 'PHP_INT_MIN' ) || define( 'PHP_INT_MIN', IS_32_BIT_SYSTEM ? -2147483648 : -9223372036854775808 );
     6
     7/*
     8 * Returns byte size represented in a numeric php.ini directive.
     9 *
     10 * Generally this can be used in combination with `ini_get( $option )`
     11 * for values that accept a numeric "byte" size, such as `post_max_size`.
     12 * It will return the value which PHP interprets from the "shorthand"
     13 * syntax, such as "128m" being 128 MiB and "128mb" being 128 B.
     14 *
     15 * Since PHP 8.2 this may return inaccurate results if passed the value
     16 * for the `memory_limit` INI directive as it uses the new unsigned
     17 * parser.
     18 *
     19 * @param false|int|string $value
     20 * @return int
     21 */
     22function wp_ini_parse_quantity( $value ) {
     23        // A missing value is an implicit lack of limit, thus we return `0`, meaning "no limit."
     24        if ( false === $value ) {
     25                return 0;
     26        }
     27
     28        /*
     29         * Directly return pre-parsed values so we can repeatedly call
     30         * this without tracking if we've already parsed a given value.
     31         */
     32        if ( is_int( $value ) ) {
     33                return $value;
     34        }
     35
     36        /*
     37         * Non-string inputs "fail" to no limit, because there's
     38         * no limit we could ascribe to this invalid value.
     39         */
     40        if ( ! is_string( $value ) ) {
     41                return 0;
     42        }
     43
     44        return ini_parse_quantity( $value );
     45}
     46
     47/**
     48 * Returns larger of two php.ini directive quantity values.
     49 *
     50 * Example:
     51 *     wp_ini_greater_quantity( '256m', -1 ) === -1
     52 *     wp_ini_greater_quantity( '64K', '64') === '64K'
     53 *     wp_ini_greater_quantity( 1000, 2000 ) === 2000
     54 *
     55 * @param int|string|false $a Quantity value.
     56 * @param int|string|false $b Quantity value.
     57 * @return int|string|false   Larger quantity value.
     58 */
     59function wp_ini_greater_quantity( $a, $b ) {
     60        return wp_ini_quantity_cmp( $a, $b ) >= 0 ? $a : $b;
     61}
     62
     63/**
     64 * Returns smaller of two php.ini directive quantity values.
     65 *
     66 * Example:
     67 *     wp_ini_lesser_quantity( '256m', -1 ) === '256m'
     68 *     wp_ini_lesser_quantity( '64K', '64') === '64'
     69 *     wp_ini_lesser_quantity( 1000, 2000 ) === 1000
     70 *
     71 * @param int|string|false $a Quantity value.
     72 * @param int|string|false $b Quantity value.
     73 * @return int|string|false   Smaller quantity value.
     74 */
     75function wp_ini_lesser_quantity( $a, $b ) {
     76        return wp_ini_quantity_cmp( $a, $b ) <= 0 ? $a : $b;
     77}
     78
     79/**
     80 * Comparator for php.ini quantity values, can be used
     81 * as the callback for functions such as `usort()`.
     82 *
     83 * Example:
     84 *     $a  <  $b => -1
     85 *     $a === $b =>  0
     86 *     $a  >  $b =>  1
     87 *
     88 * @param int|string|false $a Quantity being compared.
     89 * @param int|string|false $b Quantity against which $a is compared.
     90 * @return int
     91 */
     92function wp_ini_quantity_cmp( $a, $b ) {
     93        $a_scalar = wp_ini_parse_quantity( $a );
     94        $b_scalar = wp_ini_parse_quantity( $b );
     95
     96        if ( $a_scalar === $b_scalar ) {
     97                return 0;
     98        }
     99
     100        // No limit on $a means it's at least as large as any $b value.
     101        if ( $a_scalar <= 0 ) {
     102                return 1;
     103        }
     104
     105        // No limit on $b means it's at least as large as any $a value.
     106        if ( $b_scalar <= 0 ) {
     107                return -1;
     108        }
     109
     110        return $a_scalar > $b_scalar ? 1 : -1;
     111}
     112
     113// ini_parse_quantity added to PHP in PHP 8.2
     114if ( ! function_exists( 'ini_parse_quantity' ) ) :
     115        /**
     116         * Returns quantity represented by a php.ini directive's "byte size shorthand."
     117         *
     118         * php.ini directives may use a string representation of a number of bytes
     119         * or a "shorthand" byte size to reference larger values. Multiple numeric
     120         * php.ini directive use these shorthands even when they don't refer to bytes.
     121         *
     122         * Example:
     123         *
     124         *     ini_parse_quantity( "1m" ) == 1048576
     125         *     ini_parse_quantity( "2K" ) == 2048 // 2 * 1024
     126         *     ini_parse_quantity( "0.5g" ) == 0
     127         *     ini_parse_quantity( "14.6e-13g" ) == 15032385536 // 14 * 1024^3
     128         *     ini_parse_quantity( "-813k" ) == -832512; // -813 * 1024
     129         *     ini_parse_quantity( "boat" ) == 0;
     130         *
     131         *     // This gives an answer, but it's _wrong_ because
     132         *     // the underlying mechanism in PHP overflowed and
     133         *     // the real return value depends on whether PHP
     134         *     // was built with 64-bit support.
     135         *     ini_parse_quantity( "9223372036854775807g" ) == ??
     136         *
     137         * Notes:
     138         *  - Suffixes are specifically _the last character_ and case-insensitive.
     139         *  - Suffixes k/m/g intentionally report powers of 1024 to agree with PHP.
     140         *  - This function does not fail on invalid input; it returns `0` in such cses.
     141         *  - As noted in the PHP documentation, overflow behavior is unspecified and
     142         *    platform-dependant. Values that trigger overflow are likely wrong
     143         *  - In PHP 8.2+ this function may return an invalid count for shorthand values
     144         *    parsed with the new unsigned parser. Currently only affects "memory_limit"
     145         *    and only when the value overflows an unsigned integer on the platform.
     146         *
     147         * @since 6.1.
     148         *
     149         * @link https://www.php.net/manual/en/function.ini-get.php
     150         * @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
     151
     152         * @param string $value Numeric string value possibly in "shorthand notation."
     153         * @return int          Parsed numeric value represented by given string.
     154         */
     155        function ini_parse_quantity( $value ) {
     156                /**
     157                 * Number of bytes in input string; because we're only assessing 7-bit
     158                 * ASCII/Unicode characters we can safely count bytes vs. needing to
     159                 * worry about code units, code points, or grapheme clusters.
     160                 *
     161                 * @var int
     162                 */
     163                $strlen = strlen( $value );
     164
     165                /** @var int|float Numeric quantity represented by value string. */
     166                $scalar = 0;
     167
     168                /** @var int Sign of numeric quantity, either positive (1) or negative (-1). */
     169                $sign = 1;
     170
     171                /**
     172                 * Numeric base of digits determined by string prefix (e.g. "0x" or "0").
     173                 * Must be 8 for octal, 10 for decimal, or 16 for hexadecimal.
     174                 *
     175                 * @var int
     176                 */
     177                $base = 10;
     178
     179                /** @var int Index into input string as we walk through it and analyze each character. */
     180                $i = 0;
     181
     182                /*
     183                 * Trim leading whitespace.
     184                 *
     185                 * We could also do this with `ltrim()` but that adds a needless
     186                 * string copy and makes it appear like we could add `+` to the
     187                 * list of values to trim, which we cannot, because that
     188                 * results in the wrong parse for strings with multiple
     189                 * `+` or `-` characters in a row.
     190                 */
     191                for ( ; $i < $strlen; $i++ ) {
     192                        $c = $value[ $i ];
     193
     194                        if ( ' ' === $c || "\t" === $c || "\r" === $c || "\v" === $c || "\f" === $c ) {
     195                                continue;
     196                        }
     197
     198                        break;
     199                }
     200
     201                // Handle optional sign indicator.
     202                switch ( $value[ $i ] ) {
     203                        case '+':
     204                                $i++;
     205                                break;
     206
     207                        case '-':
     208                                $sign = -1;
     209                                $i++;
     210                                break;
     211                }
     212
     213                // Determine base for digit conversion, if not decimal.
     214                $base_a = $i < $strlen ? $value[ $i ] : '';
     215                $base_b = $i + 1 < $strlen ? $value[ $i + 1 ] : '';
     216
     217                if ( '0' === $base_a && ( 'x' === $base_b || 'X' === $base_b ) ) {
     218                        $base = 16;
     219                        $i += 2;
     220                } else if ( '0' === $base_a && ctype_digit( $base_b ) ) {
     221                        $base = 8;
     222                        $i += 1;
     223                }
     224
     225                // Trim leading zeros.
     226                for ( ; $i < $strlen; $i++ ) {
     227                        if ( '0' !== $value[ $i ] ) {
     228                                break;
     229                        }
     230                }
     231
     232                /**
     233                 * Numeric values for scanned digits.
     234                 *
     235                 * These are used to determine the decimal value the digit
     236                 * represents and whether it's an allowed character in
     237                 * the given base. It's allowed if its value is less
     238                 * than the base: e.g. '7' is allowed in octal (base 8)
     239                 * but '8' and '9' aren't because they are greater than 8.
     240                 *
     241                 * @var array
     242                 */
     243                $digits = array(
     244                        '0' => 0,
     245                        '1' => 1,
     246                        '2' => 2,
     247                        '3' => 3,
     248                        '4' => 4,
     249                        '5' => 5,
     250                        '6' => 6,
     251                        '7' => 7,
     252                        '8' => 8,
     253                        '9' => 9,
     254                        'A' => 10,
     255                        'a' => 10,
     256                        'B' => 11,
     257                        'b' => 11,
     258                        'C' => 12,
     259                        'c' => 12,
     260                        'D' => 13,
     261                        'd' => 13,
     262                        'E' => 14,
     263                        'e' => 14,
     264                        'F' => 15,
     265                        'f' => 15,
     266                );
     267
     268                // Build the scalar value by consuming the next sequence of contiguous digits.
     269                for ( ; $i < $strlen; $i++ ) {
     270                        $c = $value[ $i ];
     271
     272                        /*
     273                         * Only digits recognized in this base system can be used.
     274                         * Once we find an unrecognized digit we abort and move
     275                         * on to the next step in parsing the size suffix.
     276                         */
     277                        if ( ! isset( $digits[ $c ] ) || $digits[ $c ] >= $base ) {
     278                                break;
     279                        }
     280
     281                        /*
     282                         * This is the step that computes our integer as we see new digits.
     283                         *
     284                         * Example:
     285                         *      4   = (0 * 10) + 4
     286                         *      45  = ((0 * 10 + 4) * 10) + 5
     287                         *      458 = ((0 * 10 + 4) * 10 + 5) * 10 + 8
     288                         */
     289                        $scalar = $scalar * $base + $digits[ $c ];
     290
     291                        // Stop processing if we're already at the maximum magnitude for the sign.
     292                        if (
     293                                ( $sign > 0 && $scalar > PHP_INT_MAX ) ||
     294                                ( $sign < 0 && $scalar > -PHP_INT_MIN )
     295                        ) {
     296                                break;
     297                        }
     298                }
     299
     300                // Clamp the parsed digits to an integer value as PHP does internally.
     301                if ( $sign > 0 && $scalar >= PHP_INT_MAX ) {
     302                        $scalar = PHP_INT_MAX;
     303                } else if ( $sign < 0 && $scalar >= -PHP_INT_MIN ) {
     304                        $scalar = PHP_INT_MIN;
     305                } else if ( $sign < 0 ) {
     306                        $scalar = -$scalar;
     307                }
     308
     309                /*
     310                 * Do not use WP constants here (GB_IN_BYTES, MB_IN_BYTES, KB_IN_BYTES)
     311                 * since they are re-definable; PHP shorthand values are hard-coded
     312                 * in PHP itself and stay the same regardless of these constants.
     313                 *
     314                 * Note that we can overflow here, as happens in PHP itself.
     315                 * Overflow results will likely not match PHP's value, but
     316                 * will likely break in most cases anyway and so leaving
     317                 * this loose is the best we can do until we can read these
     318                 * values directly from PHP.
     319                 */
     320                switch ( $value[ $strlen - 1 ] ) {
     321                        case 'g':
     322                        case 'G':
     323                                $scalar *= 1073741824; // 1024^3
     324                                break;
     325
     326                        case 'm':
     327                        case 'M':
     328                                $scalar *= 1048576; // 1024^2
     329                                break;
     330
     331                        case 'k':
     332                        case 'K':
     333                                $scalar *= 1024;
     334                                break;
     335                }
     336
     337                return (int) $scalar;
     338        }
     339
     340endif;
  • tests/phpunit/tests/load/wpConvertHrToBytes.php

    diff --git a/tests/phpunit/tests/load/wpConvertHrToBytes.php b/tests/phpunit/tests/load/wpConvertHrToBytes.php
    index 66f4d4329b..cf08e58761 100644
    a b class Tests_Load_wpConvertHrToBytes extends WP_UnitTestCase { 
    4444                        array( '128m', 134217728 ),
    4545                        array( '256M', 268435456 ),
    4646                        array( '1g', 1073741824 ),
    47                         array( '128m ', 134217728 ), // Leading/trailing whitespace gets trimmed.
     47
     48                        /**
     49                         * Leading/trailing whitespace gets trimmed.
     50                         * Note that this is not the value that PHP uses internally.
     51                         * PHP interprets the value as 128, not 128 MiB.
     52                         *
     53                         * @see wp_ini_parse_quantity()
     54                         */
     55                        array( '128m ', 134217728 ),
    4856                        array( '1024', 1024 ), // No letter will be interpreted as integer value.
    4957
    5058                        // Edge cases.
  • new file tests/phpunit/tests/php-compat/ini_parse_quantity.php

    diff --git a/tests/phpunit/tests/php-compat/ini_parse_quantity.php b/tests/phpunit/tests/php-compat/ini_parse_quantity.php
    new file mode 100644
    index 0000000000..5f6233615c
    - +  
     1<?php
     2
     3/**
     4 * Tests for PHP compatability functions.
     5 *
     6 * @group php-compat.php
     7 * @covers ::wp_ini_parse_quantity
     8 */
     9class Tests_PHP_Compat_wpIniParseQuantity extends WP_UnitTestCase {
     10        public function test_unset_limit_is_no_limit() {
     11                $this->assertEquals( 0, wp_ini_parse_quantity( false ) );
     12        }
     13
     14        public function test_absent_limit_is_no_limit() {
     15                $this->assertEquals( 0, wp_ini_parse_quantity( '' ) );
     16        }
     17
     18        public function test_unlimited_is_unlimited() {
     19                $this->assertEquals( -1, wp_ini_parse_quantity( '-1' ) );
     20        }
     21
     22        public function test_unlimited_is_same_as_missing_limit() {
     23                $this->assertEqual( '', wp_ini_greater_quantity( '', '-1' ) );
     24                $this->assertEqual( '-1', wp_ini_greater_quantity( '-1', '' ) );
     25                $this->assertEqual( '', wp_ini_lesser_quantity( '', '-1' ) );
     26                $this->assertEqual( '-1', wp_ini_lesser_quantity( '-1', '' ) );
     27        }
     28
     29        public function test_unlimited_is_greater_than_hard_limit() {
     30                $this->assertEqual( 1, wp_ini_quantity_cmp( -1, 1348 ) );
     31                $this->assertEqual( 1, wp_ini_quantity_cmp( -1, '1348g' ) );
     32                $this->assertEqual( 1, wp_ini_quantity_cmp( '', 1348 ) );
     33                $this->assertEqual( 1, wp_ini_quantity_cmp( '', '1348g' ) );
     34                $this->assertEqual( 1, wp_ini_quantity_cmp( 0, 1348 ) );
     35                $this->assertEqual( 1, wp_ini_quantity_cmp( 0, '1348g' ) );
     36                $this->assertEqual( 1, wp_ini_quantity_cmp( false, 1348 ) );
     37                $this->assertEqual( 1, wp_ini_quantity_cmp( false, '1348g' ) );
     38        }
     39
     40        public function test_invalid_data_is_no_limit() {
     41                $this->assertEquals( 0, wp_ini_parse_quantity( true ) );
     42                $this->assertEquals( 0, wp_ini_parse_quantity( false ) );
     43                $this->assertEquals( 0, wp_ini_parse_quantity( array( 1, 2, 3 ) ) );
     44                $this->assertEquals( 0, wp_ini_parse_quantity( new stdClass ) );
     45        }
     46
     47        public function test_returns_already_parsed_values() {
     48                $this->assertEquals( 15, wp_ini_parse_quantity( 15 ) );
     49                $this->assertEquals( -1543, wp_ini_parse_quantity( -1543 ) );
     50        }
     51
     52        public function test_clamped_to_max_int_before_suffix() {
     53                if ( IS_32_BIT_SYSTEM ) {
     54                        $this->assertEquals( PHP_INT_MAX, wp_ini_parse_quantity( '2147483648' ) );
     55                        $this->assertEquals( PHP_INT_MIN, wp_ini_parse_quantity( '-2147483649' ) );
     56                } else {
     57                        $this->assertEquals( PHP_INT_MAX, wp_ini_parse_quantity( '9223372036854775808' ) );
     58                        $this->assertEquals( PHP_INT_MIN, wp_ini_parse_quantity( '-9223372036854775809' ) );
     59                }
     60        }
     61
     62        public function test_suffix_math_may_overflow() {
     63                if ( IS_32_BIT_SYSTEM ) {
     64                        $this->assertNotEquals( PHP_INT_MAX, wp_ini_parse_quantity( '2147483648g' ) );
     65                        $this->assertNotEquals( PHP_INT_MIN, wp_ini_parse_quantity( '-2147483648g' ) );
     66                } else {
     67                        $this->assertNotEquals( PHP_INT_MAX, wp_ini_parse_quantity( '9223372036854775807g' ) );
     68                        $this->assertNotEquals( PHP_INT_MIN, wp_ini_parse_quantity( '-9223372036854775807g' ) );
     69                }
     70        }
     71
     72        /**
     73         * Tests converting numeric php.ini directive strings into their scalar equivalents.
     74         *
     75         * @ticket 55635
     76         *
     77         * @dataProvider data_php_numeric_strings
     78         *
     79         * @param $value
     80         * @param $expected
     81         */
     82        public function test_parse_matches_php_internal_value( $value, $expected ) {
     83                $this->assertEquals( $expected, wp_ini_parse_quantity( $value ) );
     84        }
     85
     86        public function data_php_numeric_strings() {
     87                return array(
     88                        // Decimal integer input.
     89                        array( '0', 0 ),
     90                        array( '100', 100 ),
     91                        array( '-14', -14 ),
     92
     93                        // Octal integer input.
     94                        array( '0100', 64 ),
     95                        array( '-0654', -428 ),
     96
     97                        // Hex input.
     98                        array( '0x14', 20 ),
     99                        array( '0X14', 20 ),
     100                        array( '-0xAA', -170 ),
     101
     102                        // Size suffixes.
     103                        array( '1g', 1073741824 ),
     104                        array( '1gb', 0 ),
     105                        array( '32k', 32768 ),
     106                        array( '64K', 65536 ),
     107                        array( '07k', 7168 ),
     108                        array( '-0xF3d7m', -65455259648 ),
     109                        array( '128m', 134217728 ),
     110                        array( '128m ', 128 ),
     111                        array( '128mk', 131072 ),
     112                        array( '128km', 134217728 ),
     113                        array( '1.28 kmg', 1073741824 ),
     114                        array( '256M', 268435456 ),
     115
     116                        // Leading characters.
     117                        array( '    68', 68 ),
     118                        array( '+1', 1 ),
     119                        array( '    -0xdeadbeef', -3735928559 ),
     120                        array( ' 00000077', 63 ),
     121
     122                        // Things that don't look valid but are still possible.
     123                        array( '', 0 ),
     124                        array( '3km', 3145728 ),
     125                        array( '1mg', 1073741824 ),
     126                        array( 'boat', 0 ),
     127                        array( '-14chairsk', -14336 ),
     128                        array( '0xt', 0 ),
     129                        array( '++3', 0 ),
     130                        array( '0x5ome 🅰🅱🅲 attack', 5120 ),
     131                );
     132        }
     133}