From 872c8fb9d70dc1dbd8e4a85a5cf49d4fe2735525 Mon Sep 17 00:00:00 2001 From: MGatner Date: Mon, 5 Sep 2022 00:16:30 +0000 Subject: [PATCH] Release v4.2.6 --- app/Config/App.php | 1 + app/Config/ContentSecurityPolicy.php | 8 +-- app/Config/Routes.php | 2 +- app/Config/Validation.php | 8 +-- composer.json | 2 +- system/API/ResponseTrait.php | 8 +-- system/CLI/CLI.php | 4 +- system/Cache/Handlers/RedisHandler.php | 6 +- system/CodeIgniter.php | 13 ++-- system/Config/BaseService.php | 72 +++++++++++----------- system/Cookie/CloneableCookieInterface.php | 2 + system/Cookie/Cookie.php | 26 ++++---- system/Database/BaseBuilder.php | 1 + system/Database/BaseConnection.php | 4 +- system/Database/SQLSRV/Forge.php | 1 - system/Debug/Exceptions.php | 6 +- system/Entity/Entity.php | 25 ++++---- system/Files/FileCollection.php | 24 ++++---- system/Filters/Filters.php | 6 +- system/HTTP/MessageTrait.php | 8 +-- system/HTTP/Negotiate.php | 4 +- system/HTTP/Response.php | 1 + system/HTTP/ResponseInterface.php | 25 ++++---- system/HTTP/ResponseTrait.php | 12 ++-- system/Helpers/cookie_helper.php | 4 +- system/I18n/Time.php | 37 +++++------ system/Model.php | 4 +- system/Publisher/Publisher.php | 20 +++--- system/Router/Router.php | 2 +- system/Test/CIUnitTestCase.php | 24 ++++---- system/Test/DatabaseTestTrait.php | 20 +++--- system/Test/FilterTestTrait.php | 12 ++-- system/Test/Mock/MockCache.php | 8 +-- system/Test/TestResponse.php | 36 +++++------ system/Test/bootstrap.php | 4 +- system/Validation/FileRules.php | 3 +- system/Validation/StrictRules/Rules.php | 40 ++++++++++-- system/Validation/Validation.php | 30 ++++++++- 38 files changed, 290 insertions(+), 223 deletions(-) diff --git a/app/Config/App.php b/app/Config/App.php index 1a5e562d..79e5741b 100644 --- a/app/Config/App.php +++ b/app/Config/App.php @@ -437,6 +437,7 @@ class App extends BaseConfig * Defaults to `Lax` as recommended in this link: * * @see https://portswigger.net/web-security/csrf/samesite-cookies + * * @deprecated `Config\Cookie` $samesite property is used. * * @var string diff --git a/app/Config/ContentSecurityPolicy.php b/app/Config/ContentSecurityPolicy.php index aa18ba9f..0be61630 100644 --- a/app/Config/ContentSecurityPolicy.php +++ b/app/Config/ContentSecurityPolicy.php @@ -15,9 +15,9 @@ */ class ContentSecurityPolicy extends BaseConfig { - //------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // Broadbrush CSP management - //------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /** * Default CSP report context @@ -43,10 +43,10 @@ class ContentSecurityPolicy extends BaseConfig */ public $upgradeInsecureRequests = false; - //------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // Sources allowed // Note: once you set a policy to 'none', it cannot be further restricted - //------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /** * Will default to self if not overridden diff --git a/app/Config/Routes.php b/app/Config/Routes.php index ff2ac645..0bfdce97 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -25,7 +25,7 @@ // where controller filters or CSRF protection are bypassed. // If you don't want to define all routes, please use the Auto Routing (Improved). // Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true. -//$routes->setAutoRoute(false); +// $routes->setAutoRoute(false); /* * -------------------------------------------------------------------- diff --git a/app/Config/Validation.php b/app/Config/Validation.php index a254c185..e0a03bdf 100644 --- a/app/Config/Validation.php +++ b/app/Config/Validation.php @@ -10,9 +10,9 @@ class Validation extends BaseConfig { - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Setup - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Stores the classes that contain the @@ -38,7 +38,7 @@ class Validation extends BaseConfig 'single' => 'CodeIgniter\Validation\Views\single', ]; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Rules - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- } diff --git a/composer.json b/composer.json index b2a1d6d0..5fcc1565 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "require-dev": { "codeigniter/coding-standard": "^1.1", "fakerphp/faker": "^1.9", - "friendsofphp/php-cs-fixer": "3.6.*", + "friendsofphp/php-cs-fixer": "~3.11.0", "mikey179/vfsstream": "^1.6", "nexusphp/cs-config": "^3.3", "phpunit/phpunit": "^9.1", diff --git a/system/API/ResponseTrait.php b/system/API/ResponseTrait.php index 5f6a52c4..6ae0e3a3 100644 --- a/system/API/ResponseTrait.php +++ b/system/API/ResponseTrait.php @@ -136,9 +136,9 @@ protected function fail($messages, int $status = 400, ?string $code = null, stri return $this->respond($response, $status, $customMessage); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Response Helpers - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Used after successfully creating a new resource. @@ -290,9 +290,9 @@ protected function failServerError(string $description = 'Internal Server Error' return $this->fail($description, $this->codes['server_error'], $code, $message); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Utility Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Handles formatting a response. Currently makes some heavy assumptions diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index 7a503031..f20a08a1 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -756,9 +756,9 @@ public static function wrap(?string $string = null, int $max = 0, int $padLeft = return $lines; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Command-Line 'URI' support - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Parses the command line it was called from and collects all diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php index df179e74..b84c0115 100644 --- a/system/Cache/Handlers/RedisHandler.php +++ b/system/Cache/Handlers/RedisHandler.php @@ -200,7 +200,7 @@ public function increment(string $key, int $offset = 1) { $key = static::validateKey($key, $this->prefix); - return $this->redis->hIncrBy($key, 'data', $offset); + return $this->redis->hIncrBy($key, '__ci_value', $offset); } /** @@ -208,9 +208,7 @@ public function increment(string $key, int $offset = 1) */ public function decrement(string $key, int $offset = 1) { - $key = static::validateKey($key, $this->prefix); - - return $this->redis->hIncrBy($key, 'data', -$offset); + return $this->increment($key, -$offset); } /** diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index d4cc2944..c81337fd 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -47,7 +47,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - public const CI_VERSION = '4.2.5'; + public const CI_VERSION = '4.2.6'; /** * App startup time. @@ -730,9 +730,12 @@ protected function generateCacheName(Cache $config): string } $uri = $this->request->getUri(); - if ($config->cacheQueryString) { - $name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery()); + if (is_array($config->cacheQueryString)) { + $name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(['only' => $config->cacheQueryString])); + } else { + $name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery()); + } } else { $name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath()); } @@ -945,11 +948,9 @@ protected function display404errors(PageNotFoundException $e) $this->response->setStatusCode($e->getCode()); if (ENVIRONMENT !== 'testing') { - // @codeCoverageIgnoreStart if (ob_get_level() > 0) { - ob_end_flush(); + ob_end_flush(); // @codeCoverageIgnore } - // @codeCoverageIgnoreEnd } // When testing, one is for phpunit, another is for test case. elseif (ob_get_level() > 2) { diff --git a/system/Config/BaseService.php b/system/Config/BaseService.php index 5213f426..07738a74 100644 --- a/system/Config/BaseService.php +++ b/system/Config/BaseService.php @@ -92,43 +92,43 @@ * @see http://blog.ircmaxell.com/2015/11/simple-easy-risk-and-change.html * @see http://www.infoq.com/presentations/Simple-Made-Easy * - * @method static CacheInterface cache(Cache $config = null, $getShared = true) - * @method static CLIRequest clirequest(App $config = null, $getShared = true) - * @method static CodeIgniter codeigniter(App $config = null, $getShared = true) - * @method static Commands commands($getShared = true) - * @method static void createRequest(App $config, bool $isCli = false) - * @method static ContentSecurityPolicy csp(CSPConfig $config = null, $getShared = true) - * @method static CURLRequest curlrequest($options = [], ResponseInterface $response = null, App $config = null, $getShared = true) - * @method static Email email($config = null, $getShared = true) - * @method static EncrypterInterface encrypter(Encryption $config = null, $getShared = false) - * @method static Exceptions exceptions(ConfigExceptions $config = null, IncomingRequest $request = null, Response $response = null, $getShared = true) - * @method static Filters filters(ConfigFilters $config = null, $getShared = true) - * @method static Format format(ConfigFormat $config = null, $getShared = true) - * @method static Honeypot honeypot(ConfigHoneyPot $config = null, $getShared = true) - * @method static BaseHandler image($handler = null, Images $config = null, $getShared = true) - * @method static IncomingRequest incomingrequest(?App $config = null, bool $getShared = true) - * @method static Iterator iterator($getShared = true) - * @method static Language language($locale = null, $getShared = true) - * @method static Logger logger($getShared = true) - * @method static MigrationRunner migrations(Migrations $config = null, ConnectionInterface $db = null, $getShared = true) - * @method static Negotiate negotiator(RequestInterface $request = null, $getShared = true) - * @method static Pager pager(ConfigPager $config = null, RendererInterface $view = null, $getShared = true) - * @method static Parser parser($viewPath = null, ConfigView $config = null, $getShared = true) - * @method static RedirectResponse redirectresponse(App $config = null, $getShared = true) - * @method static View renderer($viewPath = null, ConfigView $config = null, $getShared = true) + * @method static CacheInterface cache(Cache $config = null, $getShared = true) + * @method static CLIRequest clirequest(App $config = null, $getShared = true) + * @method static CodeIgniter codeigniter(App $config = null, $getShared = true) + * @method static Commands commands($getShared = true) + * @method static void createRequest(App $config, bool $isCli = false) + * @method static ContentSecurityPolicy csp(CSPConfig $config = null, $getShared = true) + * @method static CURLRequest curlrequest($options = [], ResponseInterface $response = null, App $config = null, $getShared = true) + * @method static Email email($config = null, $getShared = true) + * @method static EncrypterInterface encrypter(Encryption $config = null, $getShared = false) + * @method static Exceptions exceptions(ConfigExceptions $config = null, IncomingRequest $request = null, Response $response = null, $getShared = true) + * @method static Filters filters(ConfigFilters $config = null, $getShared = true) + * @method static Format format(ConfigFormat $config = null, $getShared = true) + * @method static Honeypot honeypot(ConfigHoneyPot $config = null, $getShared = true) + * @method static BaseHandler image($handler = null, Images $config = null, $getShared = true) + * @method static IncomingRequest incomingrequest(?App $config = null, bool $getShared = true) + * @method static Iterator iterator($getShared = true) + * @method static Language language($locale = null, $getShared = true) + * @method static Logger logger($getShared = true) + * @method static MigrationRunner migrations(Migrations $config = null, ConnectionInterface $db = null, $getShared = true) + * @method static Negotiate negotiator(RequestInterface $request = null, $getShared = true) + * @method static Pager pager(ConfigPager $config = null, RendererInterface $view = null, $getShared = true) + * @method static Parser parser($viewPath = null, ConfigView $config = null, $getShared = true) + * @method static RedirectResponse redirectresponse(App $config = null, $getShared = true) + * @method static View renderer($viewPath = null, ConfigView $config = null, $getShared = true) * @method static IncomingRequest|CLIRequest request(App $config = null, $getShared = true) - * @method static Response response(App $config = null, $getShared = true) - * @method static Router router(RouteCollectionInterface $routes = null, Request $request = null, $getShared = true) - * @method static RouteCollection routes($getShared = true) - * @method static Security security(App $config = null, $getShared = true) - * @method static Session session(App $config = null, $getShared = true) - * @method static Throttler throttler($getShared = true) - * @method static Timer timer($getShared = true) - * @method static Toolbar toolbar(ConfigToolbar $config = null, $getShared = true) - * @method static Typography typography($getShared = true) - * @method static URI uri($uri = null, $getShared = true) - * @method static Validation validation(ConfigValidation $config = null, $getShared = true) - * @method static Cell viewcell($getShared = true) + * @method static Response response(App $config = null, $getShared = true) + * @method static Router router(RouteCollectionInterface $routes = null, Request $request = null, $getShared = true) + * @method static RouteCollection routes($getShared = true) + * @method static Security security(App $config = null, $getShared = true) + * @method static Session session(App $config = null, $getShared = true) + * @method static Throttler throttler($getShared = true) + * @method static Timer timer($getShared = true) + * @method static Toolbar toolbar(ConfigToolbar $config = null, $getShared = true) + * @method static Typography typography($getShared = true) + * @method static URI uri($uri = null, $getShared = true) + * @method static Validation validation(ConfigValidation $config = null, $getShared = true) + * @method static Cell viewcell($getShared = true) */ class BaseService { diff --git a/system/Cookie/CloneableCookieInterface.php b/system/Cookie/CloneableCookieInterface.php index 508c1359..93f6031e 100644 --- a/system/Cookie/CloneableCookieInterface.php +++ b/system/Cookie/CloneableCookieInterface.php @@ -60,6 +60,8 @@ public function withExpired(); * Creates a new Cookie that will virtually never expire from the browser. * * @return static + * + * @deprecated See https://github.com/codeigniter4/CodeIgniter4/pull/6413 */ public function withNeverExpiring(); diff --git a/system/Cookie/Cookie.php b/system/Cookie/Cookie.php index 22c01a7d..72188451 100644 --- a/system/Cookie/Cookie.php +++ b/system/Cookie/Cookie.php @@ -152,9 +152,9 @@ public static function setDefaults($config = []) return $oldDefaults; } - //========================================================================= + // ========================================================================= // CONSTRUCTORS - //========================================================================= + // ========================================================================= /** * Create a new Cookie instance from a `Set-Cookie` header. @@ -238,9 +238,9 @@ final public function __construct(string $name, string $value = '', array $optio $this->raw = $raw; } - //========================================================================= + // ========================================================================= // GETTERS - //========================================================================= + // ========================================================================= /** * {@inheritDoc} @@ -391,9 +391,9 @@ public function getOptions(): array ]; } - //========================================================================= + // ========================================================================= // CLONING - //========================================================================= + // ========================================================================= /** * {@inheritDoc} @@ -460,7 +460,7 @@ public function withExpired() } /** - * {@inheritDoc} + * @deprecated See https://github.com/codeigniter4/CodeIgniter4/pull/6413 */ public function withNeverExpiring() { @@ -556,9 +556,9 @@ public function withRaw(bool $raw = true) return $cookie; } - //========================================================================= + // ========================================================================= // ARRAY ACCESS FOR BC - //========================================================================= + // ========================================================================= /** * Whether an offset exists. @@ -614,9 +614,9 @@ public function offsetUnset($offset): void throw new LogicException(sprintf('Cannot unset values of properties of %s as it is immutable.', static::class)); } - //========================================================================= + // ========================================================================= // CONVERTERS - //========================================================================= + // ========================================================================= /** * {@inheritDoc} @@ -716,9 +716,9 @@ protected static function convertExpiresTimestamp($expires = 0): int return $expires > 0 ? (int) $expires : 0; } - //========================================================================= + // ========================================================================= // VALIDATION - //========================================================================= + // ========================================================================= /** * Validates the cookie name per RFC 2616. diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 39e832d1..8d9bd870 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -1928,6 +1928,7 @@ public function insert($set = null, ?bool $escape = null) * @internal This is a temporary solution. * * @see https://github.com/codeigniter4/CodeIgniter4/pull/5376 + * * @TODO Fix a root cause, and this method should be removed. */ protected function removeAlias(string $from): string diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 865a1893..11e54ea7 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1352,9 +1352,9 @@ protected function getDriverFunctionPrefix(): string return strtolower($this->DBDriver) . '_'; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // META Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns an array of table names diff --git a/system/Database/SQLSRV/Forge.php b/system/Database/SQLSRV/Forge.php index bb802149..99df4290 100755 --- a/system/Database/SQLSRV/Forge.php +++ b/system/Database/SQLSRV/Forge.php @@ -125,7 +125,6 @@ protected function _createTableAttributes(array $attributes): string */ protected function _alterTable(string $alterType, string $table, $field) { - // Handle DROP here if ($alterType === 'DROP') { // check if fields are part of any indexes diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php index 9994aa7a..437a4726 100644 --- a/system/Debug/Exceptions.php +++ b/system/Debug/Exceptions.php @@ -177,7 +177,7 @@ public function shutdownHandler() ['type' => $type, 'message' => $message, 'file' => $file, 'line' => $line] = $error; if (in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE], true)) { - $this->exceptionHandler(new ErrorException($message, $type, 0, $file, $line)); + $this->exceptionHandler(new ErrorException($message, 0, $type, $file, $line)); } } @@ -329,9 +329,9 @@ protected function determineCodes(Throwable $exception): array return [$statusCode, $exitStatus]; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Display Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * This makes nicer looking paths for the error output. diff --git a/system/Entity/Entity.php b/system/Entity/Entity.php index 39adf066..e5820d07 100644 --- a/system/Entity/Entity.php +++ b/system/Entity/Entity.php @@ -25,6 +25,7 @@ use CodeIgniter\Entity\Cast\URICast; use CodeIgniter\Entity\Exceptions\CastException; use CodeIgniter\I18n\Time; +use DateTime; use Exception; use JsonSerializable; use ReturnTypeWillChange; @@ -147,7 +148,7 @@ public function fill(?array $data = null) * * @param bool $onlyChanged If true, only return values that have changed since object creation * @param bool $cast If true, properties will be cast. - * @param bool $recursive If true, inner entities will be casted as array as well. + * @param bool $recursive If true, inner entities will be cast as array as well. */ public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recursive = false): array { @@ -189,7 +190,7 @@ public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recu * Returns the raw values of the current attributes. * * @param bool $onlyChanged If true, only return values that have changed since object creation - * @param bool $recursive If true, inner entities will be casted as array as well. + * @param bool $recursive If true, inner entities will be cast as array as well. */ public function toRawArray(bool $onlyChanged = false, bool $recursive = false): array { @@ -247,7 +248,7 @@ public function syncOriginal() * was created. Or, without a parameter, checks if any * properties have changed. * - * @param string $key + * @param string|null $key class property */ public function hasChanged(?string $key = null): bool { @@ -308,11 +309,11 @@ protected function mapProperty(string $key) * Converts the given string|timestamp|DateTime|Time instance * into the "CodeIgniter\I18n\Time" object. * - * @param mixed $value + * @param DateTime|float|int|string|Time $value * * @throws Exception * - * @return mixed|Time + * @return Time */ protected function mutateDate($value) { @@ -324,13 +325,13 @@ protected function mutateDate($value) * Add ? at the beginning of $type (i.e. ?string) to get NULL * instead of casting $value if $value === null * - * @param mixed $value Attribute value - * @param string $attribute Attribute name - * @param string $method Allowed to "get" and "set" + * @param bool|float|int|string|null $value Attribute value + * @param string $attribute Attribute name + * @param string $method Allowed to "get" and "set" * * @throws CastException * - * @return mixed + * @return array|bool|float|int|object|string|null */ protected function castAs($value, string $attribute, string $method = 'get') { @@ -424,7 +425,7 @@ public function cast(?bool $cast = null) * $this->my_property = $p; * $this->setMyProperty() = $p; * - * @param mixed|null $value + * @param array|bool|float|int|object|string|null $value * * @throws Exception * @@ -471,7 +472,9 @@ public function __set(string $key, $value = null) * * @throws Exception * - * @return mixed + * @params string $key class property + * + * @return array|bool|float|int|object|string|null */ public function __get(string $key) { diff --git a/system/Files/FileCollection.php b/system/Files/FileCollection.php index 20b208fd..ee1d0477 100644 --- a/system/Files/FileCollection.php +++ b/system/Files/FileCollection.php @@ -33,9 +33,9 @@ class FileCollection implements Countable, IteratorAggregate */ protected $files = []; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Support Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Resolves a full path and verifies it is an actual directory. @@ -106,9 +106,9 @@ final protected static function matchFiles(array $files, string $pattern): array return array_filter($files, static fn ($value) => (bool) preg_match($pattern, basename($value))); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Class Core - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Loads the Filesystem helper and adds any initial files. @@ -189,9 +189,9 @@ public function add($paths, bool $recursive = true) return $this; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // File Handling - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Verifies and adds files to the list. @@ -245,9 +245,9 @@ public function removeFile(string $file) return $this->removeFiles([$file]); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Directory Handling - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Verifies and adds files from each @@ -287,9 +287,9 @@ public function addDirectory(string $directory, bool $recursive = false) return $this; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Filtering - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Removes any files from the list that match the supplied pattern @@ -335,9 +335,9 @@ public function retainPattern(string $pattern, ?string $scope = null) return $this->removeFiles(array_diff($files, self::matchFiles($files, $pattern))); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Interface Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns the current number of files in the collection. diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index d5d5e3aa..ca2b8a4b 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -134,7 +134,7 @@ private function discoverFilters() $className = $locator->getClassname($file); // Don't include our main Filter config again... - if ($className === 'Config\\Filters') { + if ($className === FiltersConfig::class) { continue; } @@ -382,9 +382,9 @@ public function getArguments(?string $key = null) return $key === null ? $this->arguments : $this->arguments[$key]; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Processors - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Add any applicable (not excluded) global filter settings to the mix. diff --git a/system/HTTP/MessageTrait.php b/system/HTTP/MessageTrait.php index 90e36ad5..daa70875 100644 --- a/system/HTTP/MessageTrait.php +++ b/system/HTTP/MessageTrait.php @@ -38,9 +38,9 @@ trait MessageTrait */ protected $headerMap = []; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Body - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sets the body of the current message. @@ -70,9 +70,9 @@ public function appendBody($data): self return $this; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Headers - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Populates the $headers array with any headers the server knows about. diff --git a/system/HTTP/Negotiate.php b/system/HTTP/Negotiate.php index d0e82257..7b0fdc2d 100644 --- a/system/HTTP/Negotiate.php +++ b/system/HTTP/Negotiate.php @@ -122,9 +122,9 @@ public function language(array $supported): string return $this->getBestMatch($supported, $this->request->getHeaderLine('accept-language'), false, false, true); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Utility Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Does the grunt work of comparing any of the app-supported values diff --git a/system/HTTP/Response.php b/system/HTTP/Response.php index bcaffa49..c0f3a2e8 100644 --- a/system/HTTP/Response.php +++ b/system/HTTP/Response.php @@ -222,6 +222,7 @@ public function getStatusCode(): int * * @see http://tools.ietf.org/html/rfc7231#section-6 * @see http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * * @deprecated Use getReasonPhrase() * * @codeCoverageIgnore diff --git a/system/HTTP/ResponseInterface.php b/system/HTTP/ResponseInterface.php index 9cf729bb..e8bfde68 100644 --- a/system/HTTP/ResponseInterface.php +++ b/system/HTTP/ResponseInterface.php @@ -141,13 +141,14 @@ public function setStatusCode(int $code, string $reason = ''); * * @see http://tools.ietf.org/html/rfc7231#section-6 * @see http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * * @deprecated Use getReasonPhrase() */ public function getReason(): string; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Convenience Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sets the date header @@ -185,9 +186,9 @@ public function setLink(PagerInterface $pager); */ public function setContentType(string $mime, string $charset = 'UTF-8'); - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Formatter Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Converts the $body into JSON and sets the Content Type header. @@ -225,11 +226,11 @@ public function setXML($body); */ public function getXML(); - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Cache Control Methods // // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sets the appropriate headers to ensure this response @@ -265,9 +266,9 @@ public function noCache(); */ public function setCache(array $options = []); - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Output Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sends the output to the browser. @@ -290,9 +291,9 @@ public function sendHeaders(); */ public function sendBody(); - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Cookie Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Set a cookie @@ -350,9 +351,9 @@ public function deleteCookie(string $name = '', string $domain = '', string $pat */ public function getCookies(); - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Response Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Perform a redirect to a new URL, in two flavors: header or location. diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 66c7ce26..2b96d6a0 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -165,9 +165,9 @@ public function setStatusCode(int $code, string $reason = '') return $this; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Convenience Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sets the date header @@ -323,11 +323,11 @@ protected function formatBody($body, string $format) return $body; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Cache Control Methods // // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sets the appropriate headers to ensure this response @@ -422,9 +422,9 @@ public function setLastModified($date) return $this; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Output Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sends the output to the browser. diff --git a/system/Helpers/cookie_helper.php b/system/Helpers/cookie_helper.php index 5537de9c..bb355f70 100755 --- a/system/Helpers/cookie_helper.php +++ b/system/Helpers/cookie_helper.php @@ -13,9 +13,9 @@ use Config\Cookie; use Config\Services; -//============================================================================= +// ============================================================================= // CodeIgniter Cookie Helpers -//============================================================================= +// ============================================================================= if (! function_exists('set_cookie')) { /** diff --git a/system/I18n/Time.php b/system/I18n/Time.php index dd26979a..9b8633fe 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -62,9 +62,9 @@ class Time extends DateTime */ protected static $testNow; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Constructors - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Time constructor. @@ -285,6 +285,7 @@ public static function createFromInstance(DateTimeInterface $dateTime, ?string $ * @return Time * * @deprecated Use createFromInstance() instead + * * @codeCoverageIgnore */ public static function instance(DateTime $dateTime, ?string $locale = null) @@ -307,9 +308,9 @@ public function toDateTime() return $dateTime; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // For Testing - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Creates an instance of Time that will be returned during testing @@ -347,9 +348,9 @@ public static function hasTestNow(): bool return static::$testNow !== null; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Getters - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns the localized Year @@ -509,9 +510,9 @@ public function getTimezoneName(): string return $this->timezone->getName(); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Setters - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sets the current year for this instance. @@ -688,9 +689,9 @@ public function setTimestamp($timestamp) return self::parse($time, $this->timezone, $this->locale); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Add/Subtract - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns a new Time instance with $seconds added to the time. @@ -836,9 +837,9 @@ public function subYears(int $years) return $time->sub(DateInterval::createFromDateString("{$years} years")); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Formatters - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns the localized value of the date in the format 'Y-m-d H:i:s' @@ -904,9 +905,9 @@ public function toLocalizedString(?string $format = null) return IntlDateFormatter::formatObject($this->toDateTime(), $format, $this->locale); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Comparison - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Determines if the datetime passed in is equal to the current instance. @@ -984,9 +985,9 @@ public function isAfter($testTime, ?string $timezone = null): bool return $ourTime > $testTime; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Differences - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns a text string that is easily readable that describes @@ -1060,9 +1061,9 @@ public function difference($testTime, ?string $timezone = null) return new TimeDifference($ourTime, $testTime); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Utilities - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns a Time instance with the timezone converted to UTC. diff --git a/system/Model.php b/system/Model.php index 5353d9a5..434fc70d 100644 --- a/system/Model.php +++ b/system/Model.php @@ -654,7 +654,7 @@ public function insert($data = null, bool $returnID = true) { if (! empty($this->tempData['data'])) { if (empty($data)) { - $data = $this->tempData['data'] ?? null; + $data = $this->tempData['data']; } else { $data = $this->transformDataToArray($data, 'insert'); $data = array_merge($this->tempData['data'], $data); @@ -680,7 +680,7 @@ public function update($id = null, $data = null): bool { if (! empty($this->tempData['data'])) { if (empty($data)) { - $data = $this->tempData['data'] ?? null; + $data = $this->tempData['data']; } else { $data = $this->transformDataToArray($data, 'update'); $data = array_merge($this->tempData['data'], $data); diff --git a/system/Publisher/Publisher.php b/system/Publisher/Publisher.php index 01a3c62d..41ecfb0d 100644 --- a/system/Publisher/Publisher.php +++ b/system/Publisher/Publisher.php @@ -85,9 +85,9 @@ class Publisher extends FileCollection */ protected $destination = FCPATH; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Support Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Discovers and returns all Publishers in the specified namespace directory. @@ -143,9 +143,9 @@ private static function wipeDirectory(string $directory): void } } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Class Core - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Loads the helper and verifies the source and destination directories. @@ -199,9 +199,9 @@ public function publish(): bool return $this->addPath('/')->merge(true); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Property Accessors - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns the source directory. @@ -254,9 +254,9 @@ final public function getPublished(): array return $this->published; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Additional Handlers - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Verifies and adds paths to the list. @@ -320,9 +320,9 @@ final public function addUri(string $uri) return $this->addFile($file); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Write Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Removes the destination and all its files and folders. diff --git a/system/Router/Router.php b/system/Router/Router.php index 43b899fb..60aa403f 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -459,7 +459,7 @@ protected function checkRoutes(string $uri): bool return true; } - [$controller, ] = explode('::', $handler); + [$controller] = explode('::', $handler); // Checks `/` in controller name if (strpos($controller, '/') !== false) { diff --git a/system/Test/CIUnitTestCase.php b/system/Test/CIUnitTestCase.php index b5a105c6..213bcf58 100644 --- a/system/Test/CIUnitTestCase.php +++ b/system/Test/CIUnitTestCase.php @@ -71,9 +71,9 @@ abstract class CIUnitTestCase extends TestCase */ private ?array $traits = null; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Database Properties - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Should run db migration? @@ -166,9 +166,9 @@ abstract class CIUnitTestCase extends TestCase */ protected $insertCache = []; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Feature Properties - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * If present, will override application @@ -216,9 +216,9 @@ abstract class CIUnitTestCase extends TestCase */ protected $requestBody = ''; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Staging - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Load the helpers. @@ -289,9 +289,9 @@ private function callTraitMethods(string $stage): void } } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Mocking - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Resets shared instanced for all Factories components @@ -338,9 +338,9 @@ protected function mockSession() Services::injectMock('session', $session); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Assertions - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Custom function to hook into CodeIgniter's Logging mechanism @@ -496,9 +496,9 @@ public function assertCloseEnoughString($expected, $actual, string $message = '' } } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Utility - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Loads up an instance of CodeIgniter diff --git a/system/Test/DatabaseTestTrait.php b/system/Test/DatabaseTestTrait.php index 539627e2..f7a6d532 100644 --- a/system/Test/DatabaseTestTrait.php +++ b/system/Test/DatabaseTestTrait.php @@ -42,9 +42,9 @@ trait DatabaseTestTrait */ private static $doneSeed = false; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Staging - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Runs the trait set up methods. @@ -89,9 +89,9 @@ public function loadDependencies() } } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Migrations - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Migrate on setUp @@ -163,9 +163,9 @@ protected function migrateDatabase() } } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Seeds - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Seed on setUp @@ -205,9 +205,9 @@ public function seed(string $name) $this->seeder->call($name); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Utility - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Reset $doneMigration and $doneSeed @@ -264,9 +264,9 @@ public function grabFromDatabase(string $table, string $column, array $where) return $query->{$column} ?? false; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Assertions - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Asserts that records that match the conditions in $where DO diff --git a/system/Test/FilterTestTrait.php b/system/Test/FilterTestTrait.php index 1407a67b..822a6b2e 100644 --- a/system/Test/FilterTestTrait.php +++ b/system/Test/FilterTestTrait.php @@ -78,9 +78,9 @@ trait FilterTestTrait */ protected $collection; - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Staging - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Initializes dependencies once. @@ -113,9 +113,9 @@ protected function setUpFilterTestTrait(): void $this->doneFilterSetUp = true; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Utility - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns a callable method for a filter position @@ -187,9 +187,9 @@ protected function getFiltersForRoute(string $route, string $position): array return $aliases[$position]; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Assertions - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Asserts that the given route at position uses diff --git a/system/Test/Mock/MockCache.php b/system/Test/Mock/MockCache.php index ebdacccb..69afc0e4 100644 --- a/system/Test/Mock/MockCache.php +++ b/system/Test/Mock/MockCache.php @@ -236,9 +236,9 @@ public function isSupported(): bool return true; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Test Helpers - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Instructs the class to ignore all @@ -255,9 +255,9 @@ public function bypass(bool $bypass = true) return $this; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Additional Assertions - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Asserts that the cache has an item named $key. diff --git a/system/Test/TestResponse.php b/system/Test/TestResponse.php index d91f0008..16a50f74 100644 --- a/system/Test/TestResponse.php +++ b/system/Test/TestResponse.php @@ -60,9 +60,9 @@ public function __construct(ResponseInterface $response) $this->setResponse($response); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Getters / Setters - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Sets the request. @@ -114,9 +114,9 @@ public function response() return $this->response; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Status Checks - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Boils down the possible responses into a boolean valid/not-valid @@ -165,9 +165,9 @@ public function assertNotOK() $this->assertFalse($this->isOK(), "{$this->response->getStatusCode()} is an unexpected successful status code, or the Response has body content."); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Redirection - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns whether or not the Response was a redirect or RedirectResponse @@ -239,9 +239,9 @@ public function getRedirectUrl(): ?string return null; } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Session - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Asserts that an SESSION key has been set and, optionally, test it's value. @@ -275,9 +275,9 @@ public function assertSessionMissing(string $key) $this->assertArrayNotHasKey($key, $_SESSION, "'{$key}' should not be present in \$_SESSION."); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Headers - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Asserts that the Response contains a specific header. @@ -305,9 +305,9 @@ public function assertHeaderMissing(string $key) $this->assertFalse($this->response->hasHeader($key), "'{$key}' should not be in the Response headers."); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // Cookies - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Asserts that the response has the specified cookie. @@ -340,9 +340,9 @@ public function assertCookieExpired(string $key, string $prefix = '') $this->assertGreaterThan(time(), $this->response->getCookie($key, $prefix)->getExpiresTimestamp()); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // JSON - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns the response's body as JSON @@ -401,9 +401,9 @@ public function assertJSONExact($test) $this->assertJsonStringEqualsJsonString($test, $json, 'Response does not contain matching JSON.'); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // XML Methods - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Returns the response' body as XML @@ -415,9 +415,9 @@ public function getXML() return $this->response->getXML(); } - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- // DomParser - //-------------------------------------------------------------------- + // -------------------------------------------------------------------- /** * Assert that the desired text can be found in the result body. diff --git a/system/Test/bootstrap.php b/system/Test/bootstrap.php index 6b0068f0..fa375808 100644 --- a/system/Test/bootstrap.php +++ b/system/Test/bootstrap.php @@ -29,9 +29,7 @@ defined('HOMEPATH') || define('HOMEPATH', realpath(rtrim(getcwd(), '\\/ ')) . DIRECTORY_SEPARATOR); $source = is_dir(HOMEPATH . 'app') ? HOMEPATH - : (is_dir('vendor/codeigniter4/framework/') - ? 'vendor/codeigniter4/framework/' - : 'vendor/codeigniter4/codeigniter4/'); + : (is_dir('vendor/codeigniter4/framework/') ? 'vendor/codeigniter4/framework/' : 'vendor/codeigniter4/codeigniter4/'); defined('CONFIGPATH') || define('CONFIGPATH', realpath($source . 'app/Config') . DIRECTORY_SEPARATOR); defined('PUBLICPATH') || define('PUBLICPATH', realpath($source . 'public') . DIRECTORY_SEPARATOR); unset($source); diff --git a/system/Validation/FileRules.php b/system/Validation/FileRules.php index aec9d9ef..ba054d13 100644 --- a/system/Validation/FileRules.php +++ b/system/Validation/FileRules.php @@ -11,6 +11,7 @@ namespace CodeIgniter\Validation; +use CodeIgniter\HTTP\CLIRequest; use CodeIgniter\HTTP\IncomingRequest; use CodeIgniter\HTTP\Request; use CodeIgniter\HTTP\RequestInterface; @@ -39,7 +40,7 @@ public function __construct(?RequestInterface $request = null) $request = Services::request(); } - assert($request instanceof IncomingRequest); + assert($request instanceof IncomingRequest || $request instanceof CLIRequest); $this->request = $request; } diff --git a/system/Validation/StrictRules/Rules.php b/system/Validation/StrictRules/Rules.php index 8861ab72..af897012 100644 --- a/system/Validation/StrictRules/Rules.php +++ b/system/Validation/StrictRules/Rules.php @@ -71,20 +71,36 @@ public function exact_length($str, string $val): bool /** * Greater than * - * @param mixed $str + * @param mixed $str expects int|string */ public function greater_than($str, string $min): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->greater_than($str, $min); } /** * Equal to or Greater than * - * @param mixed $str + * @param mixed $str expects int|string */ public function greater_than_equal_to($str, string $min): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->greater_than_equal_to($str, $min); } @@ -141,20 +157,36 @@ public function is_unique($str, string $field, array $data): bool /** * Less than * - * @param mixed $str + * @param mixed $str expects int|string */ public function less_than($str, string $max): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->less_than($str, $max); } /** * Equal to or Less than * - * @param mixed $str + * @param mixed $str expects int|string */ public function less_than_equal_to($str, string $max): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->less_than_equal_to($str, $max); } diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index ed370a2f..68557eed 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -328,7 +328,9 @@ protected function processRules( if ($passed === false) { // if the $value is an array, convert it to as string representation if (is_array($value)) { - $value = '[' . implode(', ', $value) . ']'; + $value = $this->isStringList($value) + ? '[' . implode(', ', $value) . ']' + : json_encode($value); } elseif (is_object($value)) { $value = json_encode($value); } @@ -351,6 +353,32 @@ protected function processRules( return true; } + /** + * Is the array a string list `list`? + */ + private function isStringList(array $array): bool + { + $expectedKey = 0; + + foreach ($array as $key => $val) { + // Note: also covers PHP array key conversion, e.g. '5' and 5.1 both become 5 + if (! is_int($key)) { + return false; + } + + if ($key !== $expectedKey) { + return false; + } + $expectedKey++; + + if (! is_string($val)) { + return false; + } + } + + return true; + } + /** * Takes a Request object and grabs the input data to use from its * array values.