Browse Source

Merge pull request #12307 from cakephp/4x-utility-types

4x - Add types to Utility
Mark Story 7 years ago
parent
commit
187df2a0db

+ 1 - 1
src/Console/Shell.php

@@ -483,7 +483,7 @@ class Shell
         }
 
         $subcommands = $this->OptionParser->subcommands();
-        $method = Inflector::camelize($command);
+        $method = Inflector::camelize((string)$command);
         $isMethod = $this->hasMethod($method);
 
         if ($isMethod && $autoMethod && count($subcommands) === 0) {

+ 1 - 1
src/Shell/Task/CommandTask.php

@@ -232,7 +232,7 @@ class CommandTask extends Shell
         }
 
         $name = Inflector::camelize($name);
-        $pluginDot = Inflector::camelize($pluginDot);
+        $pluginDot = Inflector::camelize((string)$pluginDot);
         $class = App::className($pluginDot . $name, 'Shell', 'Shell');
         if (!$class) {
             return false;

+ 1 - 0
src/Utility/CookieCryptTrait.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)

+ 9 - 4
src/Utility/Crypto/OpenSsl.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -39,7 +40,7 @@ class OpenSsl
      * @return string Encrypted data.
      * @throws \InvalidArgumentException On invalid data or key.
      */
-    public static function encrypt($plain, $key)
+    public static function encrypt(string $plain, string $key): string
     {
         $method = 'AES-256-CBC';
         $ivSize = openssl_cipher_iv_length($method);
@@ -57,15 +58,19 @@ class OpenSsl
      * @return string Decrypted data. Any trailing null bytes will be removed.
      * @throws \InvalidArgumentException On invalid data or key.
      */
-    public static function decrypt($cipher, $key)
+    public static function decrypt(string $cipher, string $key): ?string
     {
         $method = 'AES-256-CBC';
         $ivSize = openssl_cipher_iv_length($method);
 
         $iv = mb_substr($cipher, 0, $ivSize, '8bit');
-
         $cipher = mb_substr($cipher, $ivSize, null, '8bit');
 
-        return openssl_decrypt($cipher, $method, $key, OPENSSL_RAW_DATA, $iv);
+        $value = openssl_decrypt($cipher, $method, $key, OPENSSL_RAW_DATA, $iv);
+        if ($value === false) {
+            return null;
+        }
+
+        return $value;
     }
 }

+ 1 - 0
src/Utility/Exception/XmlException.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)

+ 32 - 31
src/Utility/Hash.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -58,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(
@@ -121,7 +122,7 @@ class Hash
      *   if there are no matches.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::extract
      */
-    public static function extract($data, $path)
+    public static function extract($data, string $path)
     {
         if (!(is_array($data) || $data instanceof ArrayAccess)) {
             throw new InvalidArgumentException(
@@ -194,7 +195,7 @@ class Hash
      * @param string $token the token being splitted.
      * @return array [token, conditions] with token splitted
      */
-    protected static function _splitConditions($token)
+    protected static function _splitConditions(string $token): array
     {
         $conditions = false;
         $position = strpos($token, '[');
@@ -213,7 +214,7 @@ class Hash
      * @param string $token The token being matched.
      * @return bool
      */
-    protected static function _matchToken($key, $token)
+    protected static function _matchToken($key, $token): bool
     {
         switch ($token) {
             case '{n}':
@@ -234,7 +235,7 @@ class Hash
      * @param string $selector The patterns to match.
      * @return bool Fitness of expression.
      */
-    protected static function _matches($data, $selector)
+    protected static function _matches($data, string $selector): bool
     {
         preg_match_all(
             '/(\[ (?P<attr>[^=><!]+?) (\s* (?P<op>[><!]?[=]|[><]) \s* (?P<val>(?:\/.*?\/ | [^\]]+)) )? \])/x',
@@ -258,7 +259,7 @@ class Hash
                 return false;
             }
 
-            $prop = null;
+            $prop = '';
             if (isset($data[$attr])) {
                 $prop = $data[$attr];
             }
@@ -300,7 +301,7 @@ class Hash
      * @return array The data with $values inserted.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::insert
      */
-    public static function insert(array $data, $path, $values = null)
+    public static function insert(array $data, string $path, $values = null): array
     {
         $noTokens = strpos($path, '[') === false;
         if ($noTokens && strpos($path, '.') === false) {
@@ -392,7 +393,7 @@ class Hash
      * @return array The modified array.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::remove
      */
-    public static function remove(array $data, $path)
+    public static function remove(array $data, string $path): array
     {
         $noTokens = strpos($path, '[') === false;
         $noExpansion = strpos($path, '{') === false;
@@ -446,14 +447,14 @@ class Hash
      * following the path specified in `$groupPath`.
      *
      * @param array $data Array from where to extract keys and values
-     * @param string $keyPath A dot-separated string.
-     * @param string|null $valuePath A dot-separated string.
+     * @param string|array $keyPath A dot-separated string.
+     * @param string|array|null $valuePath A dot-separated string.
      * @param string|null $groupPath A dot-separated string.
      * @return array Combined array
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::combine
      * @throws \RuntimeException When keys and values count is unequal.
      */
-    public static function combine(array $data, $keyPath, $valuePath = null, $groupPath = null)
+    public static function combine(array $data, $keyPath, $valuePath = null, ?string $groupPath = null): array
     {
         if (empty($data)) {
             return [];
@@ -531,7 +532,7 @@ class Hash
      * @see sprintf()
      * @see \Cake\Utility\Hash::extract()
      */
-    public static function format(array $data, array $paths, $format)
+    public static function format(array $data, array $paths, string $format): ?array
     {
         $extracted = [];
         $count = count($paths);
@@ -569,7 +570,7 @@ class Hash
      * @return bool true If $data contains $needle, false otherwise
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::contains
      */
-    public static function contains(array $data, array $needle)
+    public static function contains(array $data, array $needle): bool
     {
         if (empty($data) || empty($needle)) {
             return false;
@@ -613,7 +614,7 @@ class Hash
      * @see \Cake\Utility\Hash::extract()
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::check
      */
-    public static function check(array $data, $path)
+    public static function check(array $data, string $path): bool
     {
         $results = static::extract($data, $path);
         if (!is_array($results)) {
@@ -632,7 +633,7 @@ class Hash
      * @return array Filtered array
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::filter
      */
-    public static function filter(array $data, $callback = ['self', '_filter'])
+    public static function filter(array $data, $callback = ['self', '_filter']): array
     {
         foreach ($data as $k => $v) {
             if (is_array($v)) {
@@ -664,7 +665,7 @@ class Hash
      * @return array
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::flatten
      */
-    public static function flatten(array $data, $separator = '.')
+    public static function flatten(array $data, string $separator = '.'): array
     {
         $result = [];
         $stack = [];
@@ -708,11 +709,11 @@ class Hash
      * @return array
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::expand
      */
-    public static function expand(array $data, $separator = '.')
+    public static function expand(array $data, string $separator = '.'): array
     {
         $result = [];
         foreach ($data as $flat => $value) {
-            $keys = explode($separator, $flat);
+            $keys = explode($separator, (string)$flat);
             $keys = array_reverse($keys);
             $child = [
                 $keys[0] => $value
@@ -745,7 +746,7 @@ class Hash
      * @return array Merged array
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::merge
      */
-    public static function merge(array $data, $merge)
+    public static function merge(array $data, $merge): array
     {
         $args = array_slice(func_get_args(), 1);
         $return = $data;
@@ -795,7 +796,7 @@ class Hash
      * @return bool true if values are numeric, false otherwise
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::numeric
      */
-    public static function numeric(array $data)
+    public static function numeric(array $data): bool
     {
         if (empty($data)) {
             return false;
@@ -815,7 +816,7 @@ class Hash
      * @return int The number of dimensions in $data
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::dimensions
      */
-    public static function dimensions(array $data)
+    public static function dimensions(array $data): int
     {
         if (empty($data)) {
             return 0;
@@ -842,7 +843,7 @@ class Hash
      * @return int The maximum number of dimensions in $data
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::maxDimensions
      */
-    public static function maxDimensions(array $data)
+    public static function maxDimensions(array $data): int
     {
         $depth = [];
         if (is_array($data) && !empty($data)) {
@@ -868,7 +869,7 @@ class Hash
      * @return array An array of the modified values.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::map
      */
-    public static function map(array $data, $path, $function)
+    public static function map(array $data, $path, $function): array
     {
         $values = (array)static::extract($data, $path);
 
@@ -884,7 +885,7 @@ class Hash
      * @return mixed The reduced value.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::reduce
      */
-    public static function reduce(array $data, $path, $function)
+    public static function reduce(array $data, string $path, $function)
     {
         $values = (array)static::extract($data, $path);
 
@@ -916,7 +917,7 @@ class Hash
      * @return mixed The results of the applied method.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::apply
      */
-    public static function apply(array $data, $path, $function)
+    public static function apply(array $data, string $path, $function)
     {
         $values = (array)static::extract($data, $path);
 
@@ -956,7 +957,7 @@ class Hash
      * @return array Sorted array of data
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::sort
      */
-    public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
+    public static function sort(array $data, string $path, string $dir = 'asc', $type = 'regular')
     {
         if (empty($data)) {
             return [];
@@ -1042,7 +1043,7 @@ class Hash
      * @param string|null $key The key for the data.
      * @return array
      */
-    protected static function _squash(array $data, $key = null)
+    protected static function _squash(array $data, $key = null): array
     {
         $stack = [];
         foreach ($data as $k => $r) {
@@ -1071,7 +1072,7 @@ class Hash
      *    The expression for this function is ($data - $compare) + ($compare - ($data - $compare))
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::diff
      */
-    public static function diff(array $data, array $compare)
+    public static function diff(array $data, array $compare): array
     {
         if (empty($data)) {
             return (array)$compare;
@@ -1098,7 +1099,7 @@ class Hash
      * @return array The merged array.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::mergeDiff
      */
-    public static function mergeDiff(array $data, array $compare)
+    public static function mergeDiff(array $data, array $compare): array
     {
         if (empty($data) && !empty($compare)) {
             return $compare;
@@ -1125,7 +1126,7 @@ class Hash
      * @return array
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::normalize
      */
-    public static function normalize(array $data, $assoc = true)
+    public static function normalize(array $data, bool $assoc = true): array
     {
         $keys = array_keys($data);
         $count = count($keys);
@@ -1173,7 +1174,7 @@ class Hash
      * @throws \InvalidArgumentException When providing invalid data.
      * @link https://book.cakephp.org/3.0/en/core-libraries/hash.html#Cake\Utility\Hash::nest
      */
-    public static function nest(array $data, array $options = [])
+    public static function nest(array $data, array $options = []): array
     {
         if (!$data) {
             return $data;

+ 12 - 11
src/Utility/Inflector.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -476,7 +477,7 @@ class Inflector
      *        new rules that are being defined in $rules.
      * @return void
      */
-    public static function rules($type, $rules, $reset = false)
+    public static function rules(string $type, array $rules, bool $reset = false)
     {
         $var = '_' . $type;
 
@@ -501,7 +502,7 @@ class Inflector
      * @return string Word in plural
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-plural-singular-forms
      */
-    public static function pluralize($word)
+    public static function pluralize(string $word): string
     {
         if (isset(static::$_cache['pluralize'][$word])) {
             return static::$_cache['pluralize'][$word];
@@ -544,7 +545,7 @@ class Inflector
      * @return string Word in singular
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-plural-singular-forms
      */
-    public static function singularize($word)
+    public static function singularize(string $word): string
     {
         if (isset(static::$_cache['singularize'][$word])) {
             return static::$_cache['singularize'][$word];
@@ -591,7 +592,7 @@ class Inflector
      * @return string CamelizedStringLikeThis.
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms
      */
-    public static function camelize($string, $delimiter = '_')
+    public static function camelize(string $string, string $delimiter = '_'): string
     {
         $cacheKey = __FUNCTION__ . $delimiter;
 
@@ -614,7 +615,7 @@ class Inflector
      * @return string underscore_version of the input string
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms
      */
-    public static function underscore($string)
+    public static function underscore(string $string): string
     {
         return static::delimit(str_replace('-', '_', $string), '_');
     }
@@ -627,7 +628,7 @@ class Inflector
      * @param string $string The string to dasherize.
      * @return string Dashed version of the input string
      */
-    public static function dasherize($string)
+    public static function dasherize(string $string): string
     {
         return static::delimit(str_replace('_', '-', $string), '-');
     }
@@ -641,7 +642,7 @@ class Inflector
      * @return string Human-readable string
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-human-readable-forms
      */
-    public static function humanize($string, $delimiter = '_')
+    public static function humanize(string $string, string $delimiter = '_'): string
     {
         $cacheKey = __FUNCTION__ . $delimiter;
 
@@ -666,7 +667,7 @@ class Inflector
      * @param string $delimiter the character to use as a delimiter
      * @return string delimited string
      */
-    public static function delimit($string, $delimiter = '_')
+    public static function delimit(string $string, string $delimiter = '_'): string
     {
         $cacheKey = __FUNCTION__ . $delimiter;
 
@@ -687,7 +688,7 @@ class Inflector
      * @return string Name of the database table for given class
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-table-and-class-name-forms
      */
-    public static function tableize($className)
+    public static function tableize(string $className): string
     {
         $result = static::_cache(__FUNCTION__, $className);
 
@@ -706,7 +707,7 @@ class Inflector
      * @return string Class name
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-table-and-class-name-forms
      */
-    public static function classify($tableName)
+    public static function classify(string $tableName): string
     {
         $result = static::_cache(__FUNCTION__, $tableName);
 
@@ -725,7 +726,7 @@ class Inflector
      * @return string in variable form
      * @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-variable-names
      */
-    public static function variable($string)
+    public static function variable(string $string): string
     {
         $result = static::_cache(__FUNCTION__, $string);
 

+ 1 - 0
src/Utility/MergeVariablesTrait.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)

+ 14 - 35
src/Utility/Security.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -58,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;
@@ -92,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;
     }
@@ -106,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);
     }
 
     /**
@@ -137,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
         );
@@ -155,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);
@@ -211,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()');
 
@@ -236,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(
@@ -251,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)) {
@@ -274,7 +253,7 @@ class Security
 
         $compareHmac = hash_hmac('sha256', $cipher, $key);
         if (!static::constantEquals($hmac, $compareHmac)) {
-            return false;
+            return null;
         }
 
         $crypto = static::engine();

+ 38 - 41
src/Utility/Text.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -59,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)
         );
     }
 
@@ -93,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 [];
@@ -187,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;
         }
@@ -252,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) {
@@ -322,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];
@@ -359,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];
@@ -408,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) {
@@ -427,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 = [];
@@ -486,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;
@@ -543,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
@@ -584,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,
@@ -682,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);
     }
@@ -699,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';
@@ -735,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';
@@ -825,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.
@@ -855,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]);
@@ -898,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);
     }
 
     /**
@@ -916,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);
 
@@ -937,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 = [];
 
@@ -978,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 = '';
 
@@ -1007,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;
@@ -1043,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()
     {
@@ -1055,7 +1053,6 @@ class Text
      *
      * @param \Transliterator $transliterator A `Transliterator` instance.
      * @return void
-     * @since 3.7.0
      */
     public static function setTransliterator(\Transliterator $transliterator)
     {
@@ -1095,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;
@@ -1125,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];

+ 20 - 17
src/Utility/Xml.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -89,9 +90,8 @@ class Xml
      * - `return` Can be 'simplexml' to return object of SimpleXMLElement or 'domdocument' to return DOMDocument.
      * - `loadEntities` Defaults to false. Set to true to enable loading of `<!ENTITY` definitions. This
      *   is disabled by default for security reasons.
-     * - `readFile` Set to false to disable file reading. This is important to disable when
-     *   putting user data into Xml::build(). If enabled local files will be read if they exist.
-     *   Defaults to true for backwards compatibility reasons.
+     * - `readFile` Set to true to enable file reading. This is disabled by default to prevent
+     *   local filesystem access. Only enable this setting when the input is safe.
      * - `parseHuge` Enable the `LIBXML_PARSEHUGE` flag.
      *
      * If using array as input, you can pass `options` from Xml::fromArray.
@@ -106,7 +106,7 @@ class Xml
         $defaults = [
             'return' => 'simplexml',
             'loadEntities' => false,
-            'readFile' => true,
+            'readFile' => false,
             'parseHuge' => false,
         ];
         $options += $defaults;
@@ -115,16 +115,17 @@ class Xml
             return static::fromArray($input, $options);
         }
 
-        if (strpos($input, '<') !== false) {
-            return static::_loadXml($input, $options);
-        }
-
         if ($options['readFile'] && file_exists($input)) {
             return static::_loadXml(file_get_contents($input), $options);
         }
 
         if (!is_string($input)) {
-            throw new XmlException('Invalid input.');
+            $type = gettype($input);
+            throw new XmlException("Invalid input. {$type} cannot be parsed as XML.");
+        }
+
+        if (strpos($input, '<') !== false) {
+            return static::_loadXml($input, $options);
         }
 
         throw new XmlException('XML cannot be read.');
@@ -138,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);
@@ -177,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',
@@ -222,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:
      *
@@ -328,7 +331,7 @@ class Xml
                             $child = $dom->createElement($key, '');
                             $child->appendChild(new DOMText($value));
                         } else {
-                            $child = $dom->createElement($key, $value);
+                            $child = $dom->createElement($key, (string)$value);
                         }
                         $node->appendChild($child);
                     } else {
@@ -336,7 +339,7 @@ class Xml
                             $key = substr($key, 1);
                         }
                         $attribute = $dom->createAttribute($key);
-                        $attribute->appendChild($dom->createTextNode($value));
+                        $attribute->appendChild($dom->createTextNode((string)$value));
                         $node->appendChild($attribute);
                     }
                 } else {
@@ -367,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,
@@ -419,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);

+ 1 - 0
src/Utility/bootstrap.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)

+ 1 - 1
src/View/View.php

@@ -732,7 +732,7 @@ class View implements EventDispatcherInterface
 
         $title = $this->Blocks->get('title');
         if ($title === '') {
-            $title = Inflector::humanize($this->templatePath);
+            $title = Inflector::humanize((string)$this->templatePath);
             $this->Blocks->set('title', $title);
         }
 

+ 6 - 4
tests/TestCase/ORM/Behavior/TimestampBehaviorTest.php

@@ -55,7 +55,7 @@ class TimestampBehaviorTest extends TestCase
      */
     public function testImplementedEventsDefault()
     {
-        $table = $this->getMockBuilder('Cake\ORM\Table')->getMock();
+        $table = $this->getTable();
         $this->Behavior = new TimestampBehavior($table);
 
         $expected = [
@@ -73,7 +73,7 @@ class TimestampBehaviorTest extends TestCase
      */
     public function testImplementedEventsCustom()
     {
-        $table = $this->getMockBuilder('Cake\ORM\Table')->getMock();
+        $table = $this->getTable();
         $settings = ['events' => ['Something.special' => ['date_specialed' => 'always']]];
         $this->Behavior = new TimestampBehavior($table, $settings);
 
@@ -488,8 +488,10 @@ class TimestampBehaviorTest extends TestCase
             'date_specialed' => ['type' => 'datetime'],
             'timestamp_str' => ['type' => 'string'],
         ];
-        $table = new Table(['schema' => $schema]);
 
-        return $table;
+        return new Table([
+            'alias' => 'Articles',
+            'schema' => $schema
+        ]);
     }
 }

+ 2 - 1
tests/TestCase/Utility/Crypto/OpenSslTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -66,6 +67,6 @@ class OpenSslTest extends TestCase
         $result = $this->crypt->encrypt($txt, $key);
 
         $key = 'Not the same key.';
-        $this->assertFalse($this->crypt->decrypt($txt, $key), 'Modified key will fail.');
+        $this->assertNull($this->crypt->decrypt($txt, $key), 'Modified key will fail.');
     }
 }

+ 1 - 0
tests/TestCase/Utility/HashTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)

+ 4 - 9
tests/TestCase/Utility/InflectorTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -378,10 +379,8 @@ class InflectorTest extends TestCase
         $this->assertSame('test_thing_extra', Inflector::underscore('testThingExtra'));
         $this->assertSame('test_thing_extrå', Inflector::underscore('testThingExtrå'));
 
-        // Test stupid values
-        $this->assertSame('', Inflector::underscore(''));
-        $this->assertSame('0', Inflector::underscore(0));
-        $this->assertSame('', Inflector::underscore(false));
+        // Test other values
+        $this->assertSame('0', Inflector::underscore('0'));
     }
 
     /**
@@ -398,10 +397,8 @@ class InflectorTest extends TestCase
         $this->assertSame('test-this-thing', Inflector::dasherize('test_this_thing'));
 
         // Test stupid values
-        $this->assertSame('', Inflector::dasherize(null));
         $this->assertSame('', Inflector::dasherize(''));
-        $this->assertSame('0', Inflector::dasherize(0));
-        $this->assertSame('', Inflector::dasherize(false));
+        $this->assertSame('0', Inflector::dasherize('0'));
     }
 
     /**
@@ -475,8 +472,6 @@ class InflectorTest extends TestCase
         $this->assertEquals('Posts', Inflector::humanize('posts'));
         $this->assertEquals('Posts Tags', Inflector::humanize('posts_tags'));
         $this->assertEquals('File Systems', Inflector::humanize('file_systems'));
-        $this->assertSame('', Inflector::humanize(null));
-        $this->assertSame('', Inflector::humanize(false));
         $this->assertSame('Hello Wörld', Inflector::humanize('hello_wörld'));
         $this->assertSame('福岡 City', Inflector::humanize('福岡_city'));
     }

+ 1 - 0
tests/TestCase/Utility/MergeVariablesTraitTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)

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

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -107,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.');
     }
 
     /**
@@ -124,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.');
     }
 
     /**
@@ -140,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.');
     }
 
     /**
@@ -169,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));
     }

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

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -175,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);
 
@@ -869,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...';

+ 15 - 10
tests/TestCase/Utility/XmlTest.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 /**
  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
@@ -20,6 +21,7 @@ use Cake\ORM\Entity;
 use Cake\TestSuite\TestCase;
 use Cake\Utility\Exception\XmlException;
 use Cake\Utility\Xml;
+use TypeError;
 
 /**
  * XmlTest class
@@ -100,17 +102,20 @@ class XmlTest extends TestCase
         $this->assertEquals('value', $obj->firstChild->nodeValue);
 
         $xml = CORE_TESTS . 'Fixture/sample.xml';
-        $obj = Xml::build($xml);
+        $obj = Xml::build($xml, ['readFile' => true]);
         $this->assertEquals('tags', $obj->getName());
         $this->assertEquals(2, count($obj));
 
-        $this->assertEquals(Xml::build($xml), Xml::build(file_get_contents($xml)));
+        $this->assertEquals(
+            Xml::build($xml, ['readFile' => true]),
+            Xml::build(file_get_contents($xml))
+        );
 
-        $obj = Xml::build($xml, ['return' => 'domdocument']);
+        $obj = Xml::build($xml, ['return' => 'domdocument', 'readFile' => true]);
         $this->assertEquals('tags', $obj->firstChild->nodeName);
 
         $this->assertEquals(
-            Xml::build($xml, ['return' => 'domdocument']),
+            Xml::build($xml, ['return' => 'domdocument', 'readFile' => true]),
             Xml::build(file_get_contents($xml), ['return' => 'domdocument'])
         );
 
@@ -123,7 +128,7 @@ class XmlTest extends TestCase
         $this->assertEquals('tag', $obj->firstChild->nodeName);
         $this->assertEquals('value', $obj->firstChild->nodeValue);
 
-        $obj = Xml::build($xml, ['return' => 'domdocument', 'encoding' => null]);
+        $obj = Xml::build($xml, ['return' => 'domdocument', 'encoding' => '']);
         $this->assertNotRegExp('/encoding/', $obj->saveXML());
     }
 
@@ -291,7 +296,7 @@ close to 5 million globally.
      */
     public function testLoadHtmlEmptyHtml()
     {
-        $this->expectException(XmlException::class);
+        $this->expectException(TypeError::class);
         Xml::loadHtml(null);
     }
 
@@ -709,7 +714,7 @@ XML;
         $this->assertEquals(['tag' => 'name'], Xml::toArray($obj));
 
         $xml = CORE_TESTS . 'Fixture/sample.xml';
-        $obj = Xml::build($xml);
+        $obj = Xml::build($xml, ['readFile' => true]);
         $expected = [
             'tags' => [
                 'tag' => [
@@ -1029,7 +1034,7 @@ XML;
      */
     public function testSoap()
     {
-        $xmlRequest = Xml::build(CORE_TESTS . 'Fixture/soap_request.xml');
+        $xmlRequest = Xml::build(CORE_TESTS . 'Fixture/soap_request.xml', ['readFile' => true]);
         $expected = [
             'Envelope' => [
                 '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding',
@@ -1042,7 +1047,7 @@ XML;
         ];
         $this->assertEquals($expected, Xml::toArray($xmlRequest));
 
-        $xmlResponse = Xml::build(CORE_TESTS . DS . 'Fixture/soap_response.xml');
+        $xmlResponse = Xml::build(CORE_TESTS . DS . 'Fixture/soap_response.xml', ['readFile' => true]);
         $expected = [
             'Envelope' => [
                 '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding',
@@ -1067,7 +1072,7 @@ XML;
                 ]
             ]
         ];
-        $xmlRequest = Xml::fromArray($xml, ['encoding' => null]);
+        $xmlRequest = Xml::fromArray($xml, ['encoding' => '']);
         $xmlText = <<<XML
 <?xml version="1.0"?>
 <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">