ソースを参照

Add types and remove deprecated code.

* Remove PHP5 compatibility shims.
* Add and fix type issues.
Mark Story 7 年 前
コミット
1c31092a56

+ 3 - 3
src/Utility/Hash.php

@@ -59,7 +59,7 @@ class Hash
         }
 
         if (is_string($path) || is_numeric($path)) {
-            $parts = explode('.', $path);
+            $parts = explode('.', (string)$path);
         } else {
             if (!is_array($path)) {
                 throw new InvalidArgumentException(sprintf(
@@ -259,7 +259,7 @@ class Hash
                 return false;
             }
 
-            $prop = null;
+            $prop = '';
             if (isset($data[$attr])) {
                 $prop = $data[$attr];
             }
@@ -713,7 +713,7 @@ class Hash
     {
         $result = [];
         foreach ($data as $flat => $value) {
-            $keys = explode($separator, $flat);
+            $keys = explode($separator, (string)$flat);
             $keys = array_reverse($keys);
             $child = [
                 $keys[0] => $value

+ 13 - 35
src/Utility/Security.php

@@ -59,7 +59,7 @@ class Security
      * @return string Hash
      * @link https://book.cakephp.org/3.0/en/core-libraries/security.html#hashing-data
      */
-    public static function hash($string, $algorithm = null, $salt = false)
+    public static function hash(string $string, ?string $algorithm = null, $salt = false): string
     {
         if (empty($algorithm)) {
             $algorithm = static::$hashType;
@@ -93,7 +93,7 @@ class Security
      * @return void
      * @see \Cake\Utility\Security::hash()
      */
-    public static function setHash($hash)
+    public static function setHash(string $hash): void
     {
         static::$hashType = $hash;
     }
@@ -107,30 +107,9 @@ class Security
      * @param int $length The number of bytes you want.
      * @return string Random bytes in binary.
      */
-    public static function randomBytes($length)
+    public static function randomBytes(int $length): string
     {
-        if (function_exists('random_bytes')) {
-            return random_bytes($length);
-        }
-        if (!function_exists('openssl_random_pseudo_bytes')) {
-            throw new RuntimeException(
-                'You do not have a safe source of random data available. ' .
-                'Install either the openssl extension, or paragonie/random_compat. ' .
-                'Or use Security::insecureRandomBytes() alternatively.'
-            );
-        }
-
-        $bytes = openssl_random_pseudo_bytes($length, $strongSource);
-        if (!$strongSource) {
-            trigger_error(
-                'openssl was unable to use a strong source of entropy. ' .
-                'Consider updating your system libraries, or ensuring ' .
-                'you have more available entropy.',
-                E_USER_WARNING
-            );
-        }
-
-        return $bytes;
+        return random_bytes($length);
     }
 
     /**
@@ -138,12 +117,11 @@ class Security
      *
      * @param int $length String length. Default 64.
      * @return string
-     * @since 3.6.0
      */
-    public static function randomString($length = 64)
+    public static function randomString(int $length = 64): string
     {
         return substr(
-            bin2hex(Security::randomBytes(ceil($length / 2))),
+            bin2hex(Security::randomBytes((int)ceil($length / 2))),
             0,
             $length
         );
@@ -156,14 +134,14 @@ class Security
      * @return string Random bytes in binary.
      * @see \Cake\Utility\Security::randomBytes()
      */
-    public static function insecureRandomBytes($length)
+    public static function insecureRandomBytes(int $length): string
     {
         $length *= 2;
 
         $bytes = '';
         $byteLength = 0;
         while ($byteLength < $length) {
-            $bytes .= static::hash(Text::uuid() . uniqid(mt_rand(), true), 'sha512', true);
+            $bytes .= static::hash(Text::uuid() . uniqid((string)mt_rand(), true), 'sha512', true);
             $byteLength = strlen($bytes);
         }
         $bytes = substr($bytes, 0, $length);
@@ -212,7 +190,7 @@ class Security
      * @return string Encrypted data.
      * @throws \InvalidArgumentException On invalid data or key.
      */
-    public static function encrypt($plain, $key, $hmacSalt = null)
+    public static function encrypt(string $plain, string $key, ?string $hmacSalt = null): string
     {
         self::_checkKey($key, 'encrypt()');
 
@@ -237,7 +215,7 @@ class Security
      * @return void
      * @throws \InvalidArgumentException When key length is not 256 bit/32 bytes
      */
-    protected static function _checkKey($key, $method)
+    protected static function _checkKey(string $key, string $method): void
     {
         if (mb_strlen($key, '8bit') < 32) {
             throw new InvalidArgumentException(
@@ -252,10 +230,10 @@ class Security
      * @param string $cipher The ciphertext to decrypt.
      * @param string $key The 256 bit/32 byte key to use as a cipher key.
      * @param string|null $hmacSalt The salt to use for the HMAC process. Leave null to use Security.salt.
-     * @return string|bool Decrypted data. Any trailing null bytes will be removed.
+     * @return string|null Decrypted data. Any trailing null bytes will be removed.
      * @throws \InvalidArgumentException On invalid data or key.
      */
-    public static function decrypt($cipher, $key, $hmacSalt = null)
+    public static function decrypt(string $cipher, string $key, ?string $hmacSalt = null): ?string
     {
         self::_checkKey($key, 'decrypt()');
         if (empty($cipher)) {
@@ -275,7 +253,7 @@ class Security
 
         $compareHmac = hash_hmac('sha256', $cipher, $key);
         if (!static::constantEquals($hmac, $compareHmac)) {
-            return false;
+            return null;
         }
 
         $crypto = static::engine();

+ 37 - 41
src/Utility/Text.php

@@ -60,27 +60,25 @@ class Text
      * @return string RFC 4122 UUID
      * @copyright Matt Farina MIT License https://github.com/lootils/uuid/blob/master/LICENSE
      */
-    public static function uuid()
+    public static function uuid(): string
     {
-        $random = function_exists('random_int') ? 'random_int' : 'mt_rand';
-
         return sprintf(
             '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
             // 32 bits for "time_low"
-            $random(0, 65535),
-            $random(0, 65535),
+            random_int(0, 65535),
+            random_int(0, 65535),
             // 16 bits for "time_mid"
-            $random(0, 65535),
+            random_int(0, 65535),
             // 12 bits before the 0100 of (version) 4 for "time_hi_and_version"
-            $random(0, 4095) | 0x4000,
+            random_int(0, 4095) | 0x4000,
             // 16 bits, 8 bits for "clk_seq_hi_res",
             // 8 bits for "clk_seq_low",
             // two most significant bits holds zero and one for variant DCE1.1
-            $random(0, 0x3fff) | 0x8000,
+            random_int(0, 0x3fff) | 0x8000,
             // 48 bits for "node"
-            $random(0, 65535),
-            $random(0, 65535),
-            $random(0, 65535)
+            random_int(0, 65535),
+            random_int(0, 65535),
+            random_int(0, 65535)
         );
     }
 
@@ -94,7 +92,7 @@ class Text
      * @param string $rightBound The right boundary to ignore separators in.
      * @return array|string Array of tokens in $data or original input if empty.
      */
-    public static function tokenize($data, $separator = ',', $leftBound = '(', $rightBound = ')')
+    public static function tokenize(string $data, string $separator = ',', string $leftBound = '(', string $rightBound = ')')
     {
         if (empty($data)) {
             return [];
@@ -188,14 +186,14 @@ class Text
      * @param array $options An array of options, see description above
      * @return string
      */
-    public static function insert($str, $data, array $options = [])
+    public static function insert(string $str, array $data, array $options = []): string
     {
         $defaults = [
-            'before' => ':', 'after' => null, 'escape' => '\\', 'format' => null, 'clean' => false
+            'before' => ':', 'after' => '', 'escape' => '\\', 'format' => null, 'clean' => false
         ];
         $options += $defaults;
         $format = $options['format'];
-        $data = (array)$data;
+        $data = $data;
         if (empty($data)) {
             return $options['clean'] ? static::cleanInsert($str, $options) : $str;
         }
@@ -253,7 +251,7 @@ class Text
      * @return string
      * @see \Cake\Utility\Text::insert()
      */
-    public static function cleanInsert($str, array $options)
+    public static function cleanInsert(string $str, array $options): string
     {
         $clean = $options['clean'];
         if (!$clean) {
@@ -323,7 +321,7 @@ class Text
      * @param array|int $options Array of options to use, or an integer to wrap the text to.
      * @return string Formatted text.
      */
-    public static function wrap($text, $options = [])
+    public static function wrap(string $text, $options = []): string
     {
         if (is_numeric($options)) {
             $options = ['width' => $options];
@@ -360,7 +358,7 @@ class Text
      * @param array|int $options Array of options to use, or an integer to wrap the text to.
      * @return string Formatted text.
      */
-    public static function wrapBlock($text, $options = [])
+    public static function wrapBlock(string $text, $options = []): string
     {
         if (is_numeric($options)) {
             $options = ['width' => $options];
@@ -409,7 +407,7 @@ class Text
      * @param bool $cut If the cut is set to true, the string is always wrapped at the specified width.
      * @return string Formatted text.
      */
-    public static function wordWrap($text, $width = 72, $break = "\n", $cut = false)
+    public static function wordWrap(string $text, int $width = 72, string $break = "\n", bool $cut = false): string
     {
         $paragraphs = explode($break, $text);
         foreach ($paragraphs as &$paragraph) {
@@ -428,7 +426,7 @@ class Text
      * @param bool $cut If the cut is set to true, the string is always wrapped at the specified width.
      * @return string Formatted text.
      */
-    protected static function _wordWrap($text, $width = 72, $break = "\n", $cut = false)
+    protected static function _wordWrap(string $text, int $width = 72, string $break = "\n", bool $cut = false): string
     {
         if ($cut) {
             $parts = [];
@@ -487,7 +485,7 @@ class Text
      * @return string The highlighted text
      * @link https://book.cakephp.org/3.0/en/core-libraries/text.html#highlighting-substrings
      */
-    public static function highlight($text, $phrase, array $options = [])
+    public static function highlight(string $text, $phrase, array $options = []): string
     {
         if (empty($phrase)) {
             return $text;
@@ -544,7 +542,7 @@ class Text
      * @param array $options An array of options.
      * @return string Trimmed string.
      */
-    public static function tail($text, $length = 100, array $options = [])
+    public static function tail(string $text, int $length = 100, array $options = []): string
     {
         $default = [
             'ellipsis' => '...', 'exact' => true
@@ -585,7 +583,7 @@ class Text
      * @return string Trimmed string.
      * @link https://book.cakephp.org/3.0/en/core-libraries/text.html#truncating-text
      */
-    public static function truncate($text, $length = 100, array $options = [])
+    public static function truncate(string $text, int $length = 100, array $options = []): string
     {
         $default = [
             'ellipsis' => '...', 'exact' => true, 'html' => false, 'trimWidth' => false,
@@ -683,7 +681,7 @@ class Text
      * @return string Trimmed string.
      * @see \Cake\Utility\Text::truncate()
      */
-    public static function truncateByWidth($text, $length = 100, array $options = [])
+    public static function truncateByWidth(string $text, int $length = 100, array $options = []): string
     {
         return static::truncate($text, $length, ['trimWidth' => true] + $options);
     }
@@ -700,7 +698,7 @@ class Text
      * @param array $options An array of options.
      * @return int
      */
-    protected static function _strlen($text, array $options)
+    protected static function _strlen(string $text, array $options): int
     {
         if (empty($options['trimWidth'])) {
             $strlen = 'mb_strlen';
@@ -736,11 +734,11 @@ class Text
      *
      * @param string $text The input string.
      * @param int $start The position to begin extracting.
-     * @param int $length The desired length.
+     * @param int|null $length The desired length.
      * @param array $options An array of options.
      * @return string
      */
-    protected static function _substr($text, $start, $length, array $options)
+    protected static function _substr(string $text, int $start, ?int $length, array $options): string
     {
         if (empty($options['trimWidth'])) {
             $substr = 'mb_substr';
@@ -826,12 +824,12 @@ class Text
      * @param string $text The input text
      * @return string
      */
-    protected static function _removeLastWord($text)
+    protected static function _removeLastWord(string $text): string
     {
         $spacepos = mb_strrpos($text, ' ');
 
         if ($spacepos !== false) {
-            $lastWord = mb_strrpos($text, $spacepos);
+            $lastWord = mb_substr($text, $spacepos);
 
             // Some languages are written without word separation.
             // We recognize a string as a word if it doesn't contain any full-width characters.
@@ -856,7 +854,7 @@ class Text
      * @return string Modified string
      * @link https://book.cakephp.org/3.0/en/core-libraries/text.html#extracting-an-excerpt
      */
-    public static function excerpt($text, $phrase, $radius = 100, $ellipsis = '...')
+    public static function excerpt(string $text, string $phrase, int $radius = 100, string $ellipsis = '...'): string
     {
         if (empty($text) || empty($phrase)) {
             return static::truncate($text, $radius * 2, ['ellipsis' => $ellipsis]);
@@ -899,16 +897,16 @@ class Text
      * @return string The glued together string.
      * @link https://book.cakephp.org/3.0/en/core-libraries/text.html#converting-an-array-to-sentence-form
      */
-    public static function toList(array $list, $and = null, $separator = ', ')
+    public static function toList(array $list, ?string $and = null, string $separator = ', '): string
     {
         if ($and === null) {
             $and = __d('cake', 'and');
         }
         if (count($list) > 1) {
-            return implode($separator, array_slice($list, null, -1)) . ' ' . $and . ' ' . array_pop($list);
+            return implode($separator, array_slice($list, 0, -1)) . ' ' . $and . ' ' . array_pop($list);
         }
 
-        return array_pop($list);
+        return (string)array_pop($list);
     }
 
     /**
@@ -917,7 +915,7 @@ class Text
      * @param string $string value to test
      * @return bool
      */
-    public static function isMultibyte($string)
+    public static function isMultibyte(string $string): bool
     {
         $length = strlen($string);
 
@@ -938,7 +936,7 @@ class Text
      * @param string $string String to convert.
      * @return array
      */
-    public static function utf8($string)
+    public static function utf8(string $string): array
     {
         $map = [];
 
@@ -979,7 +977,7 @@ class Text
      * @param array $array Array
      * @return string
      */
-    public static function ascii(array $array)
+    public static function ascii(array $array): string
     {
         $ascii = '';
 
@@ -1008,7 +1006,7 @@ class Text
      * @throws \InvalidArgumentException On invalid Unit type.
      * @link https://book.cakephp.org/3.0/en/core-libraries/text.html#Cake\Utility\Text::parseFileSize
      */
-    public static function parseFileSize($size, $default = false)
+    public static function parseFileSize(string $size, $default = false)
     {
         if (ctype_digit($size)) {
             return (int)$size;
@@ -1044,7 +1042,6 @@ class Text
      *
      * @return \Transliterator|null Either a Transliterator instance, or `null`
      *   in case no transliterator has been set yet.
-     * @since 3.7.0
      */
     public static function getTransliterator()
     {
@@ -1056,7 +1053,6 @@ class Text
      *
      * @param \Transliterator $transliterator A `Transliterator` instance.
      * @return void
-     * @since 3.7.0
      */
     public static function setTransliterator(\Transliterator $transliterator)
     {
@@ -1096,7 +1092,7 @@ class Text
      * @return string
      * @see https://secure.php.net/manual/en/transliterator.transliterate.php
      */
-    public static function transliterate($string, $transliterator = null)
+    public static function transliterate(string $string, $transliterator = null): string
     {
         if (!$transliterator) {
             $transliterator = static::$_defaultTransliterator ?: static::$_defaultTransliteratorId;
@@ -1126,7 +1122,7 @@ class Text
      * @see setTransliterator()
      * @see setTransliteratorId()
      */
-    public static function slug($string, $options = [])
+    public static function slug(string $string, $options = []): string
     {
         if (is_string($options)) {
             $options = ['replacement' => $options];

+ 8 - 6
src/Utility/Xml.php

@@ -139,7 +139,7 @@ class Xml
      * @return \SimpleXMLElement|\DOMDocument
      * @throws \Cake\Utility\Exception\XmlException
      */
-    protected static function _loadXml($input, $options)
+    protected static function _loadXml(string $input, array $options)
     {
         $hasDisable = function_exists('libxml_disable_entity_loader');
         $internalErrors = libxml_use_internal_errors(true);
@@ -178,7 +178,7 @@ class Xml
      * @return \SimpleXMLElement|\DOMDocument
      * @throws \Cake\Utility\Exception\XmlException
      */
-    public static function loadHtml($input, $options = [])
+    public static function loadHtml(string $input, array $options = [])
     {
         $defaults = [
             'return' => 'simplexml',
@@ -223,8 +223,10 @@ class Xml
      * - `format` If create childs ('tags') or attributes ('attributes').
      * - `pretty` Returns formatted Xml when set to `true`. Defaults to `false`
      * - `version` Version of XML document. Default is 1.0.
-     * - `encoding` Encoding of XML document. If null remove from XML header. Default is the some of application.
-     * - `return` If return object of SimpleXMLElement ('simplexml') or DOMDocument ('domdocument'). Default is SimpleXMLElement.
+     * - `encoding` Encoding of XML document. If null remove from XML header.
+     *    Defaults to the application's encoding
+     * - `return` If return object of SimpleXMLElement ('simplexml')
+     *   or DOMDocument ('domdocument'). Default is SimpleXMLElement.
      *
      * Using the following data:
      *
@@ -368,7 +370,7 @@ class Xml
      * @param array $data Array with information to create childs
      * @return void
      */
-    protected static function _createChild($data)
+    protected static function _createChild(array $data)
     {
         $data += [
             'dom' => null,
@@ -420,7 +422,7 @@ class Xml
      * @return array Array representation of the XML structure.
      * @throws \Cake\Utility\Exception\XmlException
      */
-    public static function toArray($obj)
+    public static function toArray($obj): array
     {
         if ($obj instanceof DOMNode) {
             $obj = simplexml_import_dom($obj);

+ 3 - 12
tests/TestCase/Utility/SecurityTest.php

@@ -108,7 +108,7 @@ class SecurityTest extends TestCase
         $result = Security::encrypt($txt, $key);
 
         $key = 'Not the same key. This one will fail';
-        $this->assertFalse(Security::decrypt($txt, $key), 'Modified key will fail.');
+        $this->assertNull(Security::decrypt($txt, $key), 'Modified key will fail.');
     }
 
     /**
@@ -125,7 +125,7 @@ class SecurityTest extends TestCase
 
         // Change one of the bytes in the hmac.
         $result[10] = 'x';
-        $this->assertFalse(Security::decrypt($result, $key, $salt), 'Modified hmac causes failure.');
+        $this->assertNull(Security::decrypt($result, $key, $salt), 'Modified hmac causes failure.');
     }
 
     /**
@@ -141,7 +141,7 @@ class SecurityTest extends TestCase
         $result = Security::encrypt($txt, $key, $salt);
 
         $salt = 'humpty dumpty had a great fall.';
-        $this->assertFalse(Security::decrypt($result, $key, $salt), 'Modified salt causes failure.');
+        $this->assertNull(Security::decrypt($result, $key, $salt), 'Modified salt causes failure.');
     }
 
     /**
@@ -170,15 +170,6 @@ class SecurityTest extends TestCase
         $result = Security::encrypt('', $key);
         $this->assertSame('', Security::decrypt($result, $key));
 
-        $result = Security::encrypt(false, $key);
-        $this->assertSame('', Security::decrypt($result, $key));
-
-        $result = Security::encrypt(null, $key);
-        $this->assertSame('', Security::decrypt($result, $key));
-
-        $result = Security::encrypt(0, $key);
-        $this->assertSame('0', Security::decrypt($result, $key));
-
         $result = Security::encrypt('0', $key);
         $this->assertSame('0', Security::decrypt($result, $key));
     }

+ 3 - 3
tests/TestCase/Utility/TextTest.php

@@ -176,7 +176,7 @@ class TextTest extends TestCase
         $result = Text::insert($string, ['src' => 'foo', 'extra' => 'bar'], ['clean' => 'html']);
         $this->assertEquals($expected, $result);
 
-        $result = Text::insert('this is a ? string', 'test');
+        $result = Text::insert('this is a ? string', ['test']);
         $expected = 'this is a test string';
         $this->assertEquals($expected, $result);
 
@@ -870,11 +870,11 @@ HTML;
         $this->assertEquals($expected, $result);
 
         $expected = 'This is a phras...';
-        $result = $this->Text->excerpt($text, null, 9, '...');
+        $result = $this->Text->excerpt($text, '', 9, '...');
         $this->assertEquals($expected, $result);
 
         $expected = $text;
-        $result = $this->Text->excerpt($text, null, 200, '...');
+        $result = $this->Text->excerpt($text, '', 200, '...');
         $this->assertEquals($expected, $result);
 
         $expected = '...a phrase w...';