From fe2c565a5128672b33c7c143de0de721046683ea Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 2 Nov 2021 11:16:17 +0900 Subject: [PATCH 001/407] fix: remove incorrect processing of CLI params Fixes #5266 --- system/HTTP/CLIRequest.php | 6 +++--- tests/system/HTTP/CLIRequestTest.php | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/system/HTTP/CLIRequest.php b/system/HTTP/CLIRequest.php index fcc2a51389d2..b10d41884733 100644 --- a/system/HTTP/CLIRequest.php +++ b/system/HTTP/CLIRequest.php @@ -170,17 +170,17 @@ protected function parseCommand() if ($optionValue) { $optionValue = false; } else { - $this->segments[] = esc(strip_tags($arg)); + $this->segments[] = $arg; } continue; } - $arg = esc(strip_tags(ltrim($arg, '-'))); + $arg = ltrim($arg, '-'); $value = null; if (isset($args[$i + 1]) && mb_strpos($args[$i + 1], '-') !== 0) { - $value = esc(strip_tags($args[$i + 1])); + $value = $args[$i + 1]; $optionValue = true; } diff --git a/tests/system/HTTP/CLIRequestTest.php b/tests/system/HTTP/CLIRequestTest.php index c31bace6b554..1c7c23c1c21e 100644 --- a/tests/system/HTTP/CLIRequestTest.php +++ b/tests/system/HTTP/CLIRequestTest.php @@ -61,6 +61,30 @@ public function testParsingSegments() $this->assertSame($segments, $this->request->getSegments()); } + public function testParsingSegmentsWithHTMLMetaChars() + { + $_SERVER['argv'] = [ + 'index.php', + 'users', + '21', + 'abc < def', + "McDonald's", + 'aaa', + ]; + + // reinstantiate it to force parsing + $this->request = new CLIRequest(new App()); + + $segments = [ + 'users', + '21', + 'abc < def', + "McDonald's", + 'aaa', + ]; + $this->assertSame($segments, $this->request->getSegments()); + } + public function testParsingOptions() { $_SERVER['argv'] = [ From 03551752975c39f57694ed615488f0740397c288 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 4 Nov 2021 19:10:16 +0900 Subject: [PATCH 002/407] feat: add CSRF token randomization --- app/Config/Security.php | 11 + env | 1 + system/Security/Security.php | 43 ++- system/Test/Mock/MockSecurity.php | 8 + .../SecurityCSRFSessionRandomizeTokenTest.php | 263 ++++++++++++++++++ 5 files changed, 323 insertions(+), 3 deletions(-) create mode 100644 tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php diff --git a/app/Config/Security.php b/app/Config/Security.php index 563cf2f3a86e..05083f8b1db1 100644 --- a/app/Config/Security.php +++ b/app/Config/Security.php @@ -17,6 +17,17 @@ class Security extends BaseConfig */ public $csrfProtection = 'cookie'; + /** + * -------------------------------------------------------------------------- + * CSRF Token Randomization + * -------------------------------------------------------------------------- + * + * Randomize the CSRF Token for added security. + * + * @var bool + */ + public $tokenRandomize = false; + /** * -------------------------------------------------------------------------- * CSRF Token Name diff --git a/env b/env index 6e30e34b7ddb..c60b367265e7 100644 --- a/env +++ b/env @@ -111,6 +111,7 @@ #-------------------------------------------------------------------- # security.csrfProtection = 'cookie' +# security.tokenRandomize = false # security.tokenName = 'csrf_token_name' # security.headerName = 'X-CSRF-TOKEN' # security.cookieName = 'csrf_cookie_name' diff --git a/system/Security/Security.php b/system/Security/Security.php index d9a44c4c9e6a..ef06661966f8 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -19,6 +19,7 @@ use Config\Cookie as CookieConfig; use Config\Security as SecurityConfig; use Config\Services; +use LogicException; /** * Class Security @@ -30,6 +31,7 @@ class Security implements SecurityInterface { public const CSRF_PROTECTION_COOKIE = 'cookie'; public const CSRF_PROTECTION_SESSION = 'session'; + public const CSRF_HASH_BYTES = 16; /** * CSRF Protection Method @@ -40,6 +42,13 @@ class Security implements SecurityInterface */ protected $csrfProtection = self::CSRF_PROTECTION_COOKIE; + /** + * CSRF Token Randomization + * + * @var bool + */ + protected $tokenRandomize = false; + /** * CSRF Hash * @@ -167,6 +176,7 @@ public function __construct(App $config) $this->regenerate = $security->regenerate ?? $this->regenerate; $this->rawCookieName = $security->cookieName ?? $this->rawCookieName; $this->expires = $security->expires ?? $this->expires; + $this->tokenRandomize = $security->tokenRandomize ?? $this->tokenRandomize; } else { // `Config/Security.php` is absence $this->tokenName = $config->CSRFTokenName ?? $this->tokenName; @@ -270,7 +280,8 @@ public function verify(RequestInterface $request) return $this; } - $token = $this->getPostedToken($request); + $token = $this->tokenRandomize ? $this->derandomize($this->getPostedToken($request)) + : $this->getPostedToken($request); // Do the tokens match? if (! isset($token, $this->hash) || ! hash_equals($this->hash, $token)) { @@ -329,7 +340,33 @@ private function getPostedToken(RequestInterface $request): ?string */ public function getHash(): ?string { - return $this->hash; + return $this->tokenRandomize ? $this->randomize($this->hash) : $this->hash; + } + + /** + * Randomize hash to avoid BREACH attacks. + */ + protected function randomize(string $hash): string + { + $key = random_bytes(self::CSRF_HASH_BYTES); + $value = hex2bin($hash); + + if ($value === false) { + throw new LogicException('$hash is invalid: ' . $hash); + } + + return bin2hex(($value ^ $key) . $key); + } + + /** + * Derandomize the token. + */ + protected function derandomize(string $token): string + { + $key = substr($token, -self::CSRF_HASH_BYTES * 2); + $value = substr($token, 0, self::CSRF_HASH_BYTES * 2); + + return bin2hex(hex2bin($value) ^ hex2bin($key)); } /** @@ -461,7 +498,7 @@ protected function generateHash(): string return $this->hash = $this->session->get($this->tokenName); } - $this->hash = bin2hex(random_bytes(16)); + $this->hash = bin2hex(random_bytes(self::CSRF_HASH_BYTES)); if ($this->isCSRFCookie()) { $this->saveHashInCookie(); diff --git a/system/Test/Mock/MockSecurity.php b/system/Test/Mock/MockSecurity.php index e24221c17b47..0e782304a2e7 100644 --- a/system/Test/Mock/MockSecurity.php +++ b/system/Test/Mock/MockSecurity.php @@ -19,4 +19,12 @@ protected function doSendCookie(): void { $_COOKIE['csrf_cookie_name'] = $this->hash; } + + protected function randomize(string $hash): string + { + $key = hex2bin('005513c290126d34d41bf41c5265e0f1'); + $value = hex2bin($hash); + + return bin2hex(($value ^ $key) . $key); + } } diff --git a/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php b/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php new file mode 100644 index 000000000000..00623d3db9f1 --- /dev/null +++ b/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php @@ -0,0 +1,263 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Security; + +use CodeIgniter\Config\Factories; +use CodeIgniter\Config\Services; +use CodeIgniter\HTTP\IncomingRequest; +use CodeIgniter\HTTP\URI; +use CodeIgniter\HTTP\UserAgent; +use CodeIgniter\Security\Exceptions\SecurityException; +use CodeIgniter\Session\Handlers\ArrayHandler; +use CodeIgniter\Session\Session; +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\Mock\MockAppConfig; +use CodeIgniter\Test\Mock\MockSecurity; +use CodeIgniter\Test\Mock\MockSession; +use CodeIgniter\Test\TestLogger; +use Config\App as AppConfig; +use Config\Logger as LoggerConfig; +use Config\Security as SecurityConfig; + +/** + * @runTestsInSeparateProcesses + * @preserveGlobalState disabled + * + * @internal + */ +final class SecurityCSRFSessionRandomizeTokenTest extends CIUnitTestCase +{ + /** + * @var string CSRF protection hash + */ + private $hash = '8b9218a55906f9dcc1dc263dce7f005a'; + + /** + * @var string CSRF randomized token + */ + private $randomizedToken = '8bc70b67c91494e815c7d2219c1ae0ab005513c290126d34d41bf41c5265e0f1'; + + protected function setUp(): void + { + parent::setUp(); + + $_SESSION = []; + Factories::reset(); + + $config = new SecurityConfig(); + $config->csrfProtection = Security::CSRF_PROTECTION_SESSION; + $config->tokenRandomize = true; + Factories::injectMock('config', 'Security', $config); + + $this->injectSession($this->hash); + } + + private function createSession($options = []): Session + { + $defaults = [ + 'sessionDriver' => 'CodeIgniter\Session\Handlers\FileHandler', + 'sessionCookieName' => 'ci_session', + 'sessionExpiration' => 7200, + 'sessionSavePath' => null, + 'sessionMatchIP' => false, + 'sessionTimeToUpdate' => 300, + 'sessionRegenerateDestroy' => false, + 'cookieDomain' => '', + 'cookiePrefix' => '', + 'cookiePath' => '/', + 'cookieSecure' => false, + 'cookieSameSite' => 'Lax', + ]; + + $config = array_merge($defaults, $options); + $appConfig = new AppConfig(); + + foreach ($config as $key => $c) { + $appConfig->{$key} = $c; + } + + $session = new MockSession(new ArrayHandler($appConfig, '127.0.0.1'), $appConfig); + $session->setLogger(new TestLogger(new LoggerConfig())); + + return $session; + } + + private function injectSession(string $hash): void + { + $session = $this->createSession(); + $session->set('csrf_test_name', $hash); + Services::injectMock('session', $session); + } + + public function testHashIsReadFromSession() + { + $security = new MockSecurity(new MockAppConfig()); + + $this->assertSame( + $this->randomizedToken, + $security->getHash() + ); + } + + public function testCSRFVerifyPostThrowsExceptionOnNoMatch() + { + $this->expectException(SecurityException::class); + + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_POST['csrf_test_name'] = '8b9218a55906f9dcc1dc263dce7f005b'; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + + $security = new Security(new MockAppConfig()); + + $security->verify($request); + } + + public function testCSRFVerifyPostReturnsSelfOnMatch() + { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_POST['foo'] = 'bar'; + $_POST['csrf_test_name'] = $this->randomizedToken; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + + $security = new Security(new MockAppConfig()); + + $this->assertInstanceOf(Security::class, $security->verify($request)); + $this->assertLogged('info', 'CSRF token verified.'); + $this->assertTrue(count($_POST) === 1); + } + + public function testCSRFVerifyPOSTHeaderThrowsExceptionOnNoMatch() + { + $_SERVER['REQUEST_METHOD'] = 'POST'; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request->setHeader('X-CSRF-TOKEN', '8b9218a55906f9dcc1dc263dce7f005b'); + + $security = new Security(new MockAppConfig()); + + $this->expectException(SecurityException::class); + $security->verify($request); + } + + public function testCSRFVerifyPOSTHeaderReturnsSelfOnMatch() + { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_POST['foo'] = 'bar'; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request->setHeader('X-CSRF-TOKEN', $this->randomizedToken); + + $security = new Security(new MockAppConfig()); + + $this->assertInstanceOf(Security::class, $security->verify($request)); + $this->assertLogged('info', 'CSRF token verified.'); + $this->assertCount(1, $_POST); + } + + public function testCSRFVerifyPUTHeaderThrowsExceptionOnNoMatch() + { + $_SERVER['REQUEST_METHOD'] = 'PUT'; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request->setHeader('X-CSRF-TOKEN', '8b9218a55906f9dcc1dc263dce7f005b'); + + $security = new Security(new MockAppConfig()); + + $this->expectException(SecurityException::class); + $security->verify($request); + } + + public function testCSRFVerifyPUTHeaderReturnsSelfOnMatch() + { + $_SERVER['REQUEST_METHOD'] = 'PUT'; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request->setHeader('X-CSRF-TOKEN', $this->randomizedToken); + + $security = new Security(new MockAppConfig()); + + $this->assertInstanceOf(Security::class, $security->verify($request)); + $this->assertLogged('info', 'CSRF token verified.'); + } + + public function testCSRFVerifyJsonThrowsExceptionOnNoMatch() + { + $this->expectException(SecurityException::class); + + $_SERVER['REQUEST_METHOD'] = 'POST'; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request->setBody('{"csrf_test_name":"8b9218a55906f9dcc1dc263dce7f005b"}'); + + $security = new Security(new MockAppConfig()); + + $security->verify($request); + } + + public function testCSRFVerifyJsonReturnsSelfOnMatch() + { + $_SERVER['REQUEST_METHOD'] = 'POST'; + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request->setBody('{"csrf_test_name":"' . $this->randomizedToken . '","foo":"bar"}'); + + $security = new Security(new MockAppConfig()); + + $this->assertInstanceOf(Security::class, $security->verify($request)); + $this->assertLogged('info', 'CSRF token verified.'); + $this->assertTrue($request->getBody() === '{"foo":"bar"}'); + } + + public function testRegenerateWithFalseSecurityRegenerateProperty() + { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_POST['csrf_test_name'] = $this->randomizedToken; + + $config = Factories::config('Security'); + $config->tokenRandomize = true; + $config->regenerate = false; + Factories::injectMock('config', 'Security', $config); + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + + $security = new MockSecurity(new MockAppConfig()); + + $oldHash = $security->getHash(); + $security->verify($request); + $newHash = $security->getHash(); + + $this->assertSame($oldHash, $newHash); + } + + public function testRegenerateWithTrueSecurityRegenerateProperty() + { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_POST['csrf_test_name'] = $this->randomizedToken; + + $config = Factories::config('Security'); + $config->tokenRandomize = true; + $config->regenerate = true; + Factories::injectMock('config', 'Security', $config); + + $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + + $security = new Security(new MockAppConfig()); + + $oldHash = $security->getHash(); + $security->verify($request); + $newHash = $security->getHash(); + + $this->assertNotSame($oldHash, $newHash); + } +} From 699129bd84238a35fb93ab54efc62d085fb5c4af Mon Sep 17 00:00:00 2001 From: vlakoff Date: Wed, 27 Oct 2021 07:05:41 +0200 Subject: [PATCH 003/407] Add variable $op, in order to not alter variable $k Conceptually cleaner, and will be helpful for the next commit. --- system/Database/BaseBuilder.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index f87f21bf7308..a2c407194ed2 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -666,9 +666,9 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $bind = $this->setBind($k, $v, $escape); if (empty($op)) { - $k .= ' ='; + $op = ' ='; } else { - $k .= " {$op}"; + $op = " {$op}"; } if ($v instanceof Closure) { @@ -679,13 +679,16 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type } } elseif (! $this->hasOperator($k) && $qbKey !== 'QBHaving') { // value appears not to have been set, assign the test to IS NULL - $k .= ' IS NULL'; + $op = ' IS NULL'; } elseif (preg_match('/\s*(!?=|<>|IS(?:\s+NOT)?)\s*$/i', $k, $match, PREG_OFFSET_CAPTURE)) { - $k = substr($k, 0, $match[0][1]) . ($match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL'); + $k = substr($k, 0, $match[0][1]); + $op = $match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL'; + } else { + $op = ''; } $this->{$qbKey}[] = [ - 'condition' => $prefix . $k . $v, + 'condition' => $prefix . $k . $op . $v, 'escape' => $escape, ]; } From 223ca28400a95594490052b032e1a921237138fb Mon Sep 17 00:00:00 2001 From: vlakoff Date: Wed, 27 Oct 2021 07:34:15 +0200 Subject: [PATCH 004/407] Do not inappropriately register bind when the value is a closure Such closure just has nothing to do in the $binds array. The code currently works because the binds compiler determines the binds to apply not by looking at the $binds array, but by looking at the query string, so it doesn't reach the closure. If we modify the binds compiler to instead look at the $binds array (which makes more sense), it would attempt to replace this registered named bind in the query string, and trying to replace with a closure would trigger a "cannot cast to string" error. --- system/Database/BaseBuilder.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index a2c407194ed2..51066398be33 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -663,8 +663,6 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type } } - $bind = $this->setBind($k, $v, $escape); - if (empty($op)) { $op = ' ='; } else { @@ -675,7 +673,8 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $builder = $this->cleanClone(); $v = '(' . str_replace("\n", ' ', $v($builder)->getCompiledSelect()) . ')'; } else { - $v = " :{$bind}:"; + $bind = $this->setBind($k, $v, $escape); + $v = " :{$bind}:"; } } elseif (! $this->hasOperator($k) && $qbKey !== 'QBHaving') { // value appears not to have been set, assign the test to IS NULL From 0ae8a670b2b90a89745c201f3846496b25128869 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Wed, 27 Oct 2021 07:41:15 +0200 Subject: [PATCH 005/407] Code simplification We can simply merge these two blocks. --- system/Database/BaseBuilder.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 51066398be33..f393c6f3874d 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -661,12 +661,9 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type if (substr($k, -1 * strlen($op)) === $op) { $k = rtrim(strrev(preg_replace(strrev('/' . $op . '/'), strrev(''), strrev($k), 1))); } - } - - if (empty($op)) { - $op = ' ='; - } else { $op = " {$op}"; + } else { + $op = ' ='; } if ($v instanceof Closure) { From abd0f7a93f314d4f3ce35fe5aac34eb4541db9f9 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Wed, 27 Oct 2021 07:48:56 +0200 Subject: [PATCH 006/407] Another code simplification Exact same effect: this complicated code was for replacing the last occurrence (there is no built-in function for this), and there is an englobing condition to ensure we replace the substring $op only if it is at the very end of $k. As a bonus, previous code was missing a preg_quote(), but we no longer need it. --- system/Database/BaseBuilder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index f393c6f3874d..0d0c21e75b3f 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -658,8 +658,8 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $op = trim(current($op)); - if (substr($k, -1 * strlen($op)) === $op) { - $k = rtrim(strrev(preg_replace(strrev('/' . $op . '/'), strrev(''), strrev($k), 1))); + if (substr($k, -strlen($op)) === $op) { + $k = rtrim(substr($k, 0, -strlen($op))); } $op = " {$op}"; } else { From 3e8903aa306e0cb6c3638b054299eda22b53881f Mon Sep 17 00:00:00 2001 From: vlakoff Date: Wed, 27 Oct 2021 07:58:01 +0200 Subject: [PATCH 007/407] Do not append $op if it has not been removed from $k If getOperator() found an $op, but it is not at the very end of $k, it does not get removed from $k. Previous code was nevertheless appending $op, so it got repeated a second time in the result, which is obviously wrong. --- system/Database/BaseBuilder.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 0d0c21e75b3f..e98084fcbec4 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -659,9 +659,11 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $op = trim(current($op)); if (substr($k, -strlen($op)) === $op) { - $k = rtrim(substr($k, 0, -strlen($op))); + $k = rtrim(substr($k, 0, -strlen($op))); + $op = " {$op}"; + } else { + $op = ''; } - $op = " {$op}"; } else { $op = ' ='; } From 01dfc65437c8972faa4ec3d2f17fec228e91f70f Mon Sep 17 00:00:00 2001 From: vlakoff Date: Wed, 27 Oct 2021 07:59:09 +0200 Subject: [PATCH 008/407] Adding a space in query This space isn't mandatory, and the query string gets normalized later, adding this space, but let's make it cleanly in the first place. --- system/Database/BaseBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index e98084fcbec4..b5088b23acea 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -670,7 +670,7 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type if ($v instanceof Closure) { $builder = $this->cleanClone(); - $v = '(' . str_replace("\n", ' ', $v($builder)->getCompiledSelect()) . ')'; + $v = ' (' . str_replace("\n", ' ', $v($builder)->getCompiledSelect()) . ')'; } else { $bind = $this->setBind($k, $v, $escape); $v = " :{$bind}:"; From 65b8569f0b1dd9de816b7ed197b9683dd9f3f9fd Mon Sep 17 00:00:00 2001 From: vlakoff Date: Thu, 28 Oct 2021 00:34:30 +0200 Subject: [PATCH 009/407] Micro-optimization strtr() is faster for single-character replacements. --- system/Database/BaseBuilder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index b5088b23acea..0a720cf33036 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -670,7 +670,7 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type if ($v instanceof Closure) { $builder = $this->cleanClone(); - $v = ' (' . str_replace("\n", ' ', $v($builder)->getCompiledSelect()) . ')'; + $v = ' (' . strtr($v($builder)->getCompiledSelect(), "\n", ' ') . ')'; } else { $bind = $this->setBind($k, $v, $escape); $v = " :{$bind}:"; @@ -842,7 +842,7 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal if ($values instanceof Closure) { $builder = $this->cleanClone(); - $ok = str_replace("\n", ' ', $values($builder)->getCompiledSelect()); + $ok = strtr($values($builder)->getCompiledSelect(), "\n", ' '); } else { $whereIn = array_values($values); $ok = $this->setBind($ok, $whereIn, $escape); From 68ad98764be764384378ceaed0bce49adb5d4317 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Sat, 30 Oct 2021 08:18:34 +0200 Subject: [PATCH 010/407] Add unit test for the case "$v === null and $k has operator" For this code path: "elseif (preg_match('/\s*(!?=|<>|IS(?:\s+NOT)?)\s*$/i', $k ..." The above code path "elseif (! $this->hasOperator($k) ..." is covered in testOrWhereInClosure() and testOrWhereNotInClosure(). --- tests/system/Database/Builder/WhereTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/system/Database/Builder/WhereTest.php b/tests/system/Database/Builder/WhereTest.php index 653c837058aa..e58af53cadab 100644 --- a/tests/system/Database/Builder/WhereTest.php +++ b/tests/system/Database/Builder/WhereTest.php @@ -111,6 +111,22 @@ public function testWhereAssociateArray() $this->assertSame($expectedBinds, $builder->getBinds()); } + public function testWhereAssociateArrayKeyHasEqualValueIsNull() + { + $builder = $this->db->table('users'); + + $where = [ + 'deleted_at =' => null, + ]; + + $expectedSQL = 'SELECT * FROM "users" WHERE "deleted_at" IS NULL'; + $expectedBinds = []; + + $builder->where($where); + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); + $this->assertSame($expectedBinds, $builder->getBinds()); + } + public function testWhereCustomString() { $builder = $this->db->table('jobs'); From 8839f74ba5d2147f214a7b61010cf6a598500876 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 3 Nov 2021 09:44:34 +0800 Subject: [PATCH 011/407] Optimize CreditCardRulesTest --- .../system/Validation/CreditCardRulesTest.php | 504 +++++++++--------- 1 file changed, 243 insertions(+), 261 deletions(-) diff --git a/tests/system/Validation/CreditCardRulesTest.php b/tests/system/Validation/CreditCardRulesTest.php index 7610ea4ee966..11725f3d4665 100644 --- a/tests/system/Validation/CreditCardRulesTest.php +++ b/tests/system/Validation/CreditCardRulesTest.php @@ -13,6 +13,7 @@ use CodeIgniter\Test\CIUnitTestCase; use Config\Services; +use Generator; use Tests\Support\Validation\TestRules; /** @@ -23,9 +24,9 @@ final class CreditCardRulesTest extends CIUnitTestCase /** * @var Validation */ - protected $validation; + private $validation; - protected $config = [ + private $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -48,29 +49,15 @@ protected function setUp(): void parent::setUp(); $this->validation = new Validation((object) $this->config, Services::renderer()); $this->validation->reset(); - - $_FILES = []; } - // Credit Card Rules - /** * @dataProvider creditCardProvider - * - * @param string $type - * @param string|null $number - * @param bool $expected */ - public function testValidCCNumber($type, $number, $expected = false) + public function testValidCCNumber(string $type, ?string $number, bool $expected): void { - $data = [ - 'cc' => $number, - ]; - - $this->validation->setRules([ - 'cc' => "valid_cc_number[{$type}]", - ]); - + $data = ['cc' => $number]; + $this->validation->setRules(['cc' => "valid_cc_number[{$type}]"]); $this->assertSame($expected, $this->validation->run($data)); } @@ -78,12 +65,10 @@ public function testValidCCNumber($type, $number, $expected = false) * Cards shown are test cards found around the web. * * @see https://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm - * - * @return array */ - public function creditCardProvider() + public function creditCardProvider(): Generator { - return [ + yield from [ 'null_test' => [ 'amex', null, @@ -91,7 +76,7 @@ public function creditCardProvider() ], 'random_test' => [ 'amex', - $this->generateCardNum('37', 16), + $this->generateCardNumber('37', 16), false, ], 'invalid_type' => [ @@ -191,1075 +176,1072 @@ public function creditCardProvider() ], 'unionpay1' => [ 'unionpay', - $this->generateCardNum(62, 16), + $this->generateCardNumber(62, 16), true, ], 'unionpay2' => [ 'unionpay', - $this->generateCardNum(62, 17), + $this->generateCardNumber(62, 17), true, ], 'unionpay3' => [ 'unionpay', - $this->generateCardNum(62, 18), + $this->generateCardNumber(62, 18), true, ], 'unionpay4' => [ 'unionpay', - $this->generateCardNum(62, 19), + $this->generateCardNumber(62, 19), true, ], 'unionpay5' => [ 'unionpay', - $this->generateCardNum(63, 19), + $this->generateCardNumber(63, 19), false, ], 'carteblanche1' => [ 'carteblanche', - $this->generateCardNum(300, 14), + $this->generateCardNumber(300, 14), true, ], 'carteblanche2' => [ 'carteblanche', - $this->generateCardNum(301, 14), + $this->generateCardNumber(301, 14), true, ], 'carteblanche3' => [ 'carteblanche', - $this->generateCardNum(302, 14), + $this->generateCardNumber(302, 14), true, ], 'carteblanche4' => [ 'carteblanche', - $this->generateCardNum(303, 14), + $this->generateCardNumber(303, 14), true, ], 'carteblanche5' => [ 'carteblanche', - $this->generateCardNum(304, 14), + $this->generateCardNumber(304, 14), true, ], 'carteblanche6' => [ 'carteblanche', - $this->generateCardNum(305, 14), + $this->generateCardNumber(305, 14), true, ], 'carteblanche7' => [ 'carteblanche', - $this->generateCardNum(306, 14), + $this->generateCardNumber(306, 14), false, ], 'dinersclub3' => [ 'dinersclub', - $this->generateCardNum(300, 14), + $this->generateCardNumber(300, 14), true, ], 'dinersclub4' => [ 'dinersclub', - $this->generateCardNum(301, 14), + $this->generateCardNumber(301, 14), true, ], 'dinersclub5' => [ 'dinersclub', - $this->generateCardNum(302, 14), + $this->generateCardNumber(302, 14), true, ], 'dinersclub6' => [ 'dinersclub', - $this->generateCardNum(303, 14), + $this->generateCardNumber(303, 14), true, ], 'dinersclub7' => [ 'dinersclub', - $this->generateCardNum(304, 14), + $this->generateCardNumber(304, 14), true, ], 'dinersclub8' => [ 'dinersclub', - $this->generateCardNum(305, 14), + $this->generateCardNumber(305, 14), true, ], 'dinersclub9' => [ 'dinersclub', - $this->generateCardNum(309, 14), + $this->generateCardNumber(309, 14), true, ], 'dinersclub10' => [ 'dinersclub', - $this->generateCardNum(36, 14), + $this->generateCardNumber(36, 14), true, ], 'dinersclub11' => [ 'dinersclub', - $this->generateCardNum(38, 14), + $this->generateCardNumber(38, 14), true, ], 'dinersclub12' => [ 'dinersclub', - $this->generateCardNum(39, 14), + $this->generateCardNumber(39, 14), true, ], 'dinersclub13' => [ 'dinersclub', - $this->generateCardNum(54, 14), + $this->generateCardNumber(54, 14), true, ], 'dinersclub14' => [ 'dinersclub', - $this->generateCardNum(55, 14), + $this->generateCardNumber(55, 14), true, ], 'dinersclub15' => [ 'dinersclub', - $this->generateCardNum(300, 16), + $this->generateCardNumber(300, 16), true, ], 'dinersclub16' => [ 'dinersclub', - $this->generateCardNum(301, 16), + $this->generateCardNumber(301, 16), true, ], 'dinersclub17' => [ 'dinersclub', - $this->generateCardNum(302, 16), + $this->generateCardNumber(302, 16), true, ], 'dinersclub18' => [ 'dinersclub', - $this->generateCardNum(303, 16), + $this->generateCardNumber(303, 16), true, ], 'dinersclub19' => [ 'dinersclub', - $this->generateCardNum(304, 16), + $this->generateCardNumber(304, 16), true, ], 'dinersclub20' => [ 'dinersclub', - $this->generateCardNum(305, 16), + $this->generateCardNumber(305, 16), true, ], 'dinersclub21' => [ 'dinersclub', - $this->generateCardNum(309, 16), + $this->generateCardNumber(309, 16), true, ], 'dinersclub22' => [ 'dinersclub', - $this->generateCardNum(36, 16), + $this->generateCardNumber(36, 16), true, ], 'dinersclub23' => [ 'dinersclub', - $this->generateCardNum(38, 16), + $this->generateCardNumber(38, 16), true, ], 'dinersclub24' => [ 'dinersclub', - $this->generateCardNum(39, 16), + $this->generateCardNumber(39, 16), true, ], 'dinersclub25' => [ 'dinersclub', - $this->generateCardNum(54, 16), + $this->generateCardNumber(54, 16), true, ], 'dinersclub26' => [ 'dinersclub', - $this->generateCardNum(55, 16), + $this->generateCardNumber(55, 16), true, ], 'discover3' => [ 'discover', - $this->generateCardNum(6011, 16), + $this->generateCardNumber(6011, 16), true, ], 'discover4' => [ 'discover', - $this->generateCardNum(622, 16), + $this->generateCardNumber(622, 16), true, ], 'discover5' => [ 'discover', - $this->generateCardNum(644, 16), + $this->generateCardNumber(644, 16), true, ], 'discover6' => [ 'discover', - $this->generateCardNum(645, 16), + $this->generateCardNumber(645, 16), true, ], 'discover7' => [ 'discover', - $this->generateCardNum(656, 16), + $this->generateCardNumber(656, 16), true, ], 'discover8' => [ 'discover', - $this->generateCardNum(647, 16), + $this->generateCardNumber(647, 16), true, ], 'discover9' => [ 'discover', - $this->generateCardNum(648, 16), + $this->generateCardNumber(648, 16), true, ], 'discover10' => [ 'discover', - $this->generateCardNum(649, 16), + $this->generateCardNumber(649, 16), true, ], 'discover11' => [ 'discover', - $this->generateCardNum(65, 16), + $this->generateCardNumber(65, 16), true, ], 'discover12' => [ 'discover', - $this->generateCardNum(6011, 19), + $this->generateCardNumber(6011, 19), true, ], 'discover13' => [ 'discover', - $this->generateCardNum(622, 19), + $this->generateCardNumber(622, 19), true, ], 'discover14' => [ 'discover', - $this->generateCardNum(644, 19), + $this->generateCardNumber(644, 19), true, ], 'discover15' => [ 'discover', - $this->generateCardNum(645, 19), + $this->generateCardNumber(645, 19), true, ], 'discover16' => [ 'discover', - $this->generateCardNum(656, 19), + $this->generateCardNumber(656, 19), true, ], 'discover17' => [ 'discover', - $this->generateCardNum(647, 19), + $this->generateCardNumber(647, 19), true, ], 'discover18' => [ 'discover', - $this->generateCardNum(648, 19), + $this->generateCardNumber(648, 19), true, ], 'discover19' => [ 'discover', - $this->generateCardNum(649, 19), + $this->generateCardNumber(649, 19), true, ], 'discover20' => [ 'discover', - $this->generateCardNum(65, 19), + $this->generateCardNumber(65, 19), true, ], 'interpayment1' => [ 'interpayment', - $this->generateCardNum(4, 16), + $this->generateCardNumber(4, 16), true, ], 'interpayment2' => [ 'interpayment', - $this->generateCardNum(4, 17), + $this->generateCardNumber(4, 17), true, ], 'interpayment3' => [ 'interpayment', - $this->generateCardNum(4, 18), + $this->generateCardNumber(4, 18), true, ], 'interpayment4' => [ 'interpayment', - $this->generateCardNum(4, 19), + $this->generateCardNumber(4, 19), true, ], 'jcb1' => [ 'jcb', - $this->generateCardNum(352, 16), + $this->generateCardNumber(352, 16), true, ], 'jcb2' => [ 'jcb', - $this->generateCardNum(353, 16), + $this->generateCardNumber(353, 16), true, ], 'jcb3' => [ 'jcb', - $this->generateCardNum(354, 16), + $this->generateCardNumber(354, 16), true, ], 'jcb4' => [ 'jcb', - $this->generateCardNum(355, 16), + $this->generateCardNumber(355, 16), true, ], 'jcb5' => [ 'jcb', - $this->generateCardNum(356, 16), + $this->generateCardNumber(356, 16), true, ], 'jcb6' => [ 'jcb', - $this->generateCardNum(357, 16), + $this->generateCardNumber(357, 16), true, ], 'jcb7' => [ 'jcb', - $this->generateCardNum(358, 16), + $this->generateCardNumber(358, 16), true, ], 'maestro1' => [ 'maestro', - $this->generateCardNum(50, 12), + $this->generateCardNumber(50, 12), true, ], 'maestro2' => [ 'maestro', - $this->generateCardNum(56, 12), + $this->generateCardNumber(56, 12), true, ], 'maestro3' => [ 'maestro', - $this->generateCardNum(57, 12), + $this->generateCardNumber(57, 12), true, ], 'maestro4' => [ 'maestro', - $this->generateCardNum(58, 12), + $this->generateCardNumber(58, 12), true, ], 'maestro5' => [ 'maestro', - $this->generateCardNum(59, 12), + $this->generateCardNumber(59, 12), true, ], 'maestro6' => [ 'maestro', - $this->generateCardNum(60, 12), + $this->generateCardNumber(60, 12), true, ], 'maestro7' => [ 'maestro', - $this->generateCardNum(61, 12), + $this->generateCardNumber(61, 12), true, ], 'maestro8' => [ 'maestro', - $this->generateCardNum(62, 12), + $this->generateCardNumber(62, 12), true, ], 'maestro9' => [ 'maestro', - $this->generateCardNum(63, 12), + $this->generateCardNumber(63, 12), true, ], 'maestro10' => [ 'maestro', - $this->generateCardNum(64, 12), + $this->generateCardNumber(64, 12), true, ], 'maestro11' => [ 'maestro', - $this->generateCardNum(65, 12), + $this->generateCardNumber(65, 12), true, ], 'maestro12' => [ 'maestro', - $this->generateCardNum(66, 12), + $this->generateCardNumber(66, 12), true, ], 'maestro13' => [ 'maestro', - $this->generateCardNum(67, 12), + $this->generateCardNumber(67, 12), true, ], 'maestro14' => [ 'maestro', - $this->generateCardNum(68, 12), + $this->generateCardNumber(68, 12), true, ], 'maestro15' => [ 'maestro', - $this->generateCardNum(69, 12), + $this->generateCardNumber(69, 12), true, ], 'maestro16' => [ 'maestro', - $this->generateCardNum(50, 13), + $this->generateCardNumber(50, 13), true, ], 'maestro17' => [ 'maestro', - $this->generateCardNum(56, 13), + $this->generateCardNumber(56, 13), true, ], 'maestro18' => [ 'maestro', - $this->generateCardNum(57, 13), + $this->generateCardNumber(57, 13), true, ], 'maestro19' => [ 'maestro', - $this->generateCardNum(58, 13), + $this->generateCardNumber(58, 13), true, ], 'maestro20' => [ 'maestro', - $this->generateCardNum(59, 13), + $this->generateCardNumber(59, 13), true, ], 'maestro21' => [ 'maestro', - $this->generateCardNum(60, 13), + $this->generateCardNumber(60, 13), true, ], 'maestro22' => [ 'maestro', - $this->generateCardNum(61, 13), + $this->generateCardNumber(61, 13), true, ], 'maestro23' => [ 'maestro', - $this->generateCardNum(62, 13), + $this->generateCardNumber(62, 13), true, ], 'maestro24' => [ 'maestro', - $this->generateCardNum(63, 13), + $this->generateCardNumber(63, 13), true, ], 'maestro25' => [ 'maestro', - $this->generateCardNum(64, 13), + $this->generateCardNumber(64, 13), true, ], 'maestro26' => [ 'maestro', - $this->generateCardNum(65, 13), + $this->generateCardNumber(65, 13), true, ], 'maestro27' => [ 'maestro', - $this->generateCardNum(66, 13), + $this->generateCardNumber(66, 13), true, ], 'maestro28' => [ 'maestro', - $this->generateCardNum(67, 13), + $this->generateCardNumber(67, 13), true, ], 'maestro29' => [ 'maestro', - $this->generateCardNum(68, 13), + $this->generateCardNumber(68, 13), true, ], 'maestro30' => [ 'maestro', - $this->generateCardNum(69, 13), + $this->generateCardNumber(69, 13), true, ], 'maestro31' => [ 'maestro', - $this->generateCardNum(50, 14), + $this->generateCardNumber(50, 14), true, ], 'maestro32' => [ 'maestro', - $this->generateCardNum(56, 14), + $this->generateCardNumber(56, 14), true, ], 'maestro33' => [ 'maestro', - $this->generateCardNum(57, 14), + $this->generateCardNumber(57, 14), true, ], 'maestro34' => [ 'maestro', - $this->generateCardNum(58, 14), + $this->generateCardNumber(58, 14), true, ], 'maestro35' => [ 'maestro', - $this->generateCardNum(59, 14), + $this->generateCardNumber(59, 14), true, ], 'maestro36' => [ 'maestro', - $this->generateCardNum(60, 14), + $this->generateCardNumber(60, 14), true, ], 'maestro37' => [ 'maestro', - $this->generateCardNum(61, 14), + $this->generateCardNumber(61, 14), true, ], 'maestro38' => [ 'maestro', - $this->generateCardNum(62, 14), + $this->generateCardNumber(62, 14), true, ], 'maestro39' => [ 'maestro', - $this->generateCardNum(63, 14), + $this->generateCardNumber(63, 14), true, ], 'maestro40' => [ 'maestro', - $this->generateCardNum(64, 14), + $this->generateCardNumber(64, 14), true, ], 'maestro41' => [ 'maestro', - $this->generateCardNum(65, 14), + $this->generateCardNumber(65, 14), true, ], 'maestro42' => [ 'maestro', - $this->generateCardNum(66, 14), + $this->generateCardNumber(66, 14), true, ], 'maestro43' => [ 'maestro', - $this->generateCardNum(67, 14), + $this->generateCardNumber(67, 14), true, ], 'maestro44' => [ 'maestro', - $this->generateCardNum(68, 14), + $this->generateCardNumber(68, 14), true, ], 'maestro45' => [ 'maestro', - $this->generateCardNum(69, 14), + $this->generateCardNumber(69, 14), true, ], 'maestro46' => [ 'maestro', - $this->generateCardNum(50, 15), + $this->generateCardNumber(50, 15), true, ], 'maestro47' => [ 'maestro', - $this->generateCardNum(56, 15), + $this->generateCardNumber(56, 15), true, ], 'maestro48' => [ 'maestro', - $this->generateCardNum(57, 15), + $this->generateCardNumber(57, 15), true, ], 'maestro49' => [ 'maestro', - $this->generateCardNum(58, 15), + $this->generateCardNumber(58, 15), true, ], 'maestro50' => [ 'maestro', - $this->generateCardNum(59, 15), + $this->generateCardNumber(59, 15), true, ], 'maestro51' => [ 'maestro', - $this->generateCardNum(60, 15), + $this->generateCardNumber(60, 15), true, ], 'maestro52' => [ 'maestro', - $this->generateCardNum(61, 15), + $this->generateCardNumber(61, 15), true, ], 'maestro53' => [ 'maestro', - $this->generateCardNum(62, 15), + $this->generateCardNumber(62, 15), true, ], 'maestro54' => [ 'maestro', - $this->generateCardNum(63, 15), + $this->generateCardNumber(63, 15), true, ], 'maestro55' => [ 'maestro', - $this->generateCardNum(64, 15), + $this->generateCardNumber(64, 15), true, ], 'maestro56' => [ 'maestro', - $this->generateCardNum(65, 15), + $this->generateCardNumber(65, 15), true, ], 'maestro57' => [ 'maestro', - $this->generateCardNum(66, 15), + $this->generateCardNumber(66, 15), true, ], 'maestro58' => [ 'maestro', - $this->generateCardNum(67, 15), + $this->generateCardNumber(67, 15), true, ], 'maestro59' => [ 'maestro', - $this->generateCardNum(68, 15), + $this->generateCardNumber(68, 15), true, ], 'maestro60' => [ 'maestro', - $this->generateCardNum(69, 15), + $this->generateCardNumber(69, 15), true, ], 'maestro61' => [ 'maestro', - $this->generateCardNum(50, 16), + $this->generateCardNumber(50, 16), true, ], 'maestro62' => [ 'maestro', - $this->generateCardNum(56, 16), + $this->generateCardNumber(56, 16), true, ], 'maestro63' => [ 'maestro', - $this->generateCardNum(57, 16), + $this->generateCardNumber(57, 16), true, ], 'maestro64' => [ 'maestro', - $this->generateCardNum(58, 16), + $this->generateCardNumber(58, 16), true, ], 'maestro65' => [ 'maestro', - $this->generateCardNum(59, 16), + $this->generateCardNumber(59, 16), true, ], 'maestro66' => [ 'maestro', - $this->generateCardNum(60, 16), + $this->generateCardNumber(60, 16), true, ], 'maestro67' => [ 'maestro', - $this->generateCardNum(61, 16), + $this->generateCardNumber(61, 16), true, ], 'maestro68' => [ 'maestro', - $this->generateCardNum(62, 16), + $this->generateCardNumber(62, 16), true, ], 'maestro69' => [ 'maestro', - $this->generateCardNum(63, 16), + $this->generateCardNumber(63, 16), true, ], 'maestro70' => [ 'maestro', - $this->generateCardNum(64, 16), + $this->generateCardNumber(64, 16), true, ], 'maestro71' => [ 'maestro', - $this->generateCardNum(65, 16), + $this->generateCardNumber(65, 16), true, ], 'maestro72' => [ 'maestro', - $this->generateCardNum(66, 16), + $this->generateCardNumber(66, 16), true, ], 'maestro73' => [ 'maestro', - $this->generateCardNum(67, 16), + $this->generateCardNumber(67, 16), true, ], 'maestro74' => [ 'maestro', - $this->generateCardNum(68, 16), + $this->generateCardNumber(68, 16), true, ], 'maestro75' => [ 'maestro', - $this->generateCardNum(69, 16), + $this->generateCardNumber(69, 16), true, ], 'maestro91' => [ 'maestro', - $this->generateCardNum(50, 18), + $this->generateCardNumber(50, 18), true, ], 'maestro92' => [ 'maestro', - $this->generateCardNum(56, 18), + $this->generateCardNumber(56, 18), true, ], 'maestro93' => [ 'maestro', - $this->generateCardNum(57, 18), + $this->generateCardNumber(57, 18), true, ], 'maestro94' => [ 'maestro', - $this->generateCardNum(58, 18), + $this->generateCardNumber(58, 18), true, ], 'maestro95' => [ 'maestro', - $this->generateCardNum(59, 18), + $this->generateCardNumber(59, 18), true, ], 'maestro96' => [ 'maestro', - $this->generateCardNum(60, 18), + $this->generateCardNumber(60, 18), true, ], 'maestro97' => [ 'maestro', - $this->generateCardNum(61, 18), + $this->generateCardNumber(61, 18), true, ], 'maestro98' => [ 'maestro', - $this->generateCardNum(62, 18), + $this->generateCardNumber(62, 18), true, ], 'maestro99' => [ 'maestro', - $this->generateCardNum(63, 18), + $this->generateCardNumber(63, 18), true, ], 'maestro100' => [ 'maestro', - $this->generateCardNum(64, 18), + $this->generateCardNumber(64, 18), true, ], 'maestro101' => [ 'maestro', - $this->generateCardNum(65, 18), + $this->generateCardNumber(65, 18), true, ], 'maestro102' => [ 'maestro', - $this->generateCardNum(66, 18), + $this->generateCardNumber(66, 18), true, ], 'maestro103' => [ 'maestro', - $this->generateCardNum(67, 18), + $this->generateCardNumber(67, 18), true, ], 'maestro104' => [ 'maestro', - $this->generateCardNum(68, 18), + $this->generateCardNumber(68, 18), true, ], 'maestro105' => [ 'maestro', - $this->generateCardNum(69, 18), + $this->generateCardNumber(69, 18), true, ], 'maestro106' => [ 'maestro', - $this->generateCardNum(50, 19), + $this->generateCardNumber(50, 19), true, ], 'maestro107' => [ 'maestro', - $this->generateCardNum(56, 19), + $this->generateCardNumber(56, 19), true, ], 'maestro108' => [ 'maestro', - $this->generateCardNum(57, 19), + $this->generateCardNumber(57, 19), true, ], 'maestro109' => [ 'maestro', - $this->generateCardNum(58, 19), + $this->generateCardNumber(58, 19), true, ], 'maestro110' => [ 'maestro', - $this->generateCardNum(59, 19), + $this->generateCardNumber(59, 19), true, ], 'maestro111' => [ 'maestro', - $this->generateCardNum(60, 19), + $this->generateCardNumber(60, 19), true, ], 'maestro112' => [ 'maestro', - $this->generateCardNum(61, 19), + $this->generateCardNumber(61, 19), true, ], 'maestro113' => [ 'maestro', - $this->generateCardNum(62, 19), + $this->generateCardNumber(62, 19), true, ], 'maestro114' => [ 'maestro', - $this->generateCardNum(63, 19), + $this->generateCardNumber(63, 19), true, ], 'maestro115' => [ 'maestro', - $this->generateCardNum(64, 19), + $this->generateCardNumber(64, 19), true, ], 'maestro116' => [ 'maestro', - $this->generateCardNum(65, 19), + $this->generateCardNumber(65, 19), true, ], 'maestro117' => [ 'maestro', - $this->generateCardNum(66, 19), + $this->generateCardNumber(66, 19), true, ], 'maestro118' => [ 'maestro', - $this->generateCardNum(67, 19), + $this->generateCardNumber(67, 19), true, ], 'maestro119' => [ 'maestro', - $this->generateCardNum(68, 19), + $this->generateCardNumber(68, 19), true, ], 'maestro120' => [ 'maestro', - $this->generateCardNum(69, 19), + $this->generateCardNumber(69, 19), true, ], 'dankort1' => [ 'dankort', - $this->generateCardNum(5019, 16), + $this->generateCardNumber(5019, 16), true, ], 'dankort2' => [ 'dankort', - $this->generateCardNum(4175, 16), + $this->generateCardNumber(4175, 16), true, ], 'dankort3' => [ 'dankort', - $this->generateCardNum(4571, 16), + $this->generateCardNumber(4571, 16), true, ], 'dankort4' => [ 'dankort', - $this->generateCardNum(4, 16), + $this->generateCardNumber(4, 16), true, ], 'mir1' => [ 'mir', - $this->generateCardNum(2200, 16), + $this->generateCardNumber(2200, 16), true, ], 'mir2' => [ 'mir', - $this->generateCardNum(2201, 16), + $this->generateCardNumber(2201, 16), true, ], 'mir3' => [ 'mir', - $this->generateCardNum(2202, 16), + $this->generateCardNumber(2202, 16), true, ], 'mir4' => [ 'mir', - $this->generateCardNum(2203, 16), + $this->generateCardNumber(2203, 16), true, ], 'mir5' => [ 'mir', - $this->generateCardNum(2204, 16), + $this->generateCardNumber(2204, 16), true, ], 'mastercard1' => [ 'mastercard', - $this->generateCardNum(51, 16), + $this->generateCardNumber(51, 16), true, ], 'mastercard2' => [ 'mastercard', - $this->generateCardNum(52, 16), + $this->generateCardNumber(52, 16), true, ], 'mastercard3' => [ 'mastercard', - $this->generateCardNum(53, 16), + $this->generateCardNumber(53, 16), true, ], 'mastercard4' => [ 'mastercard', - $this->generateCardNum(54, 16), + $this->generateCardNumber(54, 16), true, ], 'mastercard5' => [ 'mastercard', - $this->generateCardNum(55, 16), + $this->generateCardNumber(55, 16), true, ], 'mastercard6' => [ 'mastercard', - $this->generateCardNum(22, 16), + $this->generateCardNumber(22, 16), true, ], 'mastercard7' => [ 'mastercard', - $this->generateCardNum(23, 16), + $this->generateCardNumber(23, 16), true, ], 'mastercard8' => [ 'mastercard', - $this->generateCardNum(24, 16), + $this->generateCardNumber(24, 16), true, ], 'mastercard9' => [ 'mastercard', - $this->generateCardNum(25, 16), + $this->generateCardNumber(25, 16), true, ], 'mastercard10' => [ 'mastercard', - $this->generateCardNum(26, 16), + $this->generateCardNumber(26, 16), true, ], 'mastercard11' => [ 'mastercard', - $this->generateCardNum(27, 16), + $this->generateCardNumber(27, 16), true, ], 'visa1' => [ 'visa', - $this->generateCardNum(4, 13), + $this->generateCardNumber(4, 13), true, ], 'visa2' => [ 'visa', - $this->generateCardNum(4, 16), + $this->generateCardNumber(4, 16), true, ], 'visa3' => [ 'visa', - $this->generateCardNum(4, 19), + $this->generateCardNumber(4, 19), true, ], 'uatp' => [ 'uatp', - $this->generateCardNum(1, 15), + $this->generateCardNumber(1, 15), true, ], 'verve1' => [ 'verve', - $this->generateCardNum(506, 16), + $this->generateCardNumber(506, 16), true, ], 'verve2' => [ 'verve', - $this->generateCardNum(650, 16), + $this->generateCardNumber(650, 16), true, ], 'verve3' => [ 'verve', - $this->generateCardNum(506, 19), + $this->generateCardNumber(506, 19), true, ], 'verve4' => [ 'verve', - $this->generateCardNum(650, 19), + $this->generateCardNumber(650, 19), true, ], 'cibc1' => [ 'cibc', - $this->generateCardNum(4506, 16), + $this->generateCardNumber(4506, 16), true, ], 'rbc1' => [ 'rbc', - $this->generateCardNum(45, 16), + $this->generateCardNumber(45, 16), true, ], 'tdtrust' => [ 'tdtrust', - $this->generateCardNum(589297, 16), + $this->generateCardNumber(589297, 16), true, ], 'scotia1' => [ 'scotia', - $this->generateCardNum(4536, 16), + $this->generateCardNumber(4536, 16), true, ], 'bmoabm1' => [ 'bmoabm', - $this->generateCardNum(500, 16), + $this->generateCardNumber(500, 16), true, ], 'hsbc1' => [ 'hsbc', - $this->generateCardNum(56, 16), + $this->generateCardNumber(56, 16), true, ], 'hsbc2' => [ 'hsbc', - $this->generateCardNum(57, 16), + $this->generateCardNumber(57, 16), false, ], ]; } /** - * Used to generate fake credit card numbers that will still pass the Luhn - * check used to validate the card so we can be sure the cards are recognized correctly. - * - * @return string + * Generate a fake credit card number that still passes the Luhn algorithm. */ - protected function generateCardNum(int $prefix, int $length) + private function generateCardNumber(int $prefix, int $length): string { - $pos = mb_strlen($prefix); - $finalDigit = 0; - $sum = 0; + $prefix = (string) $prefix; + $cursor = strlen($prefix); - // Fill in the first values of the string based on $prefix - $string = str_split($prefix); + $digits = str_split($prefix); + $digits = array_pad($digits, $length, '0'); - // Pad out the array to the appropriate length - $string = array_pad($string, $length, 0); - - // Fill all of the remaining values with random numbers, except the last one. - while ($pos < $length - 1) { - $string[$pos++] = random_int(0, 9); + while ($cursor < $length - 1) { + $digits[$cursor++] = (string) random_int(0, 9); } - // Calculate the Luhn checksum of the current values. - $lenOffset = ($length + 1) % 2; + $digits[$length - 1] = (string) $this->calculateLuhnChecksum($digits, $length); - for ($pos = 0; $pos < $length - 1; $pos++) { - if (($pos + $lenOffset) % 2) { - $temp = $string[$pos] * 2; - if ($temp > 9) { - $temp -= 9; - } + return implode('', $digits); + } + + private function calculateLuhnChecksum(array $digits, int $length): int + { + $parity = $length % 2; + + $sum = 0; + + for ($i = $length - 1; $i >= 0; $i--) { + $current = $digits[$i]; - $sum += $temp; - } else { - $sum += $string[$pos]; + if ($i % 2 === $parity) { + $current *= 2; + + if ($current > 9) { + $current -= 9; + } } - } - // Make the last number whatever would cause the entire number to pass the checksum - $finalDigit = (10 - ($sum % 10)) % 10; - $string[$length - 1] = $finalDigit; + $sum += $current; + } - return implode('', $string); + return ($sum * 9) % 10; } } From f2fe48f4c5c2e9bc8b6999688e6c3c62bd52e623 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 3 Nov 2021 09:50:21 +0800 Subject: [PATCH 012/407] Optimize FileRulesTest --- tests/system/Validation/FileRulesTest.php | 145 ++++++++-------------- 1 file changed, 50 insertions(+), 95 deletions(-) diff --git a/tests/system/Validation/FileRulesTest.php b/tests/system/Validation/FileRulesTest.php index e8da364367a7..8a2a111c451f 100644 --- a/tests/system/Validation/FileRulesTest.php +++ b/tests/system/Validation/FileRulesTest.php @@ -23,9 +23,9 @@ final class FileRulesTest extends CIUnitTestCase /** * @var Validation */ - protected $validation; + private $validation; - protected $config = [ + private $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -64,7 +64,7 @@ protected function setUp(): void 'name' => 'my-big-file.png', 'size' => 1024000, 'type' => 'image/png', - 'error' => 0, + 'error' => UPLOAD_ERR_OK, 'width' => 640, 'height' => 400, ], @@ -73,7 +73,7 @@ protected function setUp(): void 'name' => 'my-photo.png', 'size' => 4614, 'type' => 'image/png', - 'error' => 1, // upload_max_filesize exceeded + 'error' => UPLOAD_ERR_INI_SIZE, 'width' => 640, 'height' => 400, ], @@ -95,8 +95,8 @@ protected function setUp(): void 'image/png', ], 'error' => [ - 0, - 0, + UPLOAD_ERR_OK, + UPLOAD_ERR_OK, ], 'width' => [ 640, @@ -125,8 +125,8 @@ protected function setUp(): void 'image/png', ], 'error' => [ - 1, - 0, + UPLOAD_ERR_INI_SIZE, + UPLOAD_ERR_OK, ], 'width' => [ 640, @@ -140,149 +140,110 @@ protected function setUp(): void ]; } - public function testUploadedTrue() + public function testUploadedTrue(): void { - $this->validation->setRules([ - 'avatar' => 'uploaded[avatar]', - ]); - + $this->validation->setRules(['avatar' => 'uploaded[avatar]']); $this->assertTrue($this->validation->run([])); } - public function testUploadedFalse() + public function testUploadedFalse(): void { - $this->validation->setRules([ - 'avatar' => 'uploaded[userfile]', - ]); - + $this->validation->setRules(['avatar' => 'uploaded[userfile]']); $this->assertFalse($this->validation->run([])); } - public function testUploadedArrayReturnsTrue() + public function testUploadedArrayReturnsTrue(): void { - $this->validation->setRules([ - 'images' => 'uploaded[images]', - ]); - + $this->validation->setRules(['images' => 'uploaded[images]']); $this->assertTrue($this->validation->run([])); } - public function testUploadedArrayReturnsFalse() + public function testUploadedArrayReturnsFalse(): void { - $this->validation->setRules([ - 'photos' => 'uploaded[photos]', - ]); - + $this->validation->setRules(['photos' => 'uploaded[photos]']); $this->assertFalse($this->validation->run([])); } - public function testMaxSize() + public function testMaxSize(): void { - $this->validation->setRules([ - 'avatar' => 'max_size[avatar,100]', - ]); - + $this->validation->setRules(['avatar' => 'max_size[avatar,100]']); $this->assertTrue($this->validation->run([])); } - public function testMaxSizeBigFile() + public function testMaxSizeBigFile(): void { - $this->validation->setRules([ - 'bigfile' => 'max_size[bigfile,9999]', - ]); - + $this->validation->setRules(['bigfile' => 'max_size[bigfile,9999]']); $this->assertTrue($this->validation->run([])); } - public function testMaxSizeFail() + public function testMaxSizeFail(): void { - $this->validation->setRules([ - 'avatar' => 'max_size[avatar,4]', - ]); + $this->validation->setRules(['avatar' => 'max_size[avatar,4]']); $this->assertFalse($this->validation->run([])); } - public function testMaxSizeFailDueToUploadMaxFilesizeExceededInPhpIni() + public function testMaxSizeFailDueToUploadMaxFilesizeExceededInPhpIni(): void { - $this->validation->setRules([ - 'photo' => 'max_size[photo,100]', - ]); + $this->validation->setRules(['photo' => 'max_size[photo,100]']); $this->assertFalse($this->validation->run([])); } - public function testMaxSizeBigFileFail() + public function testMaxSizeBigFileFail(): void { - $this->validation->setRules([ - 'bigfile' => 'max_size[bigfile,10]', - ]); - + $this->validation->setRules(['bigfile' => 'max_size[bigfile,10]']); $this->assertFalse($this->validation->run([])); } - public function testMaxSizeBad() + public function testMaxSizeBad(): void { - $this->validation->setRules([ - 'avatar' => 'max_size[userfile,50]', - ]); + $this->validation->setRules(['avatar' => 'max_size[userfile,50]']); $this->assertFalse($this->validation->run([])); } - public function testMaxDims() + public function testMaxDims(): void { - $this->validation->setRules([ - 'avatar' => 'max_dims[avatar,640,480]', - ]); + $this->validation->setRules(['avatar' => 'max_dims[avatar,640,480]']); $this->assertTrue($this->validation->run([])); } - public function testMaxDimsFail() + public function testMaxDimsFail(): void { - $this->validation->setRules([ - 'avatar' => 'max_dims[avatar,600,480]', - ]); + $this->validation->setRules(['avatar' => 'max_dims[avatar,600,480]']); $this->assertFalse($this->validation->run([])); } - public function testMaxDimsBad() + public function testMaxDimsBad(): void { - $this->validation->setRules([ - 'avatar' => 'max_dims[unknown,640,480]', - ]); + $this->validation->setRules(['avatar' => 'max_dims[unknown,640,480]']); $this->assertFalse($this->validation->run([])); } - public function testIsImage() + public function testIsImage(): void { - $this->validation->setRules([ - 'avatar' => 'is_image[avatar]', - ]); + $this->validation->setRules(['avatar' => 'is_image[avatar]']); $this->assertTrue($this->validation->run([])); } - public function testIsntImage() + public function testIsntImage(): void { $_FILES['stuff'] = [ 'tmp_name' => TESTPATH . '_support/Validation/uploads/abc77tz', 'name' => 'address.book', 'size' => 12345, 'type' => 'application/address', - 'error' => 0, + 'error' => UPLOAD_ERR_OK, ]; - $this->validation->setRules([ - 'avatar' => 'is_image[stuff]', - ]); + $this->validation->setRules(['avatar' => 'is_image[stuff]']); $this->assertFalse($this->validation->run([])); } - public function testAlsoIsntImage() + public function testAlsoIsntImage(): void { - $this->validation->setRules([ - 'avatar' => 'is_image[unknown]', - ]); + $this->validation->setRules(['avatar' => 'is_image[unknown]']); $this->assertFalse($this->validation->run([])); } - public function testMimeTypeOk() + public function testMimeTypeOk(): void { $this->validation->setRules([ 'avatar' => 'mime_in[avatar,image/jpg,image/jpeg,image/gif,image/png]', @@ -290,7 +251,7 @@ public function testMimeTypeOk() $this->assertTrue($this->validation->run([])); } - public function testMimeTypeNotOk() + public function testMimeTypeNotOk(): void { $this->validation->setRules([ 'avatar' => 'mime_in[avatar,application/xls,application/doc,application/ppt]', @@ -298,7 +259,7 @@ public function testMimeTypeNotOk() $this->assertFalse($this->validation->run([])); } - public function testMimeTypeImpossible() + public function testMimeTypeImpossible(): void { $this->validation->setRules([ 'avatar' => 'mime_in[unknown,application/xls,application/doc,application/ppt]', @@ -306,27 +267,21 @@ public function testMimeTypeImpossible() $this->assertFalse($this->validation->run([])); } - public function testExtensionOk() + public function testExtensionOk(): void { - $this->validation->setRules([ - 'avatar' => 'ext_in[avatar,jpg,jpeg,gif,png]', - ]); + $this->validation->setRules(['avatar' => 'ext_in[avatar,jpg,jpeg,gif,png]']); $this->assertTrue($this->validation->run([])); } - public function testExtensionNotOk() + public function testExtensionNotOk(): void { - $this->validation->setRules([ - 'avatar' => 'ext_in[avatar,xls,doc,ppt]', - ]); + $this->validation->setRules(['avatar' => 'ext_in[avatar,xls,doc,ppt]']); $this->assertFalse($this->validation->run([])); } - public function testExtensionImpossible() + public function testExtensionImpossible(): void { - $this->validation->setRules([ - 'avatar' => 'ext_in[unknown,xls,doc,ppt]', - ]); + $this->validation->setRules(['avatar' => 'ext_in[unknown,xls,doc,ppt]']); $this->assertFalse($this->validation->run([])); } } From c592af9af25ebc74230f5ea821aaf67ebd4ee924 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 3 Nov 2021 10:21:12 +0800 Subject: [PATCH 013/407] Optimize FormatRulesTest --- tests/system/Validation/FormatRulesTest.php | 210 +++++++------------- 1 file changed, 73 insertions(+), 137 deletions(-) diff --git a/tests/system/Validation/FormatRulesTest.php b/tests/system/Validation/FormatRulesTest.php index 76e613604398..9a2e9bd46efc 100644 --- a/tests/system/Validation/FormatRulesTest.php +++ b/tests/system/Validation/FormatRulesTest.php @@ -13,6 +13,7 @@ use CodeIgniter\Test\CIUnitTestCase; use Config\Services; +use Generator; use Tests\Support\Validation\TestRules; /** @@ -26,9 +27,9 @@ final class FormatRulesTest extends CIUnitTestCase /** * @var Validation */ - protected $validation; + private $validation; - protected $config = [ + private $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -51,11 +52,9 @@ protected function setUp(): void parent::setUp(); $this->validation = new Validation((object) $this->config, Services::renderer()); $this->validation->reset(); - - $_FILES = []; } - public function testRegexMatch() + public function testRegexMatch(): void { $data = [ 'foo' => 'abcde', @@ -70,7 +69,7 @@ public function testRegexMatch() $this->assertTrue($this->validation->run($data)); } - public function testRegexMatchFalse() + public function testRegexMatchFalse(): void { $data = [ 'foo' => 'abcde', @@ -130,9 +129,9 @@ public function testValidURLStrictWithSchema() $this->assertFalse($this->validation->run($data)); } - public function urlProvider() + public function urlProvider(): Generator { - return [ + yield from [ [ 'www.codeigniter.com', true, @@ -226,11 +225,8 @@ public function urlProvider() /** * @dataProvider emailProviderSingle - * - * @param $email - * @param $expected */ - public function testValidEmail($email, $expected) + public function testValidEmail(?string $email, bool $expected): void { $data = [ 'foo' => $email, @@ -245,11 +241,8 @@ public function testValidEmail($email, $expected) /** * @dataProvider emailsProvider - * - * @param $email - * @param $expected */ - public function testValidEmails($email, $expected) + public function testValidEmails(?string $email, bool $expected): void { $data = [ 'foo' => $email, @@ -262,9 +255,9 @@ public function testValidEmails($email, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function emailProviderSingle() + public function emailProviderSingle(): Generator { - return [ + yield from [ [ 'email@sample.com', true, @@ -280,9 +273,9 @@ public function emailProviderSingle() ]; } - public function emailsProvider() + public function emailsProvider(): Generator { - return [ + yield from [ [ '1@sample.com,2@sample.com', true, @@ -312,12 +305,8 @@ public function emailsProvider() /** * @dataProvider ipProvider - * - * @param $ip - * @param $which - * @param $expected */ - public function testValidIP($ip, $which, $expected) + public function testValidIP(?string $ip, ?string $which, bool $expected): void { $data = [ 'foo' => $ip, @@ -330,9 +319,9 @@ public function testValidIP($ip, $which, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function ipProvider() + public function ipProvider(): Generator { - return [ + yield from [ [ '127.0.0.1', null, @@ -384,10 +373,9 @@ public function ipProvider() /** * @dataProvider stringProvider * - * @param $str - * @param $expected + * @param int|string $str */ - public function testString($str, $expected) + public function testString($str, bool $expected): void { $data = [ 'foo' => $str, @@ -400,9 +388,9 @@ public function testString($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function stringProvider() + public function stringProvider(): Generator { - return [ + yield from [ [ '123', true, @@ -424,7 +412,7 @@ public function stringProvider() * @param $str * @param $expected */ - public function testAlpha($str, $expected) + public function testAlpha(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -437,9 +425,9 @@ public function testAlpha($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function alphaProvider() + public function alphaProvider(): Generator { - return [ + yield from [ [ self::ALPHABET, true, @@ -464,14 +452,9 @@ public function alphaProvider() } /** - * Test alpha with spaces. - * - * @param mixed $value Value. - * @param bool $expected Expected. - * * @dataProvider alphaSpaceProvider */ - public function testAlphaSpace($value, $expected) + public function testAlphaSpace(?string $value, bool $expected): void { $data = [ 'foo' => $value, @@ -484,9 +467,9 @@ public function testAlphaSpace($value, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function alphaSpaceProvider() + public function alphaSpaceProvider(): Generator { - return [ + yield from [ [ null, true, @@ -516,11 +499,8 @@ public function alphaSpaceProvider() /** * @dataProvider alphaNumericProvider - * - * @param $str - * @param $expected */ - public function testAlphaNumeric($str, $expected) + public function testAlphaNumeric(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -533,9 +513,9 @@ public function testAlphaNumeric($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function alphaNumericProvider() + public function alphaNumericProvider(): Generator { - return [ + yield from [ [ self::ALPHANUMERIC, true, @@ -557,11 +537,8 @@ public function alphaNumericProvider() /** * @dataProvider alphaNumericPunctProvider - * - * @param $str - * @param $expected */ - public function testAlphaNumericPunct($str, $expected) + public function testAlphaNumericPunct(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -574,9 +551,9 @@ public function testAlphaNumericPunct($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function alphaNumericPunctProvider() + public function alphaNumericPunctProvider(): Generator { - return [ + yield from [ [ self::ALPHANUMERIC . ' ~!#$%&*-_+=|:.', true, @@ -654,11 +631,8 @@ public function alphaNumericPunctProvider() /** * @dataProvider alphaNumericProvider - * - * @param $str - * @param $expected */ - public function testAlphaNumericSpace($str, $expected) + public function testAlphaNumericSpace(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -671,9 +645,9 @@ public function testAlphaNumericSpace($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function alphaNumericSpaceProvider() + public function alphaNumericSpaceProvider(): Generator { - return [ + yield from [ [ ' ' . self::ALPHANUMERIC, true, @@ -695,11 +669,8 @@ public function alphaNumericSpaceProvider() /** * @dataProvider alphaDashProvider - * - * @param $str - * @param $expected */ - public function testAlphaDash($str, $expected) + public function testAlphaDash(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -712,9 +683,9 @@ public function testAlphaDash($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function alphaDashProvider() + public function alphaDashProvider(): Generator { - return [ + yield from [ [ self::ALPHANUMERIC . '-', true, @@ -736,11 +707,8 @@ public function alphaDashProvider() /** * @dataProvider hexProvider - * - * @param $str - * @param $expected */ - public function testHex($str, $expected) + public function testHex(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -753,9 +721,9 @@ public function testHex($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function hexProvider() + public function hexProvider(): Generator { - return [ + yield from [ [ 'abcdefABCDEF0123456789', true, @@ -777,11 +745,8 @@ public function hexProvider() /** * @dataProvider numericProvider - * - * @param $str - * @param $expected */ - public function testNumeric($str, $expected) + public function testNumeric(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -794,9 +759,9 @@ public function testNumeric($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function numericProvider() + public function numericProvider(): Generator { - return [ + yield from [ [ '0', true, @@ -834,11 +799,8 @@ public function numericProvider() /** * @dataProvider integerProvider - * - * @param $str - * @param $expected */ - public function testInteger($str, $expected) + public function testInteger(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -851,9 +813,9 @@ public function testInteger($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function integerProvider() + public function integerProvider(): Generator { - return [ + yield from [ [ '0', true, @@ -891,11 +853,8 @@ public function integerProvider() /** * @dataProvider decimalProvider - * - * @param $str - * @param $expected */ - public function testDecimal($str, $expected) + public function testDecimal(?string $str, bool $expected): void { $data = [ 'foo' => $str, @@ -908,9 +867,9 @@ public function testDecimal($str, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function decimalProvider() + public function decimalProvider(): Generator { - return [ + yield from [ [ '1.0', true, @@ -952,15 +911,11 @@ public function decimalProvider() /** * @dataProvider naturalProvider - * - * @param $str - * @param $expected - * @param mixed $first */ - public function testNatural($first, $expected) + public function testNatural(?string $str, bool $expected): void { $data = [ - 'foo' => $first, + 'foo' => $str, ]; $this->validation->setRules([ @@ -970,9 +925,9 @@ public function testNatural($first, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function naturalProvider() + public function naturalProvider(): Generator { - return [ + yield from [ [ '0', true, @@ -998,15 +953,11 @@ public function naturalProvider() /** * @dataProvider naturalZeroProvider - * - * @param $str - * @param $expected - * @param mixed $first */ - public function testNaturalNoZero($first, $expected) + public function testNaturalNoZero(?string $str, bool $expected): void { $data = [ - 'foo' => $first, + 'foo' => $str, ]; $this->validation->setRules([ @@ -1016,9 +967,9 @@ public function testNaturalNoZero($first, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function naturalZeroProvider() + public function naturalZeroProvider(): Generator { - return [ + yield from [ [ '0', false, @@ -1044,15 +995,11 @@ public function naturalZeroProvider() /** * @dataProvider base64Provider - * - * @param $str - * @param $expected - * @param mixed $first */ - public function testBase64($first, $expected) + public function testBase64(?string $str, bool $expected): void { $data = [ - 'foo' => $first, + 'foo' => $str, ]; $this->validation->setRules([ @@ -1062,9 +1009,9 @@ public function testBase64($first, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function base64Provider() + public function base64Provider(): Generator { - return [ + yield from [ [ base64_encode('string'), true, @@ -1082,15 +1029,11 @@ public function base64Provider() /** * @dataProvider jsonProvider - * - * @param $str - * @param $expected - * @param mixed $first */ - public function testJson($first, $expected) + public function testJson(?string $str, bool $expected): void { $data = [ - 'foo' => $first, + 'foo' => $str, ]; $this->validation->setRules([ @@ -1100,9 +1043,9 @@ public function testJson($first, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function jsonProvider() + public function jsonProvider(): Generator { - return [ + yield from [ [ 'null', true, @@ -1144,14 +1087,11 @@ public function jsonProvider() /** * @dataProvider timezoneProvider - * - * @param $value - * @param $expected */ - public function testTimeZone($value, $expected) + public function testTimeZone(?string $str, bool $expected): void { $data = [ - 'foo' => $value, + 'foo' => $str, ]; $this->validation->setRules([ @@ -1161,9 +1101,9 @@ public function testTimeZone($value, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function timezoneProvider() + public function timezoneProvider(): Generator { - return [ + yield from [ [ 'America/Chicago', true, @@ -1185,12 +1125,8 @@ public function timezoneProvider() /** * @dataProvider validDateProvider - * - * @param $str - * @param $format - * @param $expected */ - public function testValidDate($str, $format, $expected) + public function testValidDate(?string $str, ?string $format, bool $expected): void { $data = [ 'foo' => $str, @@ -1203,9 +1139,9 @@ public function testValidDate($str, $format, $expected) $this->assertSame($expected, $this->validation->run($data)); } - public function validDateProvider() + public function validDateProvider(): Generator { - return [ + yield from [ [ 'Sun', 'D', From 306a2389b2f1a2ea2b947aa8ca94d88fcdf03453 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 3 Nov 2021 20:20:24 +0800 Subject: [PATCH 014/407] Move live database related rules into own file --- .../Validation/DatabaseRelatedRulesTest.php | 221 ++++++++++++++++ tests/system/Validation/RulesTest.php | 240 ------------------ 2 files changed, 221 insertions(+), 240 deletions(-) create mode 100644 tests/system/Validation/DatabaseRelatedRulesTest.php diff --git a/tests/system/Validation/DatabaseRelatedRulesTest.php b/tests/system/Validation/DatabaseRelatedRulesTest.php new file mode 100644 index 000000000000..2968c9c1e207 --- /dev/null +++ b/tests/system/Validation/DatabaseRelatedRulesTest.php @@ -0,0 +1,221 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Validation; + +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\DatabaseTestTrait; +use Config\Database; +use Config\Services; +use Tests\Support\Validation\TestRules; + +/** + * @internal + * + * @group DatabaseLive + */ +final class DatabaseRelatedRulesTest extends CIUnitTestCase +{ + use DatabaseTestTrait; + + /** + * @var Validation + */ + private $validation; + + private $config = [ + 'ruleSets' => [ + Rules::class, + FormatRules::class, + FileRules::class, + CreditCardRules::class, + TestRules::class, + ], + 'groupA' => [ + 'foo' => 'required|min_length[5]', + ], + 'groupA_errors' => [ + 'foo' => [ + 'min_length' => 'Shame, shame. Too short.', + ], + ], + ]; + + protected function setUp(): void + { + parent::setUp(); + $this->validation = new Validation((object) $this->config, Services::renderer()); + $this->validation->reset(); + } + + public function testIsUniqueFalse(): void + { + Database::connect() + ->table('user') + ->insert([ + 'name' => 'Derek Travis', + 'email' => 'derek@world.com', + 'country' => 'Elbonia', + ]); + + $data = ['email' => 'derek@world.com']; + $this->validation->setRules(['email' => 'is_unique[user.email]']); + $this->assertFalse($this->validation->run($data)); + } + + public function testIsUniqueTrue(): void + { + $data = ['email' => 'derek@world.co.uk']; + $this->validation->setRules(['email' => 'is_unique[user.email]']); + $this->assertTrue($this->validation->run($data)); + } + + public function testIsUniqueIgnoresParams(): void + { + $db = Database::connect(); + $db + ->table('user') + ->insert([ + 'name' => 'Developer A', + 'email' => 'deva@example.com', + 'country' => 'Elbonia', + ]); + $row = $db->table('user') + ->limit(1) + ->get() + ->getRow(); + + $data = ['email' => 'derek@world.co.uk']; + $this->validation->setRules(['email' => "is_unique[user.email,id,{$row->id}]"]); + $this->assertTrue($this->validation->run($data)); + } + + public function testIsUniqueIgnoresParamsPlaceholders(): void + { + $this->hasInDatabase('user', [ + 'name' => 'Derek', + 'email' => 'derek@world.co.uk', + 'country' => 'GB', + ]); + + $row = Database::connect() + ->table('user') + ->limit(1) + ->get() + ->getRow(); + + $data = [ + 'id' => $row->id, + 'email' => 'derek@world.co.uk', + ]; + + $this->validation->setRules(['email' => 'is_unique[user.email,id,{id}]']); + $this->assertTrue($this->validation->run($data)); + } + + public function testIsUniqueByManualRun(): void + { + Database::connect() + ->table('user') + ->insert([ + 'name' => 'Developer A', + 'email' => 'deva@example.com', + 'country' => 'Elbonia', + ]); + + $this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', [])); + } + + public function testIsNotUniqueFalse(): void + { + Database::connect() + ->table('user') + ->insert([ + 'name' => 'Derek Travis', + 'email' => 'derek@world.com', + 'country' => 'Elbonia', + ]); + + $data = ['email' => 'derek1@world.com']; + $this->validation->setRules(['email' => 'is_not_unique[user.email]']); + $this->assertFalse($this->validation->run($data)); + } + + public function testIsNotUniqueTrue(): void + { + Database::connect() + ->table('user') + ->insert([ + 'name' => 'Derek Travis', + 'email' => 'derek@world.com', + 'country' => 'Elbonia', + ]); + + $data = ['email' => 'derek@world.com']; + $this->validation->setRules(['email' => 'is_not_unique[user.email]']); + $this->assertTrue($this->validation->run($data)); + } + + public function testIsNotUniqueIgnoresParams(): void + { + $db = Database::connect(); + $db->table('user') + ->insert([ + 'name' => 'Developer A', + 'email' => 'deva@example.com', + 'country' => 'Elbonia', + ]); + + $row = $db->table('user') + ->limit(1) + ->get() + ->getRow(); + + $data = ['email' => 'derek@world.co.uk']; + $this->validation->setRules(['email' => "is_not_unique[user.email,id,{$row->id}]"]); + $this->assertFalse($this->validation->run($data)); + } + + public function testIsNotUniqueIgnoresParamsPlaceholders(): void + { + $this->hasInDatabase('user', [ + 'name' => 'Derek', + 'email' => 'derek@world.co.uk', + 'country' => 'GB', + ]); + + $row = Database::connect() + ->table('user') + ->limit(1) + ->get() + ->getRow(); + + $data = [ + 'id' => $row->id, + 'email' => 'derek@world.co.uk', + ]; + $this->validation->setRules(['email' => 'is_not_unique[user.email,id,{id}]']); + $this->assertTrue($this->validation->run($data)); + } + + public function testIsNotUniqueByManualRun(): void + { + Database::connect() + ->table('user') + ->insert([ + 'name' => 'Developer A', + 'email' => 'deva@example.com', + 'country' => 'Elbonia', + ]); + + $this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); + } +} diff --git a/tests/system/Validation/RulesTest.php b/tests/system/Validation/RulesTest.php index 7fe8469fcbeb..51d57bc3b109 100644 --- a/tests/system/Validation/RulesTest.php +++ b/tests/system/Validation/RulesTest.php @@ -12,8 +12,6 @@ namespace CodeIgniter\Validation; use CodeIgniter\Test\CIUnitTestCase; -use CodeIgniter\Test\DatabaseTestTrait; -use Config\Database; use Config\Services; use stdClass; use Tests\Support\Validation\TestRules; @@ -23,10 +21,6 @@ */ final class RulesTest extends CIUnitTestCase { - use DatabaseTestTrait; - - protected $refresh = true; - /** * @var Validation */ @@ -633,240 +627,6 @@ public function testNotEqualsReturnsTrueOnCaseMismatch() $this->assertTrue($this->validation->run($data)); } - /** - * @group DatabaseLive - */ - public function testIsUniqueFalse() - { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = [ - 'email' => 'derek@world.com', - ]; - - $this->validation->setRules([ - 'email' => 'is_unique[user.email]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsUniqueTrue() - { - $data = [ - 'email' => 'derek@world.co.uk', - ]; - - $this->validation->setRules([ - 'email' => 'is_unique[user.email]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsUniqueIgnoresParams() - { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'email' => 'derek@world.co.uk', - ]; - - $this->validation->setRules([ - 'email' => "is_unique[user.email,id,{$row->id}]", - ]); - - $this->assertTrue($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsUniqueIgnoresParamsPlaceholders() - { - $this->hasInDatabase('user', [ - 'name' => 'Derek', - 'email' => 'derek@world.co.uk', - 'country' => 'GB', - ]); - - $db = Database::connect(); - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'id' => $row->id, - 'email' => 'derek@world.co.uk', - ]; - - $this->validation->setRules([ - 'email' => 'is_unique[user.email,id,{id}]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsUniqueByManualRun() - { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', [])); - } - - /** - * @group DatabaseLive - */ - public function testIsNotUniqueFalse() - { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = [ - 'email' => 'derek1@world.com', - ]; - - $this->validation->setRules([ - 'email' => 'is_not_unique[user.email]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsNotUniqueTrue() - { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = [ - 'email' => 'derek@world.com', - ]; - - $this->validation->setRules([ - 'email' => 'is_not_unique[user.email]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsNotUniqueIgnoresParams() - { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'email' => 'derek@world.co.uk', - ]; - - $this->validation->setRules([ - 'email' => "is_not_unique[user.email,id,{$row->id}]", - ]); - - $this->assertFalse($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsNotUniqueIgnoresParamsPlaceholders() - { - $this->hasInDatabase('user', [ - 'name' => 'Derek', - 'email' => 'derek@world.co.uk', - 'country' => 'GB', - ]); - - $db = Database::connect(); - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'id' => $row->id, - 'email' => 'derek@world.co.uk', - ]; - - $this->validation->setRules([ - 'email' => 'is_not_unique[user.email,id,{id}]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - /** - * @group DatabaseLive - */ - public function testIsNotUniqueByManualRun() - { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); - } - public function testMinLengthNull() { $data = [ From ec958f9ce8432d69d7e61aec41cf8ba41b102a48 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 3 Nov 2021 20:40:10 +0800 Subject: [PATCH 015/407] Optimize RulesTest --- tests/system/Validation/RulesTest.php | 1088 +++++-------------------- 1 file changed, 198 insertions(+), 890 deletions(-) diff --git a/tests/system/Validation/RulesTest.php b/tests/system/Validation/RulesTest.php index 51d57bc3b109..3b3ddc11987a 100644 --- a/tests/system/Validation/RulesTest.php +++ b/tests/system/Validation/RulesTest.php @@ -13,6 +13,7 @@ use CodeIgniter\Test\CIUnitTestCase; use Config\Services; +use Generator; use stdClass; use Tests\Support\Validation\TestRules; @@ -24,9 +25,9 @@ final class RulesTest extends CIUnitTestCase /** * @var Validation */ - protected $validation; + private $validation; - protected $config = [ + private $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -47,111 +48,43 @@ final class RulesTest extends CIUnitTestCase protected function setUp(): void { parent::setUp(); - $this->validation = new Validation((object) $this->config, Services::renderer()); $this->validation->reset(); - - $_FILES = []; } - // Rules Tests - - public function testRequiredNull() - { - $data = [ - 'foo' => null, - ]; - - $this->validation->setRules([ - 'foo' => 'required|alpha', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testRequiredTrueString() - { - $data = [ - 'foo' => 123, - ]; - - $this->validation->setRules([ - 'foo' => 'required', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testRequiredFalseString() - { - $data = [ - 'foo' => null, - 'bar' => 123, - ]; - - $this->validation->setRules([ - 'foo' => 'required', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testRequiredTrueArray() - { - $data = [ - 'foo' => [123], - ]; - - $this->validation->setRules([ - 'foo' => 'required', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testRequiredFalseArray() + /** + * @dataProvider provideRequiredCases + */ + public function testRequired(array $data, bool $expected): void { - $data = [ - 'foo' => [], - ]; - - $this->validation->setRules([ - 'foo' => 'required', - ]); - - $this->assertFalse($this->validation->run($data)); + $this->validation->setRules(['foo' => 'required']); + $this->assertSame($expected, $this->validation->run($data)); } - public function testRequiredObject() + public function provideRequiredCases(): Generator { - $data = [ - 'foo' => new stdClass(), + yield from [ + [['foo' => null], false], + [['foo' => 123], true], + [['foo' => null, 'bar' => 123], false], + [['foo' => [123]], true], + [['foo' => []], false], + [['foo' => new stdClass()], true], ]; - - $this->validation->setRules([ - 'foo' => 'required', - ]); - - $this->assertTrue($this->validation->run($data)); } /** * @dataProvider ifExistProvider - * - * @param $rules - * @param $data - * @param $expected */ - public function testIfExist($rules, $data, $expected) + public function testIfExist(array $rules, array $data, bool $expected): void { $this->validation->setRules($rules); - $this->assertSame($expected, $this->validation->run($data)); } - public function ifExistProvider() + public function ifExistProvider(): Generator { - return [ + yield from [ [ ['foo' => 'required'], ['foo' => ''], @@ -188,22 +121,17 @@ public function ifExistProvider() } /** - * @dataProvider emptysProvider - * - * @param $rules - * @param $data - * @param $expected + * @dataProvider providePermitEmptyCases */ - public function testEmptys($rules, $data, $expected) + public function testPermitEmpty(array $rules, array $data, bool $expected): void { $this->validation->setRules($rules); - $this->assertSame($expected, $this->validation->run($data)); } - public function emptysProvider() + public function providePermitEmptyCases(): Generator { - return [ + yield from [ [ ['foo' => 'permit_empty'], ['foo' => ''], @@ -297,23 +225,13 @@ public function emptysProvider() true, ], [ - [ - 'foo' => 'permit_empty|required_with[bar]', - ], - [ - 'foo' => 0.0, - 'bar' => 1, - ], + ['foo' => 'permit_empty|required_with[bar]'], + ['foo' => 0.0, 'bar' => 1], true, ], [ - [ - 'foo' => 'permit_empty|required_with[bar]', - ], - [ - 'foo' => '', - 'bar' => 1, - ], + ['foo' => 'permit_empty|required_with[bar]'], + ['foo' => '', 'bar' => 1], false, ], [ @@ -327,837 +245,281 @@ public function emptysProvider() true, ], [ - [ - 'foo' => 'permit_empty|required_without[bar]', - ], - [ - 'foo' => 0.0, - 'bar' => 1, - ], + ['foo' => 'permit_empty|required_without[bar]'], + ['foo' => 0.0, 'bar' => 1], true, ], [ - [ - 'foo' => 'permit_empty|required_without[bar]', - ], - [ - 'foo' => '', - 'bar' => 1, - ], + ['foo' => 'permit_empty|required_without[bar]'], + ['foo' => '', 'bar' => 1], true, ], ]; } - public function testMatchesNull() - { - $data = [ - 'foo' => null, - 'bar' => null, - ]; - - $this->validation->setRules([ - 'foo' => 'matches[bar]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testMatchesTrue() - { - $data = [ - 'foo' => 'match', - 'bar' => 'match', - ]; - - $this->validation->setRules([ - 'foo' => 'matches[bar]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testMatchesFalse() - { - $data = [ - 'foo' => 'match', - 'bar' => 'nope', - ]; - - $this->validation->setRules([ - 'foo' => 'matches[bar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testMatcheNestedsTrue() - { - $data = [ - 'nested' => [ - 'foo' => 'match', - 'bar' => 'match', - ], - ]; - - $this->validation->setRules([ - 'nested.foo' => 'matches[nested.bar]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testMatchesNestedFalse() - { - $data = [ - 'nested' => [ - 'foo' => 'match', - 'bar' => 'nope', - ], - ]; - - $this->validation->setRules([ - 'nested.foo' => 'matches[nested.bar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testDiffersNull() - { - $data = [ - 'foo' => null, - 'bar' => null, - ]; - - $this->validation->setRules([ - 'foo' => 'differs[bar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testDiffersTrue() - { - $data = [ - 'foo' => 'match', - 'bar' => 'nope', - ]; - - $this->validation->setRules([ - 'foo' => 'differs[bar]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testDiffersFalse() - { - $data = [ - 'foo' => 'match', - 'bar' => 'match', - ]; - - $this->validation->setRules([ - 'foo' => 'differs[bar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testDiffersNestedTrue() - { - $data = [ - 'nested' => [ - 'foo' => 'match', - 'bar' => 'nope', - ], - ]; - - $this->validation->setRules([ - 'nested.foo' => 'differs[nested.bar]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testDiffersNestedFalse() - { - $data = [ - 'nested' => [ - 'foo' => 'match', - 'bar' => 'match', - ], - ]; - - $this->validation->setRules([ - 'nested.foo' => 'differs[nested.bar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testEqualsNull() - { - $data = [ - 'foo' => null, - ]; - - $this->validation->setRules([ - 'foo' => 'equals[]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testEqualsEmptyIsEmpty() - { - $data = [ - 'foo' => '', - ]; - - $this->validation->setRules([ - 'foo' => 'equals[]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testEqualsReturnsFalseOnFailure() - { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'equals[notbar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testEqualsReturnsTrueOnSuccess() - { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'equals[bar]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testEqualsReturnsFalseOnCaseMismatch() - { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'equals[Bar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testNotEqualsNull() - { - $data = [ - 'foo' => null, - ]; - - $this->validation->setRules([ - 'foo' => 'not_equals[]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testNotEqualsEmptyIsEmpty() - { - $data = [ - 'foo' => '', - ]; - - $this->validation->setRules([ - 'foo' => 'not_equals[]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testNotEqualsReturnsFalseOnFailure() - { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'not_equals[bar]', - ]); - - $this->assertFalse($this->validation->run($data)); - } - - public function testNotEqualsReturnsTrueOnSuccess() - { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'not_equals[notbar]', - ]); - - $this->assertTrue($this->validation->run($data)); - } - - public function testNotEqualsReturnsTrueOnCaseMismatch() + /** + * @dataProvider provideMatchesCases + */ + public function testMatches(array $data, bool $expected): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'not_equals[Bar]', - ]); - - $this->assertTrue($this->validation->run($data)); + $this->validation->setRules(['foo' => 'matches[bar]']); + $this->assertSame($expected, $this->validation->run($data)); } - public function testMinLengthNull() + public function provideMatchesCases(): Generator { - $data = [ - 'foo' => null, + yield from [ + [['foo' => null, 'bar' => null], true], + [['foo' => 'match', 'bar' => 'match'], true], + [['foo' => 'match', 'bar' => 'nope'], false], ]; - - $this->validation->setRules([ - 'foo' => 'min_length[3]', - ]); - - $this->assertFalse($this->validation->run($data)); } - public function testMinLengthReturnsTrueWithSuccess() + /** + * @dataProvider provideMatchesNestedCases + */ + public function testMatchesNested(array $data, bool $expected): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'min_length[2]', - ]); - - $this->assertTrue($this->validation->run($data)); + $this->validation->setRules(['nested.foo' => 'matches[nested.bar]']); + $this->assertSame($expected, $this->validation->run($data)); } - public function testMinLengthReturnsTrueWithExactLength() + public function provideMatchesNestedCases(): Generator { - $data = [ - 'foo' => 'bar', + yield from [ + [['nested' => ['foo' => 'match', 'bar' => 'match']], true], + [['nested' => ['foo' => 'match', 'bar' => 'nope']], false], ]; - - $this->validation->setRules([ - 'foo' => 'min_length[3]', - ]); - - $this->assertTrue($this->validation->run($data)); } - public function testMinLengthReturnsFalseWhenWrong() + /** + * @dataProvider provideMatchesCases + */ + public function testDiffers(array $data, bool $expected): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'min_length[4]', - ]); - - $this->assertFalse($this->validation->run($data)); + $this->validation->setRules(['foo' => 'differs[bar]']); + $this->assertSame(! $expected, $this->validation->run($data)); } - public function testMaxLengthNull() + /** + * @dataProvider provideMatchesNestedCases + */ + public function testDiffersNested(array $data, bool $expected): void { - $data = [ - 'foo' => null, - ]; - - $this->validation->setRules([ - 'foo' => 'max_length[1]', - ]); - - $this->assertTrue($this->validation->run($data)); + $this->validation->setRules(['nested.foo' => 'differs[nested.bar]']); + $this->assertSame(! $expected, $this->validation->run($data)); } - public function testMaxLengthReturnsFalseWithNonNumericVal() + /** + * @dataProvider provideEqualsCases + */ + public function testEquals(array $data, string $param, bool $expected): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'max_length[bar]', - ]); - - $this->assertFalse($this->validation->run($data)); + $this->validation->setRules(['foo' => "equals[{$param}]"]); + $this->assertSame($expected, $this->validation->run($data)); } - public function testMaxLengthReturnsTrueWithSuccess() + public function provideEqualsCases(): Generator { - $data = [ - 'foo' => 'bar', + yield from [ + 'null' => [['foo' => null], '', false], + 'empty' => [['foo' => ''], '', true], + 'fail' => [['foo' => 'bar'], 'notbar', false], + 'pass' => [['foo' => 'bar'], 'bar', true], + 'casing' => [['foo' => 'bar'], 'Bar', false], ]; - - $this->validation->setRules([ - 'foo' => 'max_length[4]', - ]); - - $this->assertTrue($this->validation->run($data)); } - public function testMaxLengthReturnsTrueWithExactLength() + /** + * @dataProvider provideMinLengthCases + */ + public function testMinLength(?string $data, string $length, bool $expected): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'max_length[3]', - ]); - - $this->assertTrue($this->validation->run($data)); + $this->validation->setRules(['foo' => "min_length[{$length}]"]); + $this->assertSame($expected, $this->validation->run(['foo' => $data])); } - public function testMaxLengthReturnsFalseWhenWrong() + public function provideMinLengthCases(): Generator { - $data = [ - 'foo' => 'bar', + yield from [ + 'null' => [null, '2', false], + 'less' => ['bar', '2', true], + 'equal' => ['bar', '3', true], + 'greater' => ['bar', '4', false], ]; - - $this->validation->setRules([ - 'foo' => 'max_length[2]', - ]); - - $this->assertFalse($this->validation->run($data)); } - public function testExactLengthNull() + /** + * @dataProvider provideMinLengthCases + */ + public function testMaxLength(?string $data, string $length, bool $expected): void { - $data = [ - 'foo' => null, - ]; - - $this->validation->setRules([ - 'foo' => 'exact_length[3]', - ]); - - $this->assertFalse($this->validation->run($data)); + $this->validation->setRules(['foo' => "max_length[{$length}]"]); + $this->assertSame(! $expected || $length === '3', $this->validation->run(['foo' => $data])); } - public function testExactLengthReturnsTrueOnSuccess() + public function testMaxLengthReturnsFalseWithNonNumericVal(): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'exact_length[3]', - ]); - - $this->assertTrue($this->validation->run($data)); + $this->validation->setRules(['foo' => 'max_length[bar]']); + $this->assertFalse($this->validation->run(['foo' => 'bar'])); } - public function testExactLengthDetectsBadLength() + /** + * @dataProvider provideExactLengthCases + */ + public function testExactLength(?string $data, bool $expected): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'exact_length[abc]', - ]); - - $this->assertFalse($this->validation->run($data)); + $this->validation->setRules(['foo' => 'exact_length[3]']); + $this->assertSame($expected, $this->validation->run(['foo' => $data])); } - public function testExactLengthReturnsFalseWhenShort() + public function provideExactLengthCases(): Generator { - $data = [ - 'foo' => 'bar', + yield from [ + 'null' => [null, false], + 'exact' => ['bar', true], + 'less' => ['ba', false], + 'greater' => ['bars', false], ]; - - $this->validation->setRules([ - 'foo' => 'exact_length[2]', - ]); - - $this->assertFalse($this->validation->run($data)); } - public function testExactLengthReturnsFalseWhenLong() + public function testExactLengthDetectsBadLength(): void { - $data = [ - 'foo' => 'bar', - ]; - - $this->validation->setRules([ - 'foo' => 'exact_length[4]', - ]); - + $data = ['foo' => 'bar']; + $this->validation->setRules(['foo' => 'exact_length[abc]']); $this->assertFalse($this->validation->run($data)); } /** * @dataProvider greaterThanProvider - * - * @param $str - * @param $expected - * @param mixed $first - * @param mixed $second */ - public function testGreaterThan($first, $second, $expected) + public function testGreaterThan(?string $first, ?string $second, bool $expected): void { - $data = [ - 'foo' => $first, - ]; - - $this->validation->setRules([ - 'foo' => "greater_than[{$second}]", - ]); - + $data = ['foo' => $first]; + $this->validation->setRules(['foo' => "greater_than[{$second}]"]); $this->assertSame($expected, $this->validation->run($data)); } - public function greaterThanProvider() + public function greaterThanProvider(): Generator { - return [ - [ - '-10', - '-11', - true, - ], - [ - '10', - '9', - true, - ], - [ - '10', - '10', - false, - ], - [ - '10', - 'a', - false, - ], - [ - '10a', - '10', - false, - ], - [ - null, - null, - false, - ], + yield from [ + ['-10', '-11', true], + ['10', '9', true], + ['10', '10', false], + ['10', 'a', false], + ['10a', '10', false], + [null, null, false], ]; } /** * @dataProvider greaterThanEqualProvider - * - * @param $str - * @param $expected - * @param mixed $first - * @param mixed $second */ - public function testGreaterThanEqual($first, $second, $expected) + public function testGreaterThanEqual(?string $first, ?string $second, bool $expected): void { - $data = [ - 'foo' => $first, - ]; - - $this->validation->setRules([ - 'foo' => "greater_than_equal_to[{$second}]", - ]); - + $data = ['foo' => $first]; + $this->validation->setRules(['foo' => "greater_than_equal_to[{$second}]"]); $this->assertSame($expected, $this->validation->run($data)); } - public function greaterThanEqualProvider() + public function greaterThanEqualProvider(): Generator { - return [ - [ - '0', - '0', - true, - ], - [ - '1', - '0', - true, - ], - [ - '-1', - '0', - false, - ], - [ - '10a', - '0', - false, - ], - [ - null, - null, - false, - ], - [ - 1, - null, - true, - ], - [ - null, - 1, - false, - ], + yield from [ + ['0', '0', true], + ['1', '0', true], + ['-1', '0', false], + ['10a', '0', false], + [null, null, false], + ['1', null, true], + [null, '1', false], ]; } /** * @dataProvider lessThanProvider - * - * @param $str - * @param $expected - * @param mixed $first - * @param mixed $second */ - public function testLessThan($first, $second, $expected) + public function testLessThan(?string $first, ?string $second, bool $expected): void { - $data = [ - 'foo' => $first, - ]; - - $this->validation->setRules([ - 'foo' => "less_than[{$second}]", - ]); - + $data = ['foo' => $first]; + $this->validation->setRules(['foo' => "less_than[{$second}]"]); $this->assertSame($expected, $this->validation->run($data)); } - public function lessThanProvider() + public function lessThanProvider(): Generator { - return [ - [ - '4', - '5', - true, - ], - [ - '-1', - '0', - true, - ], - [ - '4', - '4', - false, - ], - [ - '10a', - '5', - false, - ], - [ - null, - null, - false, - ], - [ - 1, - null, - false, - ], - [ - null, - 1, - false, - ], + yield from [ + ['-10', '-11', false], + ['9', '10', true], + ['10', '9', false], + ['10', '10', false], + ['10', 'a', true], + ['10a', '10', false], + [null, null, false], ]; } /** * @dataProvider lessThanEqualProvider - * - * @param $str - * @param $expected - * @param mixed $first - * @param mixed $second */ - public function testLessEqualThan($first, $second, $expected) + public function testLessEqualThan(?string $first, ?string $second, bool $expected): void { - $data = [ - 'foo' => $first, - ]; - - $this->validation->setRules([ - 'foo' => "less_than_equal_to[{$second}]", - ]); - + $data = ['foo' => $first]; + $this->validation->setRules(['foo' => "less_than_equal_to[{$second}]"]); $this->assertSame($expected, $this->validation->run($data)); } - public function lessThanEqualProvider() + public function lessThanEqualProvider(): Generator { - return [ - [ - '-1', - '0', - true, - ], - [ - '-1', - '-1', - true, - ], - [ - '4', - '4', - true, - ], - [ - '0', - '-1', - false, - ], - [ - '10a', - '0', - false, - ], - [ - null, - null, - false, - ], - [ - null, - 1, - false, - ], - [ - 1, - null, - false, - ], + yield from [ + ['0', '0', true], + ['1', '0', false], + ['-1', '0', true], + ['10a', '0', false], + [null, null, false], + ['1', null, false], + [null, '1', false], ]; } /** * @dataProvider inListProvider - * - * @param string $first - * @param string $second - * @param bool $expected */ - public function testInList($first, $second, $expected) + public function testInList(?string $first, ?string $second, bool $expected): void { - $data = [ - 'foo' => $first, - ]; - - $this->validation->setRules([ - 'foo' => "in_list[{$second}]", - ]); - + $data = ['foo' => $first]; + $this->validation->setRules(['foo' => "in_list[{$second}]"]); $this->assertSame($expected, $this->validation->run($data)); } /** * @dataProvider inListProvider - * - * @param string $first - * @param string $second - * @param bool $expected */ - public function testNotInList($first, $second, $expected) + public function testNotInList(?string $first, ?string $second, bool $expected): void { - $expected = ! $expected; - - $data = [ - 'foo' => $first, - ]; - - $this->validation->setRules([ - 'foo' => "not_in_list[{$second}]", - ]); - - $this->assertSame($expected, $this->validation->run($data)); + $data = ['foo' => $first]; + $this->validation->setRules(['foo' => "not_in_list[{$second}]"]); + $this->assertSame(! $expected, $this->validation->run($data)); } - public function inListProvider() + public function inListProvider(): Generator { - return [ - [ - 'red', - 'red,Blue,123', - true, - ], - [ - 'Blue', - 'red, Blue,123', - true, - ], - [ - 'Blue', - 'red,Blue,123', - true, - ], - [ - '123', - 'red,Blue,123', - true, - ], - [ - 'Red', - 'red,Blue,123', - false, - ], - [ - ' red', - 'red,Blue,123', - false, - ], - [ - '1234', - 'red,Blue,123', - false, - ], - [ - null, - 'red,Blue,123', - false, - ], - [ - 'red', - null, - false, - ], + yield from [ + ['red', 'red,Blue,123', true], + ['Blue', 'red, Blue,123', true], + ['Blue', 'red,Blue,123', true], + ['123', 'red,Blue,123', true], + ['Red', 'red,Blue,123', false], + [' red', 'red,Blue,123', false], + ['1234', 'red,Blue,123', false], + [null, 'red,Blue,123', false], + ['red', null, false], ]; } /** * @dataProvider requiredWithProvider - * - * @param $check - * @param $expected - * @param mixed $field */ - public function testRequiredWith($field, $check, $expected = false) + public function testRequiredWith(?string $field, ?string $check, bool $expected): void { $data = [ 'foo' => 'bar', @@ -1171,46 +533,19 @@ public function testRequiredWith($field, $check, $expected = false) ], ]; - $this->validation->setRules([ - $field => "required_with[{$check}]", - ]); - + $this->validation->setRules([$field => "required_with[{$check}]"]); $this->assertSame($expected, $this->validation->run($data)); } - public function requiredWithProvider() + public function requiredWithProvider(): Generator { - return [ - [ - 'nope', - 'bar', - false, - ], - [ - 'foo', - 'bar', - true, - ], - [ - 'nope', - 'baz', - true, - ], - [ - null, - null, - true, - ], - [ - null, - 'foo', - false, - ], - [ - 'foo', - null, - true, - ], + yield from [ + ['nope', 'bar', false], + ['foo', 'bar', true], + ['nope', 'baz', true], + [null, null, true], + [null, 'foo', false], + ['foo', null, true], [ 'array.emptyField1', 'array.emptyField2', @@ -1236,12 +571,8 @@ public function requiredWithProvider() /** * @dataProvider requiredWithoutProvider - * - * @param $check - * @param $expected - * @param mixed $field */ - public function testRequiredWithout($field, $check, $expected = false) + public function testRequiredWithout(?string $field, ?string $check, bool $expected): void { $data = [ 'foo' => 'bar', @@ -1255,41 +586,18 @@ public function testRequiredWithout($field, $check, $expected = false) ], ]; - $this->validation->setRules([ - $field => "required_without[{$check}]", - ]); - + $this->validation->setRules([$field => "required_without[{$check}]"]); $this->assertSame($expected, $this->validation->run($data)); } - public function requiredWithoutProvider() + public function requiredWithoutProvider(): Generator { - return [ - [ - 'nope', - 'bars', - false, - ], - [ - 'foo', - 'nope', - true, - ], - [ - null, - null, - false, - ], - [ - null, - 'foo', - true, - ], - [ - 'foo', - null, - true, - ], + yield from [ + ['nope', 'bars', false], + ['foo', 'nope', true], + [null, null, false], + [null, 'foo', true], + ['foo', null, true], [ 'array.emptyField1', 'array.emptyField2', From a4c627ea550ef2796b457cb628a14ec8f0a029cd Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 3 Nov 2021 21:01:03 +0800 Subject: [PATCH 016/407] Optimize ValidationTest --- tests/system/Validation/ValidationTest.php | 351 ++++++--------------- 1 file changed, 98 insertions(+), 253 deletions(-) diff --git a/tests/system/Validation/ValidationTest.php b/tests/system/Validation/ValidationTest.php index 8b77686fc3b5..cffde6abf3bd 100644 --- a/tests/system/Validation/ValidationTest.php +++ b/tests/system/Validation/ValidationTest.php @@ -18,6 +18,7 @@ use CodeIgniter\Validation\Exceptions\ValidationException; use Config\App; use Config\Services; +use Generator; use Tests\Support\Validation\TestRules; /** @@ -28,9 +29,9 @@ final class ValidationTest extends CIUnitTestCase /** * @var Validation */ - protected $validation; + private $validation; - protected $config = [ + private $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -72,66 +73,44 @@ final class ValidationTest extends CIUnitTestCase protected function setUp(): void { parent::setUp(); - - Services::reset(true); - $this->validation = new Validation((object) $this->config, Services::renderer()); $this->validation->reset(); - - $_FILES = []; } - public function testSetRulesStoresRules() + public function testSetRulesStoresRules(): void { $rules = [ 'foo' => 'bar|baz', 'bar' => 'baz|belch', ]; - $this->validation->setRules($rules); - $this->assertSame($rules, $this->validation->getRules()); } - public function testRunReturnsFalseWithNothingToDo() + public function testRunReturnsFalseWithNothingToDo(): void { $this->validation->setRules([]); - $this->assertFalse($this->validation->run([])); } - public function testRunDoesTheBasics() + public function testRunDoesTheBasics(): void { - $data = [ - 'foo' => 'notanumber', - ]; - - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); - + $data = ['foo' => 'notanumber']; + $this->validation->setRules(['foo' => 'is_numeric']); $this->assertFalse($this->validation->run($data)); } - public function testRunReturnsLocalizedErrors() + public function testRunReturnsLocalizedErrors(): void { - $data = [ - 'foo' => 'notanumber', - ]; - - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); - + $data = ['foo' => 'notanumber']; + $this->validation->setRules(['foo' => 'is_numeric']); $this->assertFalse($this->validation->run($data)); $this->assertSame('Validation.is_numeric', $this->validation->getError('foo')); } - public function testRunWithCustomErrors() + public function testRunWithCustomErrors(): void { - $data = [ - 'foo' => 'notanumber', - ]; + $data = ['foo' => 'notanumber']; $messages = [ 'foo' => [ @@ -139,26 +118,23 @@ public function testRunWithCustomErrors() ], ]; - $this->validation->setRules([ - 'foo' => 'is_numeric', - ], $messages); - + $this->validation->setRules(['foo' => 'is_numeric'], $messages); $this->validation->run($data); $this->assertSame('Nope. Not a number.', $this->validation->getError('foo')); } - public function testCheck() + public function testCheck(): void { $this->assertFalse($this->validation->check('notanumber', 'is_numeric')); } - public function testCheckLocalizedError() + public function testCheckLocalizedError(): void { $this->assertFalse($this->validation->check('notanumber', 'is_numeric')); $this->assertSame('Validation.is_numeric', $this->validation->getError()); } - public function testCheckCustomError() + public function testCheckCustomError(): void { $this->validation->check('notanumber', 'is_numeric', [ 'is_numeric' => 'Nope. Not a number.', @@ -166,122 +142,87 @@ public function testCheckCustomError() $this->assertSame('Nope. Not a number.', $this->validation->getError()); } - public function testGetErrors() + public function testGetErrors(): void { - $data = [ - 'foo' => 'notanumber', - ]; - - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); - + $data = ['foo' => 'notanumber']; + $this->validation->setRules(['foo' => 'is_numeric']); $this->validation->run($data); - $this->assertSame(['foo' => 'Validation.is_numeric'], $this->validation->getErrors()); } - public function testGetErrorsWhenNone() + public function testGetErrorsWhenNone(): void { - $_SESSION = []; - - $data = [ - 'foo' => 123, - ]; - - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); - + $data = ['foo' => 123]; + $this->validation->setRules(['foo' => 'is_numeric']); $this->validation->run($data); - $this->assertSame([], $this->validation->getErrors()); } - public function testSetErrors() + public function testSetErrors(): void { - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); - + $this->validation->setRules(['foo' => 'is_numeric']); $this->validation->setError('foo', 'Nadda'); - $this->assertSame(['foo' => 'Nadda'], $this->validation->getErrors()); } - public function testRulesReturnErrors() + public function testRulesReturnErrors(): void { - $this->validation->setRules([ - 'foo' => 'customError', - ]); - + $this->validation->setRules(['foo' => 'customError']); $this->validation->run(['foo' => 'bar']); - $this->assertSame(['foo' => 'My lovely error'], $this->validation->getErrors()); } - public function testGroupsReadFromConfig() + public function testGroupsReadFromConfig(): void { - $data = [ - 'foo' => 'bar', - ]; - + $data = ['foo' => 'bar']; $this->assertFalse($this->validation->run($data, 'groupA')); $this->assertSame('Shame, shame. Too short.', $this->validation->getError('foo')); } - public function testGroupsReadFromConfigValid() + public function testGroupsReadFromConfigValid(): void { - $data = [ - 'foo' => 'barsteps', - ]; - + $data = ['foo' => 'barsteps']; $this->assertTrue($this->validation->run($data, 'groupA')); } - public function testGetRuleGroup() + public function testGetRuleGroup(): void { $this->assertSame([ 'foo' => 'required|min_length[5]', ], $this->validation->getRuleGroup('groupA')); } - public function testGetRuleGroupException() + public function testGetRuleGroupException(): void { $this->expectException(ValidationException::class); $this->validation->getRuleGroup('groupZ'); } - public function testSetRuleGroup() + public function testSetRuleGroup(): void { $this->validation->setRuleGroup('groupA'); - $this->assertSame([ 'foo' => 'required|min_length[5]', ], $this->validation->getRules()); } - public function testSetRuleGroupException() + public function testSetRuleGroupException(): void { $this->expectException(ValidationException::class); - $this->validation->setRuleGroup('groupZ'); } - public function testSetRuleGroupWithCustomErrorMessage() + public function testSetRuleGroupWithCustomErrorMessage(): void { $this->validation->reset(); $this->validation->setRuleGroup('login'); - $this->validation->run([ - 'username' => 'codeigniter', - ]); - + $this->validation->run(['username' => 'codeigniter']); $this->assertSame([ 'password' => 'custom password required error msg.', ], $this->validation->getErrors()); } - public function testRunGroupWithCustomErrorMessage() + public function testRunGroupWithCustomErrorMessage(): void { $this->validation->reset(); $this->validation->run([ @@ -296,28 +237,20 @@ public function testRunGroupWithCustomErrorMessage() /** * @dataProvider rulesSetupProvider * - * @param mixed $rules - * @param mixed $expected - * @param mixed $errors + * @param string|string[] $rules + * @param string $expected */ - public function testRulesSetup($rules, $expected, $errors = []) + public function testRulesSetup($rules, $expected, array $errors = []) { - $data = [ - 'foo' => '', - ]; - - $this->validation->setRules([ - 'foo' => $rules, - ], $errors); - + $data = ['foo' => '']; + $this->validation->setRules(['foo' => $rules], $errors); $this->validation->run($data); - $this->assertSame($expected, $this->validation->getError('foo')); } - public function rulesSetupProvider() + public function rulesSetupProvider(): Generator { - return [ + yield from [ [ 'min_length[10]', 'The foo field must be at least 10 characters in length.', @@ -366,7 +299,7 @@ public function rulesSetupProvider() ]; } - public function testSetRulesRemovesErrorsArray() + public function testSetRulesRemovesErrorsArray(): void { $rules = [ 'foo' => [ @@ -379,13 +312,11 @@ public function testSetRulesRemovesErrorsArray() ]; $this->validation->setRules($rules, []); - $this->validation->run(['foo' => 'abc']); - $this->assertSame('The Foo Bar field is very short.', $this->validation->getError('foo')); } - public function testInvalidRule() + public function testInvalidRule(): void { $this->expectException(ValidationException::class); @@ -395,13 +326,11 @@ public function testInvalidRule() ]; $this->validation->setRules($rules); - $data = [ - 'foo' => '', - ]; + $data = ['foo' => '']; $this->validation->run($data); } - public function testRawInput() + public function testRawInput(): void { $rawstring = 'username=admin001&role=administrator&usepass=0'; @@ -419,7 +348,7 @@ public function testRawInput() $this->assertSame([], $this->validation->getErrors()); } - public function testJsonInput() + public function testJsonInput(): void { $data = [ 'username' => 'admin001', @@ -449,187 +378,126 @@ public function testJsonInput() unset($_SERVER['CONTENT_TYPE']); } - public function testHasRule() + public function testHasRule(): void { $this->validation->setRuleGroup('groupA'); - $this->assertTrue($this->validation->hasRule('foo')); } - public function testNotARealGroup() + public function testNotARealGroup(): void { $this->expectException(ValidationException::class); $this->validation->setRuleGroup('groupX'); $this->validation->getRuleGroup('groupX'); } - public function testBadTemplate() + public function testBadTemplate(): void { $this->expectException(ValidationException::class); $this->validation->listErrors('obviouslyBadTemplate'); } - public function testShowNonError() + public function testShowNonError(): void { - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); - + $this->validation->setRules(['foo' => 'is_numeric']); $this->validation->setError('foo', 'Nadda'); - $this->assertSame('', $this->validation->showError('bogus')); } - public function testShowBadTemplate() + public function testShowBadTemplate(): void { $this->expectException(ValidationException::class); - - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); + $this->validation->setRules(['foo' => 'is_numeric']); $this->validation->setError('foo', 'Nadda'); - $this->assertSame('We should never get here', $this->validation->showError('foo', 'bogus_template')); } - public function testNoRuleSetsSetup() + public function testNoRuleSetsSetup(): void { $this->expectException(ValidationException::class); $this->config['ruleSets'] = null; $this->validation = new Validation((object) $this->config, Services::renderer()); $this->validation->reset(); - - $data = [ - 'foo' => '', - ]; - - $this->validation->run($data); + $this->validation->run(['foo' => '']); } - public function testNotCustomRuleGroup() + public function testNotCustomRuleGroup(): void { $this->expectException(ValidationException::class); - - $data = [ - 'foo' => '', - ]; - + $data = ['foo' => '']; $this->validation->run($data, 'GeorgeRules'); } - public function testNotRealCustomRule() + public function testNotRealCustomRule(): void { $this->expectException(ValidationException::class); - - $data = [ - 'foo' => '', - ]; - + $data = ['foo' => '']; $this->validation->run($data, 'groupX'); } - public function testHasError() + public function testHasError(): void { - $data = [ - 'foo' => 'notanumber', - ]; - - $this->validation->setRules([ - 'foo' => 'is_numeric', - ]); - + $data = ['foo' => 'notanumber']; + $this->validation->setRules(['foo' => 'is_numeric']); $this->validation->run($data); - $this->assertTrue($this->validation->hasError('foo')); } - public function testSplitRulesTrue() + public function testSplitRulesTrue(): void { - $data = [ - 'phone' => '0987654321', - ]; - $this->validation->setRules([ 'phone' => 'required|regex_match[/^(01[2689]|09)[0-9]{8}$/]|numeric', ]); - - $result = $this->validation->run($data); - - $this->assertTrue($result); + $this->assertTrue($this->validation->run(['phone' => '0987654321'])); } - public function testSplitRulesFalse() + public function testSplitRulesFalse(): void { - $data = [ - 'phone' => '09876543214', - ]; - $this->validation->setRules([ 'phone' => 'required|regex_match[/^(01[2689]|09)[0-9]{8}$/]|numeric', ]); - - $result = $this->validation->run($data); - - $this->assertFalse($result); + $this->assertFalse($this->validation->run(['phone' => '09876543214'])); } /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/1201 */ - public function testSplitNotRegex() + public function testSplitNotRegex(): void { $method = $this->getPrivateMethodInvoker($this->validation, 'splitRules'); - $result = $method('uploaded[avatar]|max_size[avatar,1024]'); - $this->assertSame('uploaded[avatar]', $result[0]); } - public function testSplitRegex() + public function testSplitRegex(): void { $method = $this->getPrivateMethodInvoker($this->validation, 'splitRules'); - $result = $method('required|regex_match[/^[0-9]{4}[\-\.\[\/][0-9]{2}[\-\.\[\/][0-9]{2}/]|max_length[10]'); - $this->assertSame('regex_match[/^[0-9]{4}[\-\.\[\/][0-9]{2}[\-\.\[\/][0-9]{2}/]', $result[1]); } - public function testTagReplacement() + public function testTagReplacement(): void { - // data - $data = [ - 'Username' => 'Pizza', - ]; - - // rules - $this->validation->setRules([ - 'Username' => 'min_length[6]', - ], [ - 'Username' => [ + $data = ['Username' => 'Pizza']; + $this->validation->setRules( + ['Username' => 'min_length[6]'], + ['Username' => [ 'min_length' => 'Supplied value ({value}) for {field} must have at least {param} characters.', - ], - ]); - - // run validation + ]] + ); $this->validation->run($data); - - // $errors should contain an associative array $errors = $this->validation->getErrors(); - // if "Username" doesn't exist in errors if (! isset($errors['Username'])) { $this->fail('Unable to find "Username"'); } - // expected error message $expected = 'Supplied value (Pizza) for Username must have at least 6 characters.'; - - // check if they are the same! $this->assertSame($expected, $errors['Username']); } - public function testRulesForObjectField() + public function testRulesForObjectField(): void { $this->validation->setRules([ 'configuration' => 'required|check_object_rule', @@ -640,7 +508,6 @@ public function testRulesForObjectField() $this->assertSame([], $this->validation->getErrors()); $this->validation->reset(); - $this->validation->setRules([ 'configuration' => 'required|check_object_rule', ]); @@ -655,12 +522,8 @@ public function testRulesForObjectField() /** * @dataProvider arrayFieldDataProvider - * - * @param mixed $body - * @param mixed $rules - * @param mixed $results */ - public function testRulesForArrayField($body, $rules, $results) + public function testRulesForArrayField(array $body, array $rules, array $results) { $config = new App(); $config->baseURL = 'http://example.com/'; @@ -672,9 +535,9 @@ public function testRulesForArrayField($body, $rules, $results) $this->assertSame($results, $this->validation->getErrors()); } - public function arrayFieldDataProvider() + public function arrayFieldDataProvider(): Generator { - return [ + yield from [ 'all_rules_should_pass' => [ 'body' => [ 'foo' => [ @@ -728,7 +591,7 @@ public function arrayFieldDataProvider() ]; } - public function testRulesForSingleRuleWithAsteriskWillReturnNoError() + public function testRulesForSingleRuleWithAsteriskWillReturnNoError(): void { $config = new App(); $config->baseURL = 'http://example.com/'; @@ -755,7 +618,7 @@ public function testRulesForSingleRuleWithAsteriskWillReturnNoError() $this->assertSame([], $this->validation->getErrors()); } - public function testRulesForSingleRuleWithAsteriskWillReturnError() + public function testRulesForSingleRuleWithAsteriskWillReturnError(): void { $config = new App(); $config->baseURL = 'http://example.com/'; @@ -785,7 +648,7 @@ public function testRulesForSingleRuleWithAsteriskWillReturnError() ], $this->validation->getErrors()); } - public function testRulesForSingleRuleWithSingleValue() + public function testRulesForSingleRuleWithSingleValue(): void { $config = new App(); $config->baseURL = 'http://example.com/'; @@ -806,7 +669,7 @@ public function testRulesForSingleRuleWithSingleValue() ], $this->validation->getErrors()); } - public function testTranslatedLabel() + public function testTranslatedLabel(): void { $rules = [ 'foo' => [ @@ -816,13 +679,11 @@ public function testTranslatedLabel() ]; $this->validation->setRules($rules, []); - $this->validation->run(['foo' => 'abc']); - $this->assertSame('The Foo Bar Translated field must be at least 10 characters in length.', $this->validation->getError('foo')); } - public function testTranslatedLabelIsMissing() + public function testTranslatedLabelIsMissing(): void { $rules = [ 'foo' => [ @@ -832,13 +693,11 @@ public function testTranslatedLabelIsMissing() ]; $this->validation->setRules($rules, []); - $this->validation->run(['foo' => 'abc']); - $this->assertSame('The Foo.bar.is.missing field must be at least 10 characters in length.', $this->validation->getError('foo')); } - public function testTranslatedLabelWithCustomErrorMessage() + public function testTranslatedLabelWithCustomErrorMessage(): void { $rules = [ 'foo' => [ @@ -851,46 +710,32 @@ public function testTranslatedLabelWithCustomErrorMessage() ]; $this->validation->setRules($rules, []); - $this->validation->run(['foo' => 'abc']); - $this->assertSame('The Foo Bar Translated field is very short.', $this->validation->getError('foo')); } - public function testTranslatedLabelTagReplacement() + public function testTranslatedLabelTagReplacement(): void { - // data - $data = [ - 'Username' => 'Pizza', - ]; + $data = ['Username' => 'Pizza']; - // rules - $this->validation->setRules([ - 'Username' => [ + $this->validation->setRules( + ['Username' => [ 'label' => 'Foo.bar', 'rules' => 'min_length[6]', - ], - ], [ - 'Username' => [ + ]], + ['Username' => [ 'min_length' => 'Foo.bar.min_length2', - ], - ]); + ]] + ); - // run validation $this->validation->run($data); - - // $errors should contain an associative array $errors = $this->validation->getErrors(); - // if "Username" doesn't exist in errors if (! isset($errors['Username'])) { $this->fail('Unable to find "Username"'); } - // expected error message $expected = 'Supplied value (Pizza) for Foo Bar Translated must have at least 6 characters.'; - - // check if they are the same! $this->assertSame($expected, $errors['Username']); } @@ -905,7 +750,7 @@ public function testDotNotationOnIfExistRule(bool $expected, array $rules, array $this->assertSame($expected, $actual); } - public function dotNotationForIfExistProvider() + public function dotNotationForIfExistProvider(): Generator { yield 'dot-on-end-fail' => [ false, From 5bf6d51ef49cce76cea3baeaf8fa7905f0c4d6bd Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 8 Nov 2021 11:13:14 +0900 Subject: [PATCH 017/407] fix: cannot find files in sub-namespaces of the same vendor For example, when you have `CodeIgniter` and `CodeIgniter\Devkit`. --- system/Autoloader/FileLocator.php | 18 ++++++++---------- tests/system/Autoloader/FileLocatorTest.php | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/system/Autoloader/FileLocator.php b/system/Autoloader/FileLocator.php index 6fa8109bf992..b8bfdf6df217 100644 --- a/system/Autoloader/FileLocator.php +++ b/system/Autoloader/FileLocator.php @@ -55,6 +55,7 @@ public function locateFile(string $file, ?string $folder = null, string $ext = ' // Standardize slashes to handle nested directories. $file = strtr($file, '/', '\\'); + $file = ltrim($file, '\\'); $segments = explode('\\', $file); @@ -64,23 +65,20 @@ public function locateFile(string $file, ?string $folder = null, string $ext = ' } $paths = []; - $prefix = ''; $filename = ''; // Namespaces always comes with arrays of paths $namespaces = $this->autoloader->getNamespace(); - while (! empty($segments)) { - $prefix .= empty($prefix) ? array_shift($segments) : '\\' . array_shift($segments); + foreach (array_keys($namespaces) as $namespace) { + if (substr($file, 0, strlen($namespace)) === $namespace) { + // There may be sub-namespaces of the same vendor, + // so overwrite them with namespaces found later. + $paths = $namespaces[$namespace]; - if (empty($namespaces[$prefix])) { - continue; + $fileWithoutNamespace = substr($file, strlen($namespace)); + $filename = ltrim(str_replace('\\', '/', $fileWithoutNamespace), '/'); } - - $paths = $namespaces[$prefix]; - - $filename = implode('/', $segments); - break; } // if no namespaces matched then quit diff --git a/tests/system/Autoloader/FileLocatorTest.php b/tests/system/Autoloader/FileLocatorTest.php index c85e4c215ba2..3a40ed24345b 100644 --- a/tests/system/Autoloader/FileLocatorTest.php +++ b/tests/system/Autoloader/FileLocatorTest.php @@ -39,8 +39,11 @@ protected function setUp(): void TESTPATH, SYSTEMPATH, ], - 'Errors' => APPPATH . 'Views/errors', - 'System' => SUPPORTPATH . 'Autoloader/system', + 'Errors' => APPPATH . 'Views/errors', + 'System' => SUPPORTPATH . 'Autoloader/system', + 'CodeIgniter\\Devkit' => [ + TESTPATH . '_support/', + ], ]); $this->locator = new FileLocator($autoloader); @@ -125,6 +128,15 @@ public function testLocateFileCanFindNestedNamespacedView() $this->assertSame($expected, $this->locator->locateFile($file, 'html')); } + public function testLocateFileCanFindNamespacedViewWhenVendorHasTwoNamespaces() + { + $file = '\CodeIgniter\Devkit\View\Views/simple'; + + $expected = ROOTPATH . 'tests/_support/View/Views/simple.php'; + + $this->assertSame($expected, $this->locator->locateFile($file, 'Views')); + } + public function testLocateFileNotFoundExistingNamespace() { $file = '\App\Views/unexistence-file.php'; From 73f771e0f734fbbb0c100349949de0b0610f4535 Mon Sep 17 00:00:00 2001 From: MGatner Date: Mon, 8 Nov 2021 16:14:12 +0000 Subject: [PATCH 018/407] Fix TOCs --- user_guide_src/source/changelogs/index.rst | 1 + user_guide_src/source/installation/upgrading.rst | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/changelogs/index.rst b/user_guide_src/source/changelogs/index.rst index 2ec12f649150..8a54083777d3 100644 --- a/user_guide_src/source/changelogs/index.rst +++ b/user_guide_src/source/changelogs/index.rst @@ -12,6 +12,7 @@ See all the changes. .. toctree:: :titlesonly: + v4.1.6 v4.1.5 v4.1.4 v4.1.3 diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index 771392d8f81a..0264b6eaa3bb 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -8,7 +8,6 @@ upgrading from. .. toctree:: :titlesonly: - Upgrading from 4.1.5 to 4.1.6 Upgrading from 4.1.4 to 4.1.5 Upgrading from 4.1.3 to 4.1.4 Upgrading from 4.1.2 to 4.1.3 From c0ac3bc4aad9881f129c1591f4d99dcebb947e73 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 11:32:09 +0900 Subject: [PATCH 019/407] docs: add GitHub auto-generated release note for v4.1.5 --- CHANGELOG.md | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74513d243589..f1bfe6ce8c3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,194 @@ # Changelog +## [v4.1.5](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.5) (2021-11-08) + +[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.1.4...v4.1.5) + +* Fixes and enhancements to Exceptions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5052 +* Add entry to changelog for initial PHP 8.1 changes by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5054 +* Apply NoCodeSeparatorCommentFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5053 +* Fix entity name generation when bundled in model by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5055 +* docs: fix indentation of the changelog v4.1.4 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5057 +* Fix variable variable `$$id` in RedisHandler by @Terrorboy in https://github.com/codeigniter4/CodeIgniter4/pull/5062 +* Update 'updated_at' when enabled in replace() by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4684 +* Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 +* Document new coding style guide by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4825 +* Update to phpdocumentor v3.1.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5020 +* Add phive to tools in workflow by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5063 +* Test fixing apidocs action by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5064 +* docs: fix upgrade_414 format by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5067 +* docs: update coding-standard links by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5068 +* Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 +* docs: add session table change for upgrade by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5069 +* docs: update PSR Compliance (PSR-12) by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5070 +* Update rector/rector requirement from 0.11.52 to 0.11.53 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5071 +* docs: fix view_parser by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5072 +* docs: small fixes for entities by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5077 +* docs: fix db_forge by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5076 +* docs: extended upgrading from CI3 to CI4 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5078 +* docs: add about upgrading migration table by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5079 +* docs: rename v4.2.0 to v4.1.5 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5081 +* [Rector] Clean up rector skip config by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5086 +* docs: fix query_builder RST format by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5083 +* docs: fix sample code in upgrade_routing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5084 +* docs: small fixes for configuration by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5085 +* docs: fix indentation for migration by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5089 +* docs: add new line at end of file by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5090 +* docs: fix indentation for testing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5091 +* Fix typo in Config/Factories.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5092 +* docs: fix api responses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5093 +* Remove --using-cache=no from php-cs-fixer in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5095 +* Previous Responses by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5034 +* docs: fix cli library by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5099 +* Add composer scripts for coding style by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5098 +* docs: replace tab with space by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5102 +* [Rector] Apply Rector: SimplifyEmptyArrayCheckRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5101 +* docs: replace tab with space by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5105 +* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5109 +* docs: describe in detail how to add a service by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5112 +* docs: update debugging by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5111 +* IncomingRequest - Trim trailing slash by @najdanovicivan in https://github.com/codeigniter4/CodeIgniter4/pull/4974 +* docs: fix 404 link by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5119 +* docs: fix indentation of list by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5120 +* Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 +* docs: small improvement Upgrading from 3.x to 4.x by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5121 +* Fix query binding with two colons in query by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5117 +* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5122 +* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5130 +* Fixed the problem that _createTable does not take into account that it returns true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5133 +* Fix Forge test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5135 +* Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 +* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5140 +* chore(deps-dev): update rector/rector requirement from 0.11.53 to 0.11.54 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5144 +* docs: fix sample code in user_agent.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5146 +* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5145 +* chore(deps): bump actions/github-script from 4 to 5 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5143 +* Fix MemcachedHandlerTest::testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5147 +* add SECURITY.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5123 +* chore(deps-dev): update rector/rector requirement from 0.11.54 to 0.11.55 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5151 +* docs: fix link styleguide.md in CONTRIBUTING.md by @Felipebros in https://github.com/codeigniter4/CodeIgniter4/pull/5152 +* docs: fix Google.com to DuckDuckGo.com by @Felipebros in https://github.com/codeigniter4/CodeIgniter4/pull/5153 +* Fix color not updated in several places of the precompiled CSS by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5155 +* chore(deps-dev): update rector/rector requirement from 0.11.55 to 0.11.56 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5154 +* Fix `Model::__call` throwing `BadMethodCallException` on empty results by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5139 +* Error when value is an object - validating api data by @daycry in https://github.com/codeigniter4/CodeIgniter4/pull/5142 +* Fix debugbar styles printing by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5100 +* docs: fix tests/README by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5166 +* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 +* docs: fix classname for testing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5169 +* Fix highlighting in database debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5129 +* Fixed an issue where the dropForeginKey method would execute an empty query when the dropConstraintStr property was empty. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5173 +* docs: fix coding style in uploaded_files.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5174 +* fix typo by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/5124 +* Multiple filters for a route and classname filter by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5128 +* (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 +* Fix debug toolbar db connection count by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5172 +* Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 +* Add tabs detector for RST files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5165 +* feat: `_` can be used as separators in environment variable names by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5156 +* chore(deps-dev): update rector/rector requirement from 0.11.56 to 0.11.57 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5177 +* docs: fix 404 links to sytle guide by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5167 +* docs: convert `contributing/*.rst` to `*.md` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5180 +* Fixed a problem with not run escape for identities in like when `insensitiveSearch` is true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5170 +* Fixed an issue where an unnecessary prefix was given when the random number was a column. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5179 +* Enable `no_alternative_syntax` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5181 +* Add support for new fixers added in php-cs-fixer v3.2.0 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5175 +* Refactor/optimise starter's tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5158 +* Add unit test to ensure named binds don't get replaced in binded values by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5184 +* Fix PHPDoc for Security by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5187 +* Fix Cache testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5189 +* Feature - Mark duplicate queries by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5185 +* Remove coverage.txt by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5188 +* chore: add Database in bug report template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5182 +* Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 +* Change behavior of `class_attributes_separation` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5176 +* Move PR template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5191 +* docs: rework contributing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5183 +* Update admin/README.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5199 +* Update README by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5197 +* Update CSRF related docs by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5198 +* docs: Github -> GitHub by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5203 +* chore(deps-dev): update rector/rector requirement from 0.11.57 to 0.11.58 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5204 +* [Debug] Add formatted query string to timeline. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5196 +* Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171 +* [Debug] Improve keyword highlighting and escaping of query strings. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5200 +* Fix CSRF filter does not work when set it to only post by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5194 +* Fix GC issue when session lifetime is set to 0 by @lf-uraku-yuki in https://github.com/codeigniter4/CodeIgniter4/pull/4744 +* docs: small improvement in debugging by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5208 +* Add `@group CacheLive` to tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5209 +* docs: remove link to Model in routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5210 +* docs: unify the decoration of app/Config/*.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5213 +* chore(deps-dev): update rector/rector requirement from 0.11.58 to 0.11.59 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5219 +* docs: improve Form Validation Tutorial by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5223 +* Improve contributing docs by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5222 +* Fix typo in @var classname in Tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5216 +* docs: add caution on filtering to routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5212 +* chore(deps-dev): update rector/rector requirement from 0.11.59 to 0.11.60 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5225 +* Improve tests/README.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5221 +* add escape to identifiers for document. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5195 +* Add Session based CSRF Protection by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5201 +* Add CSRF Protection for PUT/PATCH/DELETE by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5228 +* docs: improve Upgrading 4.1.5 page format by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5232 +* Rename toolbar loader to be a regular JS file by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5224 +* Remove invalid @runTestsInSeparateProcesses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5217 +* [HTTP] Update Http Status Description based on latest iana.org by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5235 +* Fix user guide on CSRF by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5230 +* Remove CSRF properties by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5231 +* docs: improve validation.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5233 +* [Rector] Using LevelSetList::UP_TO_PHP_73 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5239 +* Switch PHPCPD to tool by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5240 +* docs: fix installation/upgrade_4xx.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5238 +* docs: fix format of testing/overview.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5237 +* Fix Publisher test failures on macOS by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5211 +* docs: fix typography.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5241 +* Add CSRF test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5236 +* Fix TimeTest::testToFormattedDateString() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5245 +* Fix wrong helper path resolution by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5246 +* docs: decorate `.env` with `**` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5248 +* style: global_namespace_import true by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5250 +* Fix CreateDatabaseTest::testCreateDatabase() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5244 +* docs: fix security_helper.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5252 +* docs: fix upgrade_security.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5253 +* Cleanup php-cs-fixer config files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5254 +* Optimize `builds` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5255 +* Replace explicit calls to `Services::reset()` in tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5259 +* Remove static variables for PHP 8.1 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5262 +* Fix: remove CURLRequest headers sharing from $_SERVER by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5249 +* Fix CURLRequest extra headers by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5218 +* Speed up `CommonSingleServiceTest` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5258 +* Disable blank issues by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5257 +* Replace usage of `FILTER_SANITIZE_STRING` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5263 +* Enable `ordered_class_elements` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5265 +* Convert bug report to new syntax by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5264 +* Enclose the PR template's notes as comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5256 +* Simplify logic of `number_to_roman` function by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5270 +* [Rector] Refactor UnderscoreToCamelCaseVariableNameRector so no longer require symplify/package-builder by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5271 +* Refactor FiltersTest.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5242 +* docs: add how to fix code with Rector by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5273 +* Fix Localization not working/being ignored for 404 page by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5267 +* docs: fix html_helper.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5276 +* docs: move CSRF Protection Methods section up by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5275 +* Fix compatibility of `PgSql\Result` on closing the result instance by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5279 +* Fix compatibility of Postgres result for PHP 8.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5278 +* [Rector] Remove FixClassCaseSensitivityNameRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5288 +* Update bug report template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5287 +* docs: update Tutorial by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5285 +* docs: improve modules.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5281 +* feat: add valid_url_strict rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5268 +* fix: module filters are not discovered when using route filters by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5280 +* docs: improve routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5284 +* docs: fix RST format in caching.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5291 +* Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 +* Prep for 4.1.5 release by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5293 +* 4.1.5 Ready code by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5294 + +## New Contributors +* @Terrorboy made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5062 +* @vlakoff made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5136 +* @Felipebros made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5152 +* @daycry made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5142 +* @danielTiringer made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5172 + ## [v4.1.4](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.4) (2021-09-06) This release focuses on code style. All changes (except those noted below) are cosmetic to bring the code in line with the new From 8cb858bd6e8b203afadf04ac927744c54857e339 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 11:39:49 +0900 Subject: [PATCH 020/407] docs: add and fix headings --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1bfe6ce8c3d..582fc05daddc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ [Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.1.4...v4.1.5) +**Fixed bugs:** + +**Implemented enhancements:** + +**Merged pull requests:** + * Fixes and enhancements to Exceptions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5052 * Add entry to changelog for initial PHP 8.1 changes by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5054 * Apply NoCodeSeparatorCommentFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5053 @@ -182,7 +188,8 @@ * Prep for 4.1.5 release by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5293 * 4.1.5 Ready code by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5294 -## New Contributors +**New Contributors** + * @Terrorboy made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5062 * @vlakoff made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5136 * @Felipebros made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/5152 From 21a29fd5c3360067cdd4661f1776e8a407558ae3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 11:44:12 +0900 Subject: [PATCH 021/407] docs: move Fixed PRs --- CHANGELOG.md | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 582fc05daddc..53f356e6a787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,17 +6,38 @@ **Fixed bugs:** +* Fixes and enhancements to Exceptions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5052 +* Fix entity name generation when bundled in model by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5055 +* Fix variable variable `$$id` in RedisHandler by @Terrorboy in https://github.com/codeigniter4/CodeIgniter4/pull/5062 +* Previous Responses by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5034 +* Fix query binding with two colons in query by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5117 +* Fixed the problem that _createTable does not take into account that it returns true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5133 +* Fix color not updated in several places of the precompiled CSS by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5155 +* Fix `Model::__call` throwing `BadMethodCallException` on empty results by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5139 +* Error when value is an object - validating api data by @daycry in https://github.com/codeigniter4/CodeIgniter4/pull/5142 +* Fix debugbar styles printing by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5100 +* Fix highlighting in database debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5129 +* Fixed an issue where the dropForeginKey method would execute an empty query when the dropConstraintStr property was empty. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5173 +* Fix debug toolbar db connection count by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5172 +* Fixed a problem with not run escape for identities in like when `insensitiveSearch` is true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5170 +* Fixed an issue where an unnecessary prefix was given when the random number was a column. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5179 +* Fix CSRF filter does not work when set it to only post by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5194 +* Fix GC issue when session lifetime is set to 0 by @lf-uraku-yuki in https://github.com/codeigniter4/CodeIgniter4/pull/4744 +* Fix wrong helper path resolution by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5246 +* Fix: remove CURLRequest headers sharing from $_SERVER by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5249 +* Fix CURLRequest extra headers by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5218 +* Fix Localization not working/being ignored for 404 page by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5267 +* fix: module filters are not discovered when using route filters by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5280 +* Update 'updated_at' when enabled in replace() by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4684 +* IncomingRequest - Trim trailing slash by @najdanovicivan in https://github.com/codeigniter4/CodeIgniter4/pull/4974 + **Implemented enhancements:** **Merged pull requests:** -* Fixes and enhancements to Exceptions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5052 * Add entry to changelog for initial PHP 8.1 changes by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5054 * Apply NoCodeSeparatorCommentFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5053 -* Fix entity name generation when bundled in model by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5055 * docs: fix indentation of the changelog v4.1.4 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5057 -* Fix variable variable `$$id` in RedisHandler by @Terrorboy in https://github.com/codeigniter4/CodeIgniter4/pull/5062 -* Update 'updated_at' when enabled in replace() by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4684 * Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 * Document new coding style guide by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4825 * Update to phpdocumentor v3.1.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5020 @@ -44,7 +65,6 @@ * Fix typo in Config/Factories.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5092 * docs: fix api responses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5093 * Remove --using-cache=no from php-cs-fixer in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5095 -* Previous Responses by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5034 * docs: fix cli library by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5099 * Add composer scripts for coding style by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5098 * docs: replace tab with space by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5102 @@ -53,15 +73,12 @@ * docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5109 * docs: describe in detail how to add a service by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5112 * docs: update debugging by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5111 -* IncomingRequest - Trim trailing slash by @najdanovicivan in https://github.com/codeigniter4/CodeIgniter4/pull/4974 * docs: fix 404 link by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5119 * docs: fix indentation of list by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5120 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 * docs: small improvement Upgrading from 3.x to 4.x by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5121 -* Fix query binding with two colons in query by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5117 * docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5122 * docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5130 -* Fixed the problem that _createTable does not take into account that it returns true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5133 * Fix Forge test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5135 * Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 * docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5140 @@ -74,29 +91,20 @@ * chore(deps-dev): update rector/rector requirement from 0.11.54 to 0.11.55 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5151 * docs: fix link styleguide.md in CONTRIBUTING.md by @Felipebros in https://github.com/codeigniter4/CodeIgniter4/pull/5152 * docs: fix Google.com to DuckDuckGo.com by @Felipebros in https://github.com/codeigniter4/CodeIgniter4/pull/5153 -* Fix color not updated in several places of the precompiled CSS by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5155 * chore(deps-dev): update rector/rector requirement from 0.11.55 to 0.11.56 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5154 -* Fix `Model::__call` throwing `BadMethodCallException` on empty results by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5139 -* Error when value is an object - validating api data by @daycry in https://github.com/codeigniter4/CodeIgniter4/pull/5142 -* Fix debugbar styles printing by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5100 * docs: fix tests/README by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5166 * Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 * docs: fix classname for testing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5169 -* Fix highlighting in database debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5129 -* Fixed an issue where the dropForeginKey method would execute an empty query when the dropConstraintStr property was empty. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5173 * docs: fix coding style in uploaded_files.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5174 * fix typo by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/5124 * Multiple filters for a route and classname filter by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5128 * (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 -* Fix debug toolbar db connection count by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5172 * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 * Add tabs detector for RST files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5165 * feat: `_` can be used as separators in environment variable names by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5156 * chore(deps-dev): update rector/rector requirement from 0.11.56 to 0.11.57 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5177 * docs: fix 404 links to sytle guide by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5167 * docs: convert `contributing/*.rst` to `*.md` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5180 -* Fixed a problem with not run escape for identities in like when `insensitiveSearch` is true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5170 -* Fixed an issue where an unnecessary prefix was given when the random number was a column. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5179 * Enable `no_alternative_syntax` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5181 * Add support for new fixers added in php-cs-fixer v3.2.0 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5175 * Refactor/optimise starter's tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5158 @@ -118,8 +126,6 @@ * [Debug] Add formatted query string to timeline. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5196 * Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171 * [Debug] Improve keyword highlighting and escaping of query strings. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5200 -* Fix CSRF filter does not work when set it to only post by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5194 -* Fix GC issue when session lifetime is set to 0 by @lf-uraku-yuki in https://github.com/codeigniter4/CodeIgniter4/pull/4744 * docs: small improvement in debugging by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5208 * Add `@group CacheLive` to tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5209 * docs: remove link to Model in routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5210 @@ -149,7 +155,6 @@ * docs: fix typography.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5241 * Add CSRF test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5236 * Fix TimeTest::testToFormattedDateString() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5245 -* Fix wrong helper path resolution by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5246 * docs: decorate `.env` with `**` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5248 * style: global_namespace_import true by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5250 * Fix CreateDatabaseTest::testCreateDatabase() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5244 @@ -159,8 +164,6 @@ * Optimize `builds` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5255 * Replace explicit calls to `Services::reset()` in tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5259 * Remove static variables for PHP 8.1 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5262 -* Fix: remove CURLRequest headers sharing from $_SERVER by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5249 -* Fix CURLRequest extra headers by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5218 * Speed up `CommonSingleServiceTest` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5258 * Disable blank issues by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5257 * Replace usage of `FILTER_SANITIZE_STRING` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5263 @@ -171,7 +174,6 @@ * [Rector] Refactor UnderscoreToCamelCaseVariableNameRector so no longer require symplify/package-builder by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5271 * Refactor FiltersTest.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5242 * docs: add how to fix code with Rector by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5273 -* Fix Localization not working/being ignored for 404 page by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5267 * docs: fix html_helper.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5276 * docs: move CSRF Protection Methods section up by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5275 * Fix compatibility of `PgSql\Result` on closing the result instance by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5279 @@ -181,7 +183,6 @@ * docs: update Tutorial by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5285 * docs: improve modules.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5281 * feat: add valid_url_strict rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5268 -* fix: module filters are not discovered when using route filters by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5280 * docs: improve routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5284 * docs: fix RST format in caching.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5291 * Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 From b5167aaf7d1a4ba5ff251c193c224781c283cb62 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 11:51:23 +0900 Subject: [PATCH 022/407] docs: move enhancements PRs --- CHANGELOG.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53f356e6a787..974a7dab4a7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,18 @@ **Implemented enhancements:** +* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 +* Multiple filters for a route and classname filter by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5128 +* feat: `_` can be used as separators in environment variable names by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5156 +* Feature - Mark duplicate queries by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5185 +* [Debug] Add formatted query string to timeline. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5196 +* Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171 +* [Debug] Improve keyword highlighting and escaping of query strings. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5200 +* Add Session based CSRF Protection by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5201 +* Add CSRF Protection for PUT/PATCH/DELETE by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5228 +* feat: add valid_url_strict rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5268 +* Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 + **Merged pull requests:** * Add entry to changelog for initial PHP 8.1 changes by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5054 @@ -93,15 +105,12 @@ * docs: fix Google.com to DuckDuckGo.com by @Felipebros in https://github.com/codeigniter4/CodeIgniter4/pull/5153 * chore(deps-dev): update rector/rector requirement from 0.11.55 to 0.11.56 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5154 * docs: fix tests/README by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5166 -* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 * docs: fix classname for testing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5169 * docs: fix coding style in uploaded_files.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5174 * fix typo by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/5124 -* Multiple filters for a route and classname filter by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5128 * (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 * Add tabs detector for RST files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5165 -* feat: `_` can be used as separators in environment variable names by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5156 * chore(deps-dev): update rector/rector requirement from 0.11.56 to 0.11.57 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5177 * docs: fix 404 links to sytle guide by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5167 * docs: convert `contributing/*.rst` to `*.md` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5180 @@ -111,7 +120,6 @@ * Add unit test to ensure named binds don't get replaced in binded values by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5184 * Fix PHPDoc for Security by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5187 * Fix Cache testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5189 -* Feature - Mark duplicate queries by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5185 * Remove coverage.txt by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5188 * chore: add Database in bug report template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5182 * Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 @@ -123,9 +131,6 @@ * Update CSRF related docs by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5198 * docs: Github -> GitHub by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5203 * chore(deps-dev): update rector/rector requirement from 0.11.57 to 0.11.58 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5204 -* [Debug] Add formatted query string to timeline. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5196 -* Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171 -* [Debug] Improve keyword highlighting and escaping of query strings. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5200 * docs: small improvement in debugging by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5208 * Add `@group CacheLive` to tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5209 * docs: remove link to Model in routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5210 @@ -138,8 +143,6 @@ * chore(deps-dev): update rector/rector requirement from 0.11.59 to 0.11.60 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5225 * Improve tests/README.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5221 * add escape to identifiers for document. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5195 -* Add Session based CSRF Protection by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5201 -* Add CSRF Protection for PUT/PATCH/DELETE by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5228 * docs: improve Upgrading 4.1.5 page format by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5232 * Rename toolbar loader to be a regular JS file by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5224 * Remove invalid @runTestsInSeparateProcesses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5217 @@ -182,10 +185,8 @@ * Update bug report template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5287 * docs: update Tutorial by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5285 * docs: improve modules.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5281 -* feat: add valid_url_strict rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5268 * docs: improve routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5284 * docs: fix RST format in caching.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5291 -* Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 * Prep for 4.1.5 release by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5293 * 4.1.5 Ready code by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5294 From a32754ca55947df91038f55a7a9af57101debb24 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 11:54:45 +0900 Subject: [PATCH 023/407] docs: remove docs PRs --- CHANGELOG.md | 63 ---------------------------------------------------- 1 file changed, 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 974a7dab4a7a..01b46aa6edd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,71 +49,32 @@ * Add entry to changelog for initial PHP 8.1 changes by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5054 * Apply NoCodeSeparatorCommentFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5053 -* docs: fix indentation of the changelog v4.1.4 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5057 * Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 * Document new coding style guide by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4825 * Update to phpdocumentor v3.1.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5020 * Add phive to tools in workflow by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5063 * Test fixing apidocs action by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5064 -* docs: fix upgrade_414 format by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5067 -* docs: update coding-standard links by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5068 * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 -* docs: add session table change for upgrade by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5069 -* docs: update PSR Compliance (PSR-12) by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5070 * Update rector/rector requirement from 0.11.52 to 0.11.53 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5071 -* docs: fix view_parser by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5072 -* docs: small fixes for entities by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5077 -* docs: fix db_forge by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5076 -* docs: extended upgrading from CI3 to CI4 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5078 -* docs: add about upgrading migration table by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5079 -* docs: rename v4.2.0 to v4.1.5 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5081 * [Rector] Clean up rector skip config by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5086 -* docs: fix query_builder RST format by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5083 -* docs: fix sample code in upgrade_routing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5084 -* docs: small fixes for configuration by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5085 -* docs: fix indentation for migration by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5089 -* docs: add new line at end of file by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5090 -* docs: fix indentation for testing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5091 * Fix typo in Config/Factories.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5092 -* docs: fix api responses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5093 * Remove --using-cache=no from php-cs-fixer in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5095 -* docs: fix cli library by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5099 * Add composer scripts for coding style by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5098 -* docs: replace tab with space by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5102 * [Rector] Apply Rector: SimplifyEmptyArrayCheckRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5101 -* docs: replace tab with space by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5105 -* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5109 -* docs: describe in detail how to add a service by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5112 -* docs: update debugging by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5111 -* docs: fix 404 link by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5119 -* docs: fix indentation of list by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5120 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 -* docs: small improvement Upgrading from 3.x to 4.x by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5121 -* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5122 -* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5130 * Fix Forge test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5135 * Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 -* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5140 * chore(deps-dev): update rector/rector requirement from 0.11.53 to 0.11.54 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5144 -* docs: fix sample code in user_agent.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5146 -* docs: replace tabs with spaces by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5145 * chore(deps): bump actions/github-script from 4 to 5 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5143 * Fix MemcachedHandlerTest::testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5147 * add SECURITY.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5123 * chore(deps-dev): update rector/rector requirement from 0.11.54 to 0.11.55 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5151 -* docs: fix link styleguide.md in CONTRIBUTING.md by @Felipebros in https://github.com/codeigniter4/CodeIgniter4/pull/5152 -* docs: fix Google.com to DuckDuckGo.com by @Felipebros in https://github.com/codeigniter4/CodeIgniter4/pull/5153 * chore(deps-dev): update rector/rector requirement from 0.11.55 to 0.11.56 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5154 -* docs: fix tests/README by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5166 -* docs: fix classname for testing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5169 -* docs: fix coding style in uploaded_files.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5174 * fix typo by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/5124 * (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 * Add tabs detector for RST files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5165 * chore(deps-dev): update rector/rector requirement from 0.11.56 to 0.11.57 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5177 -* docs: fix 404 links to sytle guide by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5167 -* docs: convert `contributing/*.rst` to `*.md` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5180 * Enable `no_alternative_syntax` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5181 * Add support for new fixers added in php-cs-fixer v3.2.0 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5175 * Refactor/optimise starter's tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5158 @@ -125,44 +86,27 @@ * Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 * Change behavior of `class_attributes_separation` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5176 * Move PR template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5191 -* docs: rework contributing by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5183 * Update admin/README.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5199 * Update README by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5197 -* Update CSRF related docs by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5198 -* docs: Github -> GitHub by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5203 * chore(deps-dev): update rector/rector requirement from 0.11.57 to 0.11.58 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5204 -* docs: small improvement in debugging by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5208 * Add `@group CacheLive` to tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5209 -* docs: remove link to Model in routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5210 -* docs: unify the decoration of app/Config/*.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5213 * chore(deps-dev): update rector/rector requirement from 0.11.58 to 0.11.59 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5219 -* docs: improve Form Validation Tutorial by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5223 -* Improve contributing docs by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5222 * Fix typo in @var classname in Tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5216 -* docs: add caution on filtering to routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5212 * chore(deps-dev): update rector/rector requirement from 0.11.59 to 0.11.60 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5225 * Improve tests/README.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5221 * add escape to identifiers for document. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5195 -* docs: improve Upgrading 4.1.5 page format by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5232 * Rename toolbar loader to be a regular JS file by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5224 * Remove invalid @runTestsInSeparateProcesses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5217 * [HTTP] Update Http Status Description based on latest iana.org by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5235 * Fix user guide on CSRF by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5230 * Remove CSRF properties by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5231 -* docs: improve validation.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5233 * [Rector] Using LevelSetList::UP_TO_PHP_73 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5239 * Switch PHPCPD to tool by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5240 -* docs: fix installation/upgrade_4xx.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5238 -* docs: fix format of testing/overview.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5237 * Fix Publisher test failures on macOS by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5211 -* docs: fix typography.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5241 * Add CSRF test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5236 * Fix TimeTest::testToFormattedDateString() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5245 -* docs: decorate `.env` with `**` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5248 * style: global_namespace_import true by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5250 * Fix CreateDatabaseTest::testCreateDatabase() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5244 -* docs: fix security_helper.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5252 -* docs: fix upgrade_security.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5253 * Cleanup php-cs-fixer config files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5254 * Optimize `builds` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5255 * Replace explicit calls to `Services::reset()` in tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5259 @@ -176,17 +120,10 @@ * Simplify logic of `number_to_roman` function by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5270 * [Rector] Refactor UnderscoreToCamelCaseVariableNameRector so no longer require symplify/package-builder by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5271 * Refactor FiltersTest.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5242 -* docs: add how to fix code with Rector by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5273 -* docs: fix html_helper.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5276 -* docs: move CSRF Protection Methods section up by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5275 * Fix compatibility of `PgSql\Result` on closing the result instance by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5279 * Fix compatibility of Postgres result for PHP 8.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5278 * [Rector] Remove FixClassCaseSensitivityNameRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5288 * Update bug report template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5287 -* docs: update Tutorial by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5285 -* docs: improve modules.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5281 -* docs: improve routing.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5284 -* docs: fix RST format in caching.rst by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5291 * Prep for 4.1.5 release by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5293 * 4.1.5 Ready code by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5294 From 4299a59017cfdfab0b90efd7ace44de6c6ce0f92 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 11:59:58 +0900 Subject: [PATCH 024/407] docs: remove chore PRs --- CHANGELOG.md | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01b46aa6edd5..0c9d19058984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,81 +51,40 @@ * Apply NoCodeSeparatorCommentFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5053 * Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 * Document new coding style guide by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4825 -* Update to phpdocumentor v3.1.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5020 -* Add phive to tools in workflow by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5063 -* Test fixing apidocs action by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5064 * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 -* Update rector/rector requirement from 0.11.52 to 0.11.53 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5071 -* [Rector] Clean up rector skip config by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5086 * Fix typo in Config/Factories.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5092 -* Remove --using-cache=no from php-cs-fixer in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5095 -* Add composer scripts for coding style by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5098 -* [Rector] Apply Rector: SimplifyEmptyArrayCheckRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5101 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 * Fix Forge test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5135 * Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 -* chore(deps-dev): update rector/rector requirement from 0.11.53 to 0.11.54 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5144 -* chore(deps): bump actions/github-script from 4 to 5 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5143 * Fix MemcachedHandlerTest::testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5147 -* add SECURITY.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5123 -* chore(deps-dev): update rector/rector requirement from 0.11.54 to 0.11.55 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5151 -* chore(deps-dev): update rector/rector requirement from 0.11.55 to 0.11.56 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5154 * fix typo by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/5124 * (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 -* Add tabs detector for RST files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5165 -* chore(deps-dev): update rector/rector requirement from 0.11.56 to 0.11.57 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5177 -* Enable `no_alternative_syntax` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5181 -* Add support for new fixers added in php-cs-fixer v3.2.0 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5175 * Refactor/optimise starter's tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5158 * Add unit test to ensure named binds don't get replaced in binded values by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5184 * Fix PHPDoc for Security by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5187 * Fix Cache testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5189 -* Remove coverage.txt by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5188 -* chore: add Database in bug report template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5182 * Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 -* Change behavior of `class_attributes_separation` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5176 -* Move PR template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5191 -* Update admin/README.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5199 -* Update README by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5197 -* chore(deps-dev): update rector/rector requirement from 0.11.57 to 0.11.58 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5204 * Add `@group CacheLive` to tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5209 -* chore(deps-dev): update rector/rector requirement from 0.11.58 to 0.11.59 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5219 * Fix typo in @var classname in Tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5216 -* chore(deps-dev): update rector/rector requirement from 0.11.59 to 0.11.60 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5225 -* Improve tests/README.md by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5221 * add escape to identifiers for document. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5195 * Rename toolbar loader to be a regular JS file by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5224 * Remove invalid @runTestsInSeparateProcesses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5217 * [HTTP] Update Http Status Description based on latest iana.org by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5235 * Fix user guide on CSRF by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5230 * Remove CSRF properties by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5231 -* [Rector] Using LevelSetList::UP_TO_PHP_73 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5239 -* Switch PHPCPD to tool by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5240 * Fix Publisher test failures on macOS by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5211 * Add CSRF test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5236 * Fix TimeTest::testToFormattedDateString() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5245 -* style: global_namespace_import true by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5250 * Fix CreateDatabaseTest::testCreateDatabase() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5244 -* Cleanup php-cs-fixer config files by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5254 -* Optimize `builds` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5255 * Replace explicit calls to `Services::reset()` in tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5259 * Remove static variables for PHP 8.1 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5262 * Speed up `CommonSingleServiceTest` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5258 -* Disable blank issues by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5257 * Replace usage of `FILTER_SANITIZE_STRING` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5263 -* Enable `ordered_class_elements` rule by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5265 -* Convert bug report to new syntax by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5264 -* Enclose the PR template's notes as comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5256 * Simplify logic of `number_to_roman` function by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5270 -* [Rector] Refactor UnderscoreToCamelCaseVariableNameRector so no longer require symplify/package-builder by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5271 * Refactor FiltersTest.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5242 * Fix compatibility of `PgSql\Result` on closing the result instance by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5279 * Fix compatibility of Postgres result for PHP 8.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5278 -* [Rector] Remove FixClassCaseSensitivityNameRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5288 -* Update bug report template by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5287 -* Prep for 4.1.5 release by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5293 -* 4.1.5 Ready code by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5294 **New Contributors** From 4b1a4a140d404725f70a38a8d74e95cb8c3023cd Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:04:06 +0900 Subject: [PATCH 025/407] docs: remove docs PRs --- CHANGELOG.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c9d19058984..fc2a3e32aadf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,10 +47,8 @@ **Merged pull requests:** -* Add entry to changelog for initial PHP 8.1 changes by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5054 * Apply NoCodeSeparatorCommentFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5053 * Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 -* Document new coding style guide by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4825 * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 * Fix typo in Config/Factories.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5092 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 @@ -62,16 +60,11 @@ * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 * Refactor/optimise starter's tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5158 * Add unit test to ensure named binds don't get replaced in binded values by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5184 -* Fix PHPDoc for Security by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5187 * Fix Cache testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5189 * Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 -* Add `@group CacheLive` to tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5209 -* Fix typo in @var classname in Tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5216 -* add escape to identifiers for document. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5195 * Rename toolbar loader to be a regular JS file by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5224 * Remove invalid @runTestsInSeparateProcesses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5217 * [HTTP] Update Http Status Description based on latest iana.org by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5235 -* Fix user guide on CSRF by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5230 * Remove CSRF properties by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5231 * Fix Publisher test failures on macOS by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5211 * Add CSRF test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5236 From 3e7972e6bb7595842faefb406d1f23ce524a7c2b Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:04:47 +0900 Subject: [PATCH 026/407] docs: remove chore PRs --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc2a3e32aadf..d523e37787c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,6 @@ **Merged pull requests:** -* Apply NoCodeSeparatorCommentFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5053 * Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 * Fix typo in Config/Factories.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5092 From 8e11120a721b72e1e9b5aff3d5108c0de891a4e4 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:05:27 +0900 Subject: [PATCH 027/407] docs: remove docs PRs --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d523e37787c7..e4c06281a8ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,7 +49,6 @@ * Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 -* Fix typo in Config/Factories.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5092 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 * Fix Forge test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5135 * Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 From be2b7d3ca00951c9867ba4027043c959169b4293 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:06:43 +0900 Subject: [PATCH 028/407] docs: remove test PRs --- CHANGELOG.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4c06281a8ad..f09a50b8e5cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,30 +50,17 @@ * Merge branch '4.2' by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5060 * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 -* Fix Forge test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5135 * Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 -* Fix MemcachedHandlerTest::testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5147 * fix typo by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/5124 * (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 -* Refactor/optimise starter's tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5158 -* Add unit test to ensure named binds don't get replaced in binded values by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5184 -* Fix Cache testGetMetaData() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5189 * Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 * Rename toolbar loader to be a regular JS file by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5224 -* Remove invalid @runTestsInSeparateProcesses by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5217 * [HTTP] Update Http Status Description based on latest iana.org by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5235 * Remove CSRF properties by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5231 -* Fix Publisher test failures on macOS by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5211 -* Add CSRF test by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5236 -* Fix TimeTest::testToFormattedDateString() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5245 -* Fix CreateDatabaseTest::testCreateDatabase() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5244 -* Replace explicit calls to `Services::reset()` in tests by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5259 * Remove static variables for PHP 8.1 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5262 -* Speed up `CommonSingleServiceTest` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5258 * Replace usage of `FILTER_SANITIZE_STRING` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5263 * Simplify logic of `number_to_roman` function by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5270 -* Refactor FiltersTest.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5242 * Fix compatibility of `PgSql\Result` on closing the result instance by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5279 * Fix compatibility of Postgres result for PHP 8.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5278 From 410d83694b25f170a11e2ccde08c322d3750c172 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:07:19 +0900 Subject: [PATCH 029/407] docs: remove docs PRs --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f09a50b8e5cb..51d592be71e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,6 @@ * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 * Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 -* fix typo by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/5124 * (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 * Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 From 36475a2bfd8eb7a0691eff982b0f10e5265b02b8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:09:06 +0900 Subject: [PATCH 030/407] docs: move Fixed PRs --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51d592be71e8..ef65b3c7f942 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ * fix: module filters are not discovered when using route filters by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5280 * Update 'updated_at' when enabled in replace() by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4684 * IncomingRequest - Trim trailing slash by @najdanovicivan in https://github.com/codeigniter4/CodeIgniter4/pull/4974 +* (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 **Implemented enhancements:** @@ -51,7 +52,6 @@ * Update to latest laminas-escaper 2.9.0 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5065 * Remove unintended dead code in pre-commit by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5116 * Adjust orange color in debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5136 -* (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 * Extract method to get prefix for DB access function by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5178 * Improve `model()` auto-completion by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5186 * Rename toolbar loader to be a regular JS file by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5224 From 3e757ed0e83cd6bc14a201b82b0227ea26c97f38 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:47:40 +0900 Subject: [PATCH 031/407] docs: remove unmerged PR which is included in other PR --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef65b3c7f942..956b79b6530f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,6 @@ * Fix GC issue when session lifetime is set to 0 by @lf-uraku-yuki in https://github.com/codeigniter4/CodeIgniter4/pull/4744 * Fix wrong helper path resolution by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5246 * Fix: remove CURLRequest headers sharing from $_SERVER by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5249 -* Fix CURLRequest extra headers by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5218 * Fix Localization not working/being ignored for 404 page by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5267 * fix: module filters are not discovered when using route filters by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5280 * Update 'updated_at' when enabled in replace() by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4684 From bead2b897ad9991317fb95e65ee1e7146e2f4a71 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:51:23 +0900 Subject: [PATCH 032/407] docs: sort enhancements PRs Grouped by function --- CHANGELOG.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 956b79b6530f..77e91ede321b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,17 +33,16 @@ **Implemented enhancements:** -* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 -* Multiple filters for a route and classname filter by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5128 * feat: `_` can be used as separators in environment variable names by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5156 +* Multiple filters for a route and classname filter by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5128 * Feature - Mark duplicate queries by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5185 * [Debug] Add formatted query string to timeline. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5196 -* Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171 * [Debug] Improve keyword highlighting and escaping of query strings. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5200 +* Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 +* Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 * Add Session based CSRF Protection by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5201 * Add CSRF Protection for PUT/PATCH/DELETE by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5228 * feat: add valid_url_strict rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5268 -* Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 **Merged pull requests:** From e1ed6865ec428594ec18f95a9887d63b2804ba37 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 12:59:57 +0900 Subject: [PATCH 033/407] docs: sort Fixed PRs --- CHANGELOG.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77e91ede321b..bfcf64840267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,30 +6,30 @@ **Fixed bugs:** -* Fixes and enhancements to Exceptions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5052 * Fix entity name generation when bundled in model by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5055 -* Fix variable variable `$$id` in RedisHandler by @Terrorboy in https://github.com/codeigniter4/CodeIgniter4/pull/5062 -* Previous Responses by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5034 +* Fix `Model::__call` throwing `BadMethodCallException` on empty results by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5139 +* Fixed an issue where the dropForeginKey method would execute an empty query when the dropConstraintStr property was empty. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5173 +* Update 'updated_at' when enabled in replace() by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4684 * Fix query binding with two colons in query by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5117 * Fixed the problem that _createTable does not take into account that it returns true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5133 -* Fix color not updated in several places of the precompiled CSS by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5155 -* Fix `Model::__call` throwing `BadMethodCallException` on empty results by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5139 +* Fixed a problem with not run escape for identities in like when `insensitiveSearch` is true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5170 +* Fixed an issue where an unnecessary prefix was given when the random number was a column. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5179 * Error when value is an object - validating api data by @daycry in https://github.com/codeigniter4/CodeIgniter4/pull/5142 +* Fix color not updated in several places of the precompiled CSS by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5155 * Fix debugbar styles printing by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5100 * Fix highlighting in database debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5129 -* Fixed an issue where the dropForeginKey method would execute an empty query when the dropConstraintStr property was empty. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5173 * Fix debug toolbar db connection count by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5172 -* Fixed a problem with not run escape for identities in like when `insensitiveSearch` is true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5170 -* Fixed an issue where an unnecessary prefix was given when the random number was a column. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5179 * Fix CSRF filter does not work when set it to only post by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5194 * Fix GC issue when session lifetime is set to 0 by @lf-uraku-yuki in https://github.com/codeigniter4/CodeIgniter4/pull/4744 * Fix wrong helper path resolution by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5246 * Fix: remove CURLRequest headers sharing from $_SERVER by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5249 * Fix Localization not working/being ignored for 404 page by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5267 * fix: module filters are not discovered when using route filters by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5280 -* Update 'updated_at' when enabled in replace() by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4684 * IncomingRequest - Trim trailing slash by @najdanovicivan in https://github.com/codeigniter4/CodeIgniter4/pull/4974 +* Previous Responses by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5034 * (Paging) Ensure page validity by @puschie286 in https://github.com/codeigniter4/CodeIgniter4/pull/5125 +* Fix variable variable `$$id` in RedisHandler by @Terrorboy in https://github.com/codeigniter4/CodeIgniter4/pull/5062 +* Fixes and enhancements to Exceptions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5052 **Implemented enhancements:** From c674b93d6c9ba4db6f00bf5a2a83b204d37af3e1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 14:15:33 +0900 Subject: [PATCH 034/407] docs: fix missing line break --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfcf64840267..48a24eb6d37c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,8 @@ * Feature - Mark duplicate queries by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5185 * [Debug] Add formatted query string to timeline. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5196 * [Debug] Improve keyword highlighting and escaping of query strings. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5200 -* Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 +* Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171 +* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 * Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 * Add Session based CSRF Protection by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5201 * Add CSRF Protection for PUT/PATCH/DELETE by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5228 From 303d0f0ba3c7e7f1c169fe51e47f497b39da1f7d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 14:27:33 +0900 Subject: [PATCH 035/407] docs: move PR from enhancements to Fixed --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48a24eb6d37c..70656a3f6e50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * Fix highlighting in database debug toolbar by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5129 * Fix debug toolbar db connection count by @danielTiringer in https://github.com/codeigniter4/CodeIgniter4/pull/5172 * Fix CSRF filter does not work when set it to only post by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5194 +* Add CSRF Protection for PUT/PATCH/DELETE by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5228 * Fix GC issue when session lifetime is set to 0 by @lf-uraku-yuki in https://github.com/codeigniter4/CodeIgniter4/pull/4744 * Fix wrong helper path resolution by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5246 * Fix: remove CURLRequest headers sharing from $_SERVER by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5249 @@ -42,7 +43,6 @@ * Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 * Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 * Add Session based CSRF Protection by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5201 -* Add CSRF Protection for PUT/PATCH/DELETE by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5228 * feat: add valid_url_strict rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5268 **Merged pull requests:** From 10f0279186f2107cd8f6ba3251dbd777e5a0436c Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 14:51:14 +0900 Subject: [PATCH 036/407] docs: move PR from enhancements to Fixed --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70656a3f6e50..1a77c0a4d13a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * Fixed the problem that _createTable does not take into account that it returns true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5133 * Fixed a problem with not run escape for identities in like when `insensitiveSearch` is true. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5170 * Fixed an issue where an unnecessary prefix was given when the random number was a column. by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5179 +* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 * Error when value is an object - validating api data by @daycry in https://github.com/codeigniter4/CodeIgniter4/pull/5142 * Fix color not updated in several places of the precompiled CSS by @vlakoff in https://github.com/codeigniter4/CodeIgniter4/pull/5155 * Fix debugbar styles printing by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5100 @@ -40,7 +41,6 @@ * [Debug] Add formatted query string to timeline. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5196 * [Debug] Improve keyword highlighting and escaping of query strings. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5200 * Add `dropKey` method to `Forge` by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5171 -* Always escape identifiers in the set(), setUpdateBatch(), and insertBatch() by @ytetsuro in https://github.com/codeigniter4/CodeIgniter4/pull/5132 * Reduce memory usage of insertBatch(), updateBatch() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5202 * Add Session based CSRF Protection by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5201 * feat: add valid_url_strict rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/5268 From 40154ac4827b7e84f6f9e448fa186a9930b9269e Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 16:06:12 +0900 Subject: [PATCH 037/407] chore: add .github/release.yml See https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#example-configuration --- .github/release.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/release.yml diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000000..de6e982d91a6 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,23 @@ +changelog: + exclude: + authors: + - dependabot + categories: + - title: Breaking Changes + labels: + - 'breaking change' + - title: Fixed Bugs + labels: + - bug + - title: New Features + labels: + - 'new feature' + - title: Enhancements + labels: + - enhancement + - title: Refactoring + labels: + - refactor + - title: Others (Only for checking. Remove this category) + labels: + - "*" From 42b29469c0dadcd47664c5d64331e3b1edd8c634 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 16:06:37 +0900 Subject: [PATCH 038/407] docs: add "Labeling PRs" --- admin/RELEASE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/admin/RELEASE.md b/admin/RELEASE.md index 822bd1f5f154..7eb3fe2c0cc3 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -4,6 +4,17 @@ > Updated for `4.1.2` on May 17, 2021. > -MGatner +## Labeling PRs + +To auto-generate changelog, each PR to be listed in changelog must have one of the following [labels](https://github.com/codeigniter4/CodeIgniter4/labels): +- **bug** ... PRs that fix bugs +- **enhancement** ... PRs to improve existing functionalities +- **new feature** ... PRs for new features +- **refactor** ... PRs to refactor + +And a PRs that has the breaking changes must have the following label: +- **breaking change** ... PRs that may break existing functionalities + ## Preparation * Work off direct clones of the repos so the release branches persist for a time From 4c2b1c478882e87185c662182ee0dab221bc7af3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Nov 2021 16:45:37 +0900 Subject: [PATCH 039/407] docs: update changelogs/v4.1.5.rst --- user_guide_src/source/changelogs/v4.1.5.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/user_guide_src/source/changelogs/v4.1.5.rst b/user_guide_src/source/changelogs/v4.1.5.rst index 3e8fb8f629f0..9cd543f181e2 100644 --- a/user_guide_src/source/changelogs/v4.1.5.rst +++ b/user_guide_src/source/changelogs/v4.1.5.rst @@ -23,6 +23,14 @@ Enhancements - Added Cache config for reserved characters - The ``addForeignKey`` function of the ``Forge`` class can now define composite foreign keys in an array - The ``dropKey`` function of the ``Forge`` class can remove key +- Now ``_`` can be used as separators in environment variable +- Added Multiple filters for a route and Classname filter +- Reduced memory usage of ``insertBatch()`` and ``updateBatch()`` +- Added Session based CSRF Protection +- Added ``valid_url_strict`` rule for ``Validation`` +- Debug Toolbar + - Added formatted query string to timeline + - Improved keyword highlighting and escaping of query strings Changes ======= @@ -33,3 +41,8 @@ Deprecations ============ - Deprecated ``CodeIgniter\\Cache\\Handlers\\BaseHandler::RESERVED_CHARACTERS`` in favor of the new config property + +Bugs Fixed +========== + +See the repo's `CHANGELOG.md `_ for a complete list of bugs fixed. From bea512e5ac0af5e576162d4c08e99b408b2fa0b0 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 1 Nov 2021 15:53:56 +0700 Subject: [PATCH 040/407] [PHPStan] Upgrade to PHPStan 1.0 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b7b3176e055f..a79e6926b882 100644 --- a/composer.json +++ b/composer.json @@ -21,10 +21,10 @@ "mikey179/vfsstream": "^1.6", "nexusphp/cs-config": "^3.3", "nexusphp/tachycardia": "^1.0", - "phpstan/phpstan": "^0.12.91", + "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.11.60" + "rector/rector": "dev-main" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" From 6d164b6b84590b58241ca6bf2342014ac4578c77 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 1 Nov 2021 15:56:01 +0700 Subject: [PATCH 041/407] use excludePaths config --- phpstan.neon.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 73e3a7a3a545..b7bde80c3819 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -18,7 +18,7 @@ parameters: treatPhpDocTypesAsCertain: false bootstrapFiles: - system/Test/bootstrap.php - excludes_analyse: + excludePaths: - app/Views/errors/cli/* - app/Views/errors/html/* - system/Commands/Generators/Views/* From 758c6ae0eee9a19fd1194e0c5788579e85cf17b2 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 1 Nov 2021 15:58:33 +0700 Subject: [PATCH 042/407] remove ignored phpstan in View\Table --- system/View/Table.php | 1 - 1 file changed, 1 deletion(-) diff --git a/system/View/Table.php b/system/View/Table.php index d57a7092de00..4d8ac37e230c 100644 --- a/system/View/Table.php +++ b/system/View/Table.php @@ -181,7 +181,6 @@ public function makeColumns($array = [], $columnLimit = 0) $new[] = $temp; } while (count($array) > 0); - // @phpstan-ignore-next-line return $new; } From e0de21a99a05bdd8941b65cda3fbb90d7caff4f1 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 1 Nov 2021 16:17:13 +0700 Subject: [PATCH 043/407] ignoring errors --- phpstan.neon.dist | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b7bde80c3819..bf23eb5303ed 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -39,6 +39,19 @@ parameters: - '#Method CodeIgniter\\Validation\\ValidationInterface::run\(\) invoked with 3 parameters, 0-2 required#' - '#Negated boolean expression is always (true|false)#' - '#Return type \(bool\) of method CodeIgniter\\HTTP\\Files\\UploadedFile::move\(\) should be compatible with return type \(CodeIgniter\\Files\\File\) of method CodeIgniter\\Files\\File::move\(\)#' + - '#.*\son left side of \?\? is not nullable#' + - '#While loop condition is always true#' + - '#Right side of && is always true#' + - '#.*in isset\(\) is not nullable#' + - '#.*in empty\(\) is not falsy#' + - '#.*on left side of \?\? always exists and is not nullable#' + - '#Variable \$error on left side of \?\? always exists and is always null#' + - '#Variable \$config in empty\(\) always exists and is not falsy#' + - '#If condition is always true#' + - '#Dead catch - CodeIgniter\\Exceptions\\PageNotFoundException is never thrown in the try block#' + - '#.* in isset\(\) does not exist#' + - '#Variable \$mockService in empty\(\) always exists and is always falsy#' + - '#PHPDoc type string\|null of property CodeIgniter\\Images\\Handlers\\ImageMagickHandler::\$resource is not covariant with PHPDoc type resource\|null of overridden property CodeIgniter\\Images\\Handlers\\BaseHandler::\$resource#' parallel: processTimeout: 300.0 scanDirectories: From 1b39245ed35df948cfb11e9b014f900d91d74a8f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 1 Nov 2021 17:14:49 +0700 Subject: [PATCH 044/407] remove symplify/package-builder dep --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index a79e6926b882..7cf5fa8c152c 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "fakerphp/faker": "^1.9", "friendsofphp/php-cs-fixer": "^3.1", "mikey179/vfsstream": "^1.6", + "nette/utils": "^3.2", "nexusphp/cs-config": "^3.3", "nexusphp/tachycardia": "^1.0", "phpstan/phpstan": "^1.0", From b437088f1480bcd04d0077318f34964583c79d28 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 1 Nov 2021 19:59:09 +0700 Subject: [PATCH 045/407] remove nette/utils --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 7cf5fa8c152c..a79e6926b882 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,6 @@ "fakerphp/faker": "^1.9", "friendsofphp/php-cs-fixer": "^3.1", "mikey179/vfsstream": "^1.6", - "nette/utils": "^3.2", "nexusphp/cs-config": "^3.3", "nexusphp/tachycardia": "^1.0", "phpstan/phpstan": "^1.0", From c19875c1baf74017ee954c901c30797e9bc85fd9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 9 Nov 2021 19:27:29 +0700 Subject: [PATCH 046/407] update to composer 0.12 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a79e6926b882..31d3eddae2e0 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "dev-main" + "rector/rector": "0.12.0" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" From 707e847ad507e3073c96606f67cf8e096aadc6a6 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 9 Nov 2021 19:37:57 +0700 Subject: [PATCH 047/407] re-run rector --- rector.php | 4 ++++ system/View/Table.php | 2 +- .../Rector/UnderscoreToCamelCaseVariableNameRector.php | 10 +--------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/rector.php b/rector.php index 4a5fde83a45c..b95e240edf57 100644 --- a/rector.php +++ b/rector.php @@ -39,6 +39,7 @@ use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector; use Rector\Php70\Rector\FuncCall\RandomFunctionRector; +use Rector\Php70\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector; use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; @@ -109,6 +110,9 @@ // use mt_rand instead of random_int on purpose on non-cryptographically random RandomFunctionRector::class, + + // buggy on rector 0.12.0 + ThisCallOnStaticMethodToStaticCallRector::class, ]); // auto import fully qualified class names diff --git a/system/View/Table.php b/system/View/Table.php index 4d8ac37e230c..539fd193c2a3 100644 --- a/system/View/Table.php +++ b/system/View/Table.php @@ -179,7 +179,7 @@ public function makeColumns($array = [], $columnLimit = 0) } $new[] = $temp; - } while (count($array) > 0); + } while ($array !== []); return $new; } diff --git a/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php b/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php index f87222bb2d5d..206af5955ca3 100644 --- a/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php +++ b/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php @@ -20,7 +20,6 @@ use PhpParser\Node\Stmt\Function_; use Rector\Core\Php\ReservedKeywordAnalyzer; use Rector\Core\Rector\AbstractRector; -use Rector\NodeNestingScope\ParentFinder; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -40,17 +39,10 @@ final class UnderscoreToCamelCaseVariableNameRector extends AbstractRector */ private $reservedKeywordAnalyzer; - /** - * @var ParentFinder - */ - private $parentFinder; - public function __construct( ReservedKeywordAnalyzer $reservedKeywordAnalyzer, - ParentFinder $parentFinder ) { $this->reservedKeywordAnalyzer = $reservedKeywordAnalyzer; - $this->parentFinder = $parentFinder; } public function getRuleDefinition(): RuleDefinition @@ -124,7 +116,7 @@ public function refactor(Node $node): ?Node private function updateDocblock(Variable $variable, string $variableName, string $camelCaseName): void { - $parentClassMethodOrFunction = $this->parentFinder->findByTypes($variable, [ClassMethod::class, Function_::class]); + $parentClassMethodOrFunction = $this->betterNodeFinder->findParentByTypes($variable, [ClassMethod::class, Function_::class]); if ($parentClassMethodOrFunction === null) { return; From 395b164866fb9fdb2295c458ed2a0cbe6f5e5bf0 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 9 Nov 2021 19:46:59 +0700 Subject: [PATCH 048/407] cs fix --- utils/Rector/UnderscoreToCamelCaseVariableNameRector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php b/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php index 206af5955ca3..690a63c6febe 100644 --- a/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php +++ b/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php @@ -40,7 +40,7 @@ final class UnderscoreToCamelCaseVariableNameRector extends AbstractRector private $reservedKeywordAnalyzer; public function __construct( - ReservedKeywordAnalyzer $reservedKeywordAnalyzer, + ReservedKeywordAnalyzer $reservedKeywordAnalyzer ) { $this->reservedKeywordAnalyzer = $reservedKeywordAnalyzer; } From e44008b8c74e514d96cd82f3d23438f126bf014d Mon Sep 17 00:00:00 2001 From: Najdanovic Ivan Date: Mon, 8 Nov 2021 18:08:57 +0100 Subject: [PATCH 049/407] Toolbar - Make it possible to turn off var data collection --- app/Config/Toolbar.php | 12 ++++++++++++ system/Debug/Toolbar.php | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/app/Config/Toolbar.php b/app/Config/Toolbar.php index 16a37e83c2b8..7183e1336a28 100644 --- a/app/Config/Toolbar.php +++ b/app/Config/Toolbar.php @@ -44,6 +44,18 @@ class Toolbar extends BaseConfig Events::class, ]; + /** + * -------------------------------------------------------------------------- + * Collect Var Data + * -------------------------------------------------------------------------- + * + * If set to false var data from the views will not be colleted. Usefull to + * avoid high memory usage when there are lots of data passed to the view. + * + * @var bool + */ + public $collectVarData = true; + /** * -------------------------------------------------------------------------- * Max History diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index b951e2ed9658..e3cc5b68fce4 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -310,6 +310,10 @@ protected function structureTimelineData(array $elements): array */ protected function collectVarData(): array { + if (! $this->config->collectVarData) { + return []; + } + $data = []; foreach ($this->collectors as $collector) { From c30e0b5940fec60f08b118d9ba3f6b26613b1578 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 10 Nov 2021 05:00:47 +0700 Subject: [PATCH 050/407] update to rector 0.12.1 --- composer.json | 2 +- rector.php | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 31d3eddae2e0..dcdfd339390a 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.12.0" + "rector/rector": "0.12.1" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" diff --git a/rector.php b/rector.php index b95e240edf57..4a5fde83a45c 100644 --- a/rector.php +++ b/rector.php @@ -39,7 +39,6 @@ use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector; use Rector\Php70\Rector\FuncCall\RandomFunctionRector; -use Rector\Php70\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector; use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; @@ -110,9 +109,6 @@ // use mt_rand instead of random_int on purpose on non-cryptographically random RandomFunctionRector::class, - - // buggy on rector 0.12.0 - ThisCallOnStaticMethodToStaticCallRector::class, ]); // auto import fully qualified class names From dc81868b6141b3ddcaf0f72f7c60a82723304d78 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 08:46:59 +0900 Subject: [PATCH 051/407] docs: add comma --- user_guide_src/source/database/connecting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/database/connecting.rst b/user_guide_src/source/database/connecting.rst index 65a3ed086d27..0280dbe5a71e 100644 --- a/user_guide_src/source/database/connecting.rst +++ b/user_guide_src/source/database/connecting.rst @@ -15,7 +15,7 @@ database available globally in that class. $db = \Config\Database::connect(); If the above function does **not** contain any information in the first -parameter it will connect to the default group specified in your database config +parameter, it will connect to the default group specified in your database config file. For most people, this is the preferred method of use. A convenience method exists that is purely a wrapper around the above line From 603e1792269fcf20ac788b69020b5a55486f3659 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 08:47:55 +0900 Subject: [PATCH 052/407] docs: improve parameters explanation --- user_guide_src/source/database/connecting.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/database/connecting.rst b/user_guide_src/source/database/connecting.rst index 0280dbe5a71e..67d9ac2e1aab 100644 --- a/user_guide_src/source/database/connecting.rst +++ b/user_guide_src/source/database/connecting.rst @@ -26,8 +26,10 @@ and is provided for your convenience:: Available Parameters -------------------- -#. The database group name, a string that must match the config class' property name. Default value is ``$config->defaultGroup``. -#. true/false (boolean). Whether to return the shared connection (see +**\\Config\\Database::connect($group = null, bool $getShared = true): BaseConnection** + +#. ``$group``: The database group name, a string that must match the config class' property name. Default value is ``$config->defaultGroup``. +#. ``$getShared``: true/false (boolean). Whether to return the shared connection (see Connecting to Multiple Databases below). Manually Connecting to a Database From deba152f05b9de590bf037460a0691c1917872fa Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 08:48:42 +0900 Subject: [PATCH 053/407] docs: fix variable name --- user_guide_src/source/database/connecting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/database/connecting.rst b/user_guide_src/source/database/connecting.rst index 67d9ac2e1aab..dca35a6e50d5 100644 --- a/user_guide_src/source/database/connecting.rst +++ b/user_guide_src/source/database/connecting.rst @@ -61,7 +61,7 @@ If you need to connect to more than one database simultaneously you can do so as follows:: $db1 = \Config\Database::connect('group_one'); - $db = \Config\Database::connect('group_two'); + $db2 = \Config\Database::connect('group_two'); Note: Change the words "group_one" and "group_two" to the specific group names you are connecting to. From 5a3fa54e37615eadc21bde204435c5e0afb96fb5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 08:49:04 +0900 Subject: [PATCH 054/407] docs: fix decoration for string in the code --- user_guide_src/source/database/connecting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/database/connecting.rst b/user_guide_src/source/database/connecting.rst index dca35a6e50d5..41a42e5f0f2f 100644 --- a/user_guide_src/source/database/connecting.rst +++ b/user_guide_src/source/database/connecting.rst @@ -63,7 +63,7 @@ do so as follows:: $db1 = \Config\Database::connect('group_one'); $db2 = \Config\Database::connect('group_two'); -Note: Change the words "group_one" and "group_two" to the specific +Note: Change the words ``group_one`` and ``group_two`` to the specific group names you are connecting to. .. note:: You don't need to create separate database configurations if you From 395f71fad77eb1bc192417b1b87fe1ffe34a509d Mon Sep 17 00:00:00 2001 From: Najdanovic Ivan Date: Wed, 10 Nov 2021 01:05:07 +0100 Subject: [PATCH 055/407] Update system/Debug/Toolbar.php Co-authored-by: Lonnie Ezell --- system/Debug/Toolbar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index e3cc5b68fce4..3502ae877caf 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -310,7 +310,7 @@ protected function structureTimelineData(array $elements): array */ protected function collectVarData(): array { - if (! $this->config->collectVarData) { + if (! ($this->config->collectVarData ?? true)) { return []; } From b45fb1e76d01995a0df78614fcca3ab6b533e204 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 10:22:54 +0900 Subject: [PATCH 056/407] dpcs: fix typo --- admin/RELEASE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/RELEASE.md b/admin/RELEASE.md index 7eb3fe2c0cc3..932ce34ec018 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -12,7 +12,7 @@ To auto-generate changelog, each PR to be listed in changelog must have one of t - **new feature** ... PRs for new features - **refactor** ... PRs to refactor -And a PRs that has the breaking changes must have the following label: +And PRs that have the breaking changes must have the following label: - **breaking change** ... PRs that may break existing functionalities ## Preparation From 5fe35fa6286fd11bc8f7fe658df17bf20e26b7b3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 10:23:16 +0900 Subject: [PATCH 057/407] docs: add about labeling PRs in the congtribution docs --- contributing/pull_request.md | 1 + contributing/workflow.md | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/contributing/pull_request.md b/contributing/pull_request.md index e08a5c110558..488e299d7000 100644 --- a/contributing/pull_request.md +++ b/contributing/pull_request.md @@ -225,6 +225,7 @@ The best way to contribute is to fork the CodeIgniter4 repository, and "clone" t 12. Make sure the tests pass to have a higher chance of merging. 13. [Push](https://docs.github.com/en/github/using-git/pushing-commits-to-a-remote-repository) your contribution branch to your fork. 14. Send a [pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork). +15. Label your pull request with the appropriate label if you can. See [Contribution workflow](./workflow.md) for Git workflow details. diff --git a/contributing/workflow.md b/contributing/workflow.md index 670727a89653..b2309df9477a 100644 --- a/contributing/workflow.md +++ b/contributing/workflow.md @@ -185,7 +185,6 @@ Make sure that the PR title is helpful for the maintainers and other developers. Add any comments appropriate, for instance asking for review. - **Note:** > If you do not provide a title or description for your PR, the odds of it being summarily rejected rise astronomically. @@ -203,6 +202,19 @@ If your PR does not follow our contribution guidelines, or is incomplete, the codebase maintainers will comment on it, pointing out what needs fixing. +### Labeling PRs + +If you have the privilege of labeling PRs, you can help the maintainers. + +Label your PRs with the one of the following [labels](https://github.com/codeigniter4/CodeIgniter4/labels): +- **bug** ... PRs that fix bugs +- **enhancement** ... PRs to improve existing functionalities +- **new feature** ... PRs for new features +- **refactor** ... PRs to refactor + +And if your PRs have the breaking changes, label the following label: +- **breaking change** ... PRs that may break existing functionalities + ## Cleanup If your PR is accepted and merged into the shared repository, you can From ec862343faef2f34c857148b9767e877cb32d17f Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 10:35:24 +0900 Subject: [PATCH 058/407] chore: replace `github.repos.` with `github.rest.repos.` --- .github/workflows/deploy-framework.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-framework.yml b/.github/workflows/deploy-framework.yml index 5a65f3bd1cfc..cdd23f3c7242 100644 --- a/.github/workflows/deploy-framework.yml +++ b/.github/workflows/deploy-framework.yml @@ -40,11 +40,11 @@ jobs: with: github-token: ${{secrets.ACCESS_TOKEN}} script: | - const release = await github.repos.getLatestRelease({ + const release = await github.rest.repos.getLatestRelease({ owner: context.repo.owner, repo: context.repo.repo }) - github.repos.createRelease({ + github.rest.repos.createRelease({ owner: context.repo.owner, repo: 'framework', tag_name: release.data.tag_name, @@ -85,11 +85,11 @@ jobs: with: github-token: ${{secrets.ACCESS_TOKEN}} script: | - const release = await github.repos.getLatestRelease({ + const release = await github.rest.repos.getLatestRelease({ owner: context.repo.owner, repo: context.repo.repo }) - github.repos.createRelease({ + github.rest.repos.createRelease({ owner: context.repo.owner, repo: 'appstarter', tag_name: release.data.tag_name, From fcb18f9ff0f61b97f4e56d0ac13ddd2635366c9a Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 17:41:11 +0900 Subject: [PATCH 059/407] docs: make `warning` security related explanation --- user_guide_src/source/database/query_builder.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index cb0771356098..a05fb25f8159 100755 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -295,14 +295,14 @@ methods: $where = "name='Joe' AND status='boss' OR status='active'"; $builder->where($where); - If you are using user-supplied data within the string, you MUST escape the +.. warning:: If you are using user-supplied data within the string, you MUST escape the data manually. Failure to do so could result in SQL injections. :: - $name = $builder->db->escape('Joe'); - $where = "name={$name} AND status='boss' OR status='active'"; - $builder->where($where); + $name = $builder->db->escape('Joe'); + $where = "name={$name} AND status='boss' OR status='active'"; + $builder->where($where); #. **Subqueries:** From d7523eb06a2d37b0f356d02b0562680130c83fe4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Nov 2021 21:21:12 +0000 Subject: [PATCH 060/407] chore(deps-dev): update rector/rector requirement from 0.12.1 to 0.12.3 (#5305) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index dcdfd339390a..93286a4f93f8 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.12.1" + "rector/rector": "0.12.3" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" From a41ef8624cf8c3f884c52f091dbf1a8199aad4c0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Nov 2021 08:06:30 +0900 Subject: [PATCH 061/407] chore: improve ISSUE_TEMPLATE/bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 135bd52b3fe9..ca357c2962bf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -13,8 +13,6 @@ body: whether still open or closed, related to your report**. If there is, your report will be closed promptly. - And if you are not using the [latest version](https://github.com/codeigniter4/CodeIgniter4/releases) of CodeIgniter, please update. - --- - type: dropdown @@ -35,6 +33,9 @@ body: id: codeigniter-version attributes: label: CodeIgniter4 Version + description: | + e.g. 4.1.5 + If you are not using the [latest version](https://github.com/codeigniter4/CodeIgniter4/releases), please check to see if the problem occurs with the latest version. validations: required: true @@ -69,6 +70,7 @@ body: id: database attributes: label: Database + description: e.g. MySQL 5.6, MariaDB 10.2, PostgreSQL 9.6 validations: required: false From cf0a5e65831ccd0f5db8cd184e8acd7d497a8151 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Nov 2021 11:09:01 +0900 Subject: [PATCH 062/407] docs: fix MigrationRunner::regress() Class Reference --- user_guide_src/source/dbmgmt/migration.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/dbmgmt/migration.rst b/user_guide_src/source/dbmgmt/migration.rst index 027c12d3dc70..9f748da69521 100644 --- a/user_guide_src/source/dbmgmt/migration.rst +++ b/user_guide_src/source/dbmgmt/migration.rst @@ -300,10 +300,10 @@ Class Reference This locates migrations for a namespace (or all namespaces), determines which migrations have not yet been run, and runs them in order of their version (namespaces intermingled). - .. php:method:: regress($batch, $group) + .. php:method:: regress($targetBatch, $group) - :param mixed $batch: previous batch to migrate down to; 1+ specifies the batch, 0 reverts all, negative refers to the relative batch (e.g., -3 means "three batches back") - :param mixed $group: database group name, if null default database group will be used. + :param int $targetBatch: previous batch to migrate down to; 1+ specifies the batch, 0 reverts all, negative refers to the relative batch (e.g., -3 means "three batches back") + :param ?string $group: database group name, if null default database group will be used. :returns: ``true`` on success, ``false`` on failure or no migrations are found :rtype: bool From c31730b55e61cd35cb1935ace2c473557a119ac6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Nov 2021 12:50:13 +0900 Subject: [PATCH 063/407] docs: add missing line break Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index ca357c2962bf..2c28200c36aa 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,7 +35,8 @@ body: label: CodeIgniter4 Version description: | e.g. 4.1.5 - If you are not using the [latest version](https://github.com/codeigniter4/CodeIgniter4/releases), please check to see if the problem occurs with the latest version. + If you are not using the [latest version](https://github.com/codeigniter4/CodeIgniter4/releases), please + check to see if the problem occurs with the latest version. validations: required: true From 5f5fdf03beddded89e70a622a739c5d576c42d13 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Nov 2021 13:59:09 +0900 Subject: [PATCH 064/407] docs: fix sample code variable names There is no $collection in app/Config/Routes.php. --- user_guide_src/source/incoming/routing.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 899ad0797a30..5dade8d13f3d 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -188,11 +188,12 @@ While the add() method is simple to use, it is often handier to work with multip the ``map()`` method. Instead of calling the ``add()`` method for each route that you need to add, you can define an array of routes and then pass it as the first parameter to the ``map()`` method:: - $routes = []; - $routes['product/(:num)'] = 'Catalog::productLookupById'; - $routes['product/(:alphanum)'] = 'Catalog::productLookupByName'; + $multipleRoutes = [ + 'product/(:num)' => 'Catalog::productLookupById', + 'product/(:alphanum)' => 'Catalog::productLookupByName', + ]; - $collection->map($routes); + $routes->map($multipleRoutes); Redirecting Routes ================== @@ -415,7 +416,7 @@ Limit to Hostname You can restrict groups of routes to function only in certain domain or sub-domains of your application by passing the "hostname" option along with the desired domain to allow it on as part of the options array:: - $collection->get('from', 'to', ['hostname' => 'accounts.example.com']); + $routes->get('from', 'to', ['hostname' => 'accounts.example.com']); This example would only allow the specified hosts to work if the domain exactly matched "accounts.example.com". It would not work under the main site at "example.com". From bcedd1e7caee9cb3dbd23d9465ed613502f487c7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 09:22:51 +0900 Subject: [PATCH 065/407] fix: add workaround for upgraded users who not update Config\Exceptions Uncaught ErrorException: Undefined property: Config\Exceptions::$sensitiveDataInTrace --- system/Debug/Exceptions.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php index 04556c5c4f20..c594bc4eac9f 100644 --- a/system/Debug/Exceptions.php +++ b/system/Debug/Exceptions.php @@ -70,6 +70,11 @@ public function __construct(ExceptionsConfig $config, IncomingRequest $request, $this->config = $config; $this->request = $request; $this->response = $response; + + // workaround for upgraded users + if (! isset($this->config->sensitiveDataInTrace)) { + $this->config->sensitiveDataInTrace = []; + } } /** From 0e084ee926e3ace038b2f0bafd2fd34f964ce9a0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 12:51:17 +0900 Subject: [PATCH 066/407] docs: improve How-to Guide --- contributing/pull_request.md | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/contributing/pull_request.md b/contributing/pull_request.md index 488e299d7000..5bcc3511e86c 100644 --- a/contributing/pull_request.md +++ b/contributing/pull_request.md @@ -214,18 +214,28 @@ The best way to contribute is to fork the CodeIgniter4 repository, and "clone" t 2. Go to the [CodeIgniter4 repository](https://github.com/codeigniter4/CodeIgniter4). 3. [Fork](https://help.github.com/en/articles/fork-a-repo) it (to your GitHub account). 4. [Clone](https://help.github.com/en/articles/cloning-a-repository) your CodeIgniter repository: `git@github.com:/CodeIgniter4.git` -5. Create a new [branch](https://help.github.com/en/articles/about-branches) in your project for each set of changes you want to make. -6. Fix existing bugs on the [Issue tracker](https://github.com/codeigniter4/CodeIgniter4/issues) after confirming that no one else is working on them. -7. [Commit](https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project) the changed files in your contribution branch. -8. Commit messages are expected to be descriptive of what you changed specifically. Commit messages like - "Fixes #1234" would be asked by the reviewer to be revised. + - `> git clone git@github.com:/CodeIgniter4.git` +5. Install Composer dependencies. + - `> cd CodeIgniter4/` + - `> composer install` +6. Create a new [branch](https://help.github.com/en/articles/about-branches) in your project for each set of changes you want to make. + - `> git checkout -b ` +7. Fix existing bugs on the [Issue tracker](https://github.com/codeigniter4/CodeIgniter4/issues) after confirming that no one else is working on them. +8. [Commit](https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project) the changed files in your contribution branch. + - `> git commit` + - Commit messages are expected to be descriptive of what you changed specifically. Commit messages like + "Fixes #1234" would be asked by the reviewer to be revised. 9. If there are intermediate commits that are not meaningful to the overall PR, such as "Fixed error on style guide", "Fixed phpstan error", "Fixing mistake in code", and other related commits, it is advised to squash your commits so that we can have a clean commit history. 10. If you have touched PHP code, run static analysis. + - `> composer analyze` + - `> vendor/bin/rector process` 11. Run unit tests on the specific file you modified. If there are no existing tests yet, please create one. -12. Make sure the tests pass to have a higher chance of merging. -13. [Push](https://docs.github.com/en/github/using-git/pushing-commits-to-a-remote-repository) your contribution branch to your fork. -14. Send a [pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork). -15. Label your pull request with the appropriate label if you can. + - `> vendor/bin/phpunit tests/system/path/to/file/you/modified` + - Make sure the tests pass to have a higher chance of merging. +12. [Push](https://docs.github.com/en/github/using-git/pushing-commits-to-a-remote-repository) your contribution branch to your fork. + - `> git push origin ` +13. Send a [pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork). +14. Label your pull request with the appropriate label if you can. See [Contribution workflow](./workflow.md) for Git workflow details. From a6a51697d622d5dc4b761aba30f245ff5a14f593 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 13:12:32 +0900 Subject: [PATCH 067/407] docs: replace `composer install` with `composer update` composer warns if use `install`: No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information. --- contributing/pull_request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/pull_request.md b/contributing/pull_request.md index 5bcc3511e86c..02e0628a3205 100644 --- a/contributing/pull_request.md +++ b/contributing/pull_request.md @@ -217,7 +217,7 @@ The best way to contribute is to fork the CodeIgniter4 repository, and "clone" t - `> git clone git@github.com:/CodeIgniter4.git` 5. Install Composer dependencies. - `> cd CodeIgniter4/` - - `> composer install` + - `> composer update` 6. Create a new [branch](https://help.github.com/en/articles/about-branches) in your project for each set of changes you want to make. - `> git checkout -b ` 7. Fix existing bugs on the [Issue tracker](https://github.com/codeigniter4/CodeIgniter4/issues) after confirming that no one else is working on them. From baee0f355368dba64935239adb1b83b9076ca997 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 13:15:10 +0900 Subject: [PATCH 068/407] docs: remove line break and indent It is a single line. --- contributing/pull_request.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contributing/pull_request.md b/contributing/pull_request.md index 02e0628a3205..e788b76fede3 100644 --- a/contributing/pull_request.md +++ b/contributing/pull_request.md @@ -223,8 +223,7 @@ The best way to contribute is to fork the CodeIgniter4 repository, and "clone" t 7. Fix existing bugs on the [Issue tracker](https://github.com/codeigniter4/CodeIgniter4/issues) after confirming that no one else is working on them. 8. [Commit](https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project) the changed files in your contribution branch. - `> git commit` - - Commit messages are expected to be descriptive of what you changed specifically. Commit messages like - "Fixes #1234" would be asked by the reviewer to be revised. + - Commit messages are expected to be descriptive of what you changed specifically. Commit messages like "Fixes #1234" would be asked by the reviewer to be revised. 9. If there are intermediate commits that are not meaningful to the overall PR, such as "Fixed error on style guide", "Fixed phpstan error", "Fixing mistake in code", and other related commits, it is advised to squash your commits so that we can have a clean commit history. 10. If you have touched PHP code, run static analysis. - `> composer analyze` From 9d5ef6bce50d4a79ba28b5a3432e92035fe2534e Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 16:32:51 +0900 Subject: [PATCH 069/407] test: add $this->markTestSkipped() when extension not loaded --- tests/system/Cache/Handlers/MemcachedHandlerTest.php | 4 ++++ tests/system/Cache/Handlers/RedisHandlerTest.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tests/system/Cache/Handlers/MemcachedHandlerTest.php b/tests/system/Cache/Handlers/MemcachedHandlerTest.php index 38005d87ed5b..08a28f376fe7 100644 --- a/tests/system/Cache/Handlers/MemcachedHandlerTest.php +++ b/tests/system/Cache/Handlers/MemcachedHandlerTest.php @@ -37,6 +37,10 @@ protected function setUp(): void { parent::setUp(); + if (! extension_loaded('memcached')) { + $this->markTestSkipped('Memcached extension not loaded.'); + } + $this->config = new Cache(); $this->handler = new MemcachedHandler($this->config); diff --git a/tests/system/Cache/Handlers/RedisHandlerTest.php b/tests/system/Cache/Handlers/RedisHandlerTest.php index 4eb8f8b08560..205e708fc99a 100644 --- a/tests/system/Cache/Handlers/RedisHandlerTest.php +++ b/tests/system/Cache/Handlers/RedisHandlerTest.php @@ -36,6 +36,10 @@ protected function setUp(): void { parent::setUp(); + if (! extension_loaded('redis')) { + $this->markTestSkipped('redis extension not loaded.'); + } + $this->config = new Cache(); $this->handler = new RedisHandler($this->config); From 96b264607deda02c0f17c397a056b26fb669f6fd Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 16:33:42 +0900 Subject: [PATCH 070/407] test: remove unneeded return after $this->markTestSkipped() --- tests/system/Images/BaseHandlerTest.php | 2 -- tests/system/Images/GDHandlerTest.php | 2 -- tests/system/Images/ImageMagickHandlerTest.php | 2 -- 3 files changed, 6 deletions(-) diff --git a/tests/system/Images/BaseHandlerTest.php b/tests/system/Images/BaseHandlerTest.php index dddcf2bdf097..708e4ef50d3a 100644 --- a/tests/system/Images/BaseHandlerTest.php +++ b/tests/system/Images/BaseHandlerTest.php @@ -34,8 +34,6 @@ protected function setUp(): void { if (! extension_loaded('gd')) { $this->markTestSkipped('The GD extension is not available.'); - - return; } // create virtual file system diff --git a/tests/system/Images/GDHandlerTest.php b/tests/system/Images/GDHandlerTest.php index e93995d2072e..30216725a988 100644 --- a/tests/system/Images/GDHandlerTest.php +++ b/tests/system/Images/GDHandlerTest.php @@ -33,8 +33,6 @@ protected function setUp(): void { if (! extension_loaded('gd')) { $this->markTestSkipped('The GD extension is not available.'); - - return; } // create virtual file system diff --git a/tests/system/Images/ImageMagickHandlerTest.php b/tests/system/Images/ImageMagickHandlerTest.php index 1c97baeac0e5..02d02e305634 100644 --- a/tests/system/Images/ImageMagickHandlerTest.php +++ b/tests/system/Images/ImageMagickHandlerTest.php @@ -34,8 +34,6 @@ protected function setUp(): void { if (! extension_loaded('imagick')) { $this->markTestSkipped('The ImageMagick extension is not available.'); - - return; } $this->root = WRITEPATH . 'cache/'; From 07e701bbaaccb7e948675e6838a9125b8d856923 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 10:00:00 +0900 Subject: [PATCH 071/407] docs: add about redirect() change --- user_guide_src/source/installation/upgrade_4xx.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/user_guide_src/source/installation/upgrade_4xx.rst b/user_guide_src/source/installation/upgrade_4xx.rst index f28de5092e3d..2f276a738533 100644 --- a/user_guide_src/source/installation/upgrade_4xx.rst +++ b/user_guide_src/source/installation/upgrade_4xx.rst @@ -94,6 +94,9 @@ General Adjustments **Helpers** - Helpers are pretty much the same as before, though some have been simplified. +- In CI4, ``redirect()`` returns ``RedirectResponse`` instead of redirecting and terminating script execution. You must return it. + - `redirect() Documentation Codeigniter 3.X `_ + - `redirect() Documentation Codeigniter 4.X <../general/common_functions.html#redirect>`_ **Events** From 6292090f5f33bcb9f280427049d82b6466cfe855 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 11:07:14 +0900 Subject: [PATCH 072/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/installation/upgrade_4xx.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_4xx.rst b/user_guide_src/source/installation/upgrade_4xx.rst index 2f276a738533..570b9464ab64 100644 --- a/user_guide_src/source/installation/upgrade_4xx.rst +++ b/user_guide_src/source/installation/upgrade_4xx.rst @@ -95,8 +95,8 @@ General Adjustments - Helpers are pretty much the same as before, though some have been simplified. - In CI4, ``redirect()`` returns ``RedirectResponse`` instead of redirecting and terminating script execution. You must return it. - - `redirect() Documentation Codeigniter 3.X `_ - - `redirect() Documentation Codeigniter 4.X <../general/common_functions.html#redirect>`_ + - `redirect() Documentation CodeIgniter 3.X `_ + - `redirect() Documentation CodeIgniter 4.X <../general/common_functions.html#redirect>`_ **Events** From 7c00a8b2ad5d730de1deee361de40d9c5fe39004 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 11:07:24 +0900 Subject: [PATCH 073/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/installation/upgrade_4xx.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/installation/upgrade_4xx.rst b/user_guide_src/source/installation/upgrade_4xx.rst index 570b9464ab64..76fdba16c8e0 100644 --- a/user_guide_src/source/installation/upgrade_4xx.rst +++ b/user_guide_src/source/installation/upgrade_4xx.rst @@ -94,7 +94,7 @@ General Adjustments **Helpers** - Helpers are pretty much the same as before, though some have been simplified. -- In CI4, ``redirect()`` returns ``RedirectResponse`` instead of redirecting and terminating script execution. You must return it. +- In CI4, ``redirect()`` returns a ``RedirectResponse`` instance instead of redirecting and terminating script execution. You must return it. - `redirect() Documentation CodeIgniter 3.X `_ - `redirect() Documentation CodeIgniter 4.X <../general/common_functions.html#redirect>`_ From fef36dae408f3b7990bd2dc896165c0366c3652a Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 12:12:14 +0900 Subject: [PATCH 074/407] docs: replace Codeigniter with CodeIgniter --- user_guide_src/source/changelogs/v4.1.2.rst | 2 +- .../source/installation/upgrade_configuration.rst | 8 ++++---- .../source/installation/upgrade_controllers.rst | 8 ++++---- user_guide_src/source/installation/upgrade_database.rst | 8 ++++---- user_guide_src/source/installation/upgrade_emails.rst | 8 ++++---- user_guide_src/source/installation/upgrade_encryption.rst | 8 ++++---- .../source/installation/upgrade_file_upload.rst | 8 ++++---- .../source/installation/upgrade_html_tables.rst | 8 ++++---- .../source/installation/upgrade_localization.rst | 8 ++++---- user_guide_src/source/installation/upgrade_migrations.rst | 8 ++++---- user_guide_src/source/installation/upgrade_models.rst | 8 ++++---- user_guide_src/source/installation/upgrade_pagination.rst | 8 ++++---- user_guide_src/source/installation/upgrade_responses.rst | 8 ++++---- user_guide_src/source/installation/upgrade_routing.rst | 8 ++++---- user_guide_src/source/installation/upgrade_security.rst | 8 ++++---- user_guide_src/source/installation/upgrade_sessions.rst | 8 ++++---- .../source/installation/upgrade_validations.rst | 8 ++++---- .../source/installation/upgrade_view_parser.rst | 8 ++++---- user_guide_src/source/installation/upgrade_views.rst | 8 ++++---- 19 files changed, 73 insertions(+), 73 deletions(-) diff --git a/user_guide_src/source/changelogs/v4.1.2.rst b/user_guide_src/source/changelogs/v4.1.2.rst index 953083aeeff5..73fb0e4ccef6 100644 --- a/user_guide_src/source/changelogs/v4.1.2.rst +++ b/user_guide_src/source/changelogs/v4.1.2.rst @@ -38,7 +38,7 @@ Changes: Deprecations: -- Deprecated ``Codeigniter\View\View::$currentSection`` property. +- Deprecated ``CodeIgniter\View\View::$currentSection`` property. - Language strings and exceptions on invalid cookie samesite are deprecated for the ``CookieException``'s own exception message. - Deprecated `CodeIgniter\Entity` in favor of `CodeIgniter\Entity\Entity` - Deprecated cookie-related properties of ``Response`` in order to use the ``Cookie`` class. diff --git a/user_guide_src/source/installation/upgrade_configuration.rst b/user_guide_src/source/installation/upgrade_configuration.rst index 93fbf7f9cd72..21c309cb34f2 100644 --- a/user_guide_src/source/installation/upgrade_configuration.rst +++ b/user_guide_src/source/installation/upgrade_configuration.rst @@ -8,8 +8,8 @@ Upgrade Configuration Documentations ============== -- `Config Documentation Codeigniter 3.X `_ -- :doc:`Configuration Documentation Codeigniter 4.X ` +- `Config Documentation CodeIgniter 3.X `_ +- :doc:`Configuration Documentation CodeIgniter 4.X ` What has been changed @@ -37,7 +37,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ Path: ``application/models``:: @@ -49,7 +49,7 @@ Path: ``application/models``:: $siteName = 'My Great Site'; $siteEmail = 'webmaster@example.com'; -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- Path: ``app/Config``:: diff --git a/user_guide_src/source/installation/upgrade_controllers.rst b/user_guide_src/source/installation/upgrade_controllers.rst index 4af4449f0832..2625bd29cbb0 100644 --- a/user_guide_src/source/installation/upgrade_controllers.rst +++ b/user_guide_src/source/installation/upgrade_controllers.rst @@ -8,8 +8,8 @@ Upgrade Controllers Documentations ============== -- `Controller Documentation Codeigniter 3.X `_ -- :doc:`Controller Documentation Codeigniter 4.X ` +- `Controller Documentation CodeIgniter 3.X `_ +- :doc:`Controller Documentation CodeIgniter 4.X ` What has been changed ===================== @@ -38,7 +38,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ Path: ``application/controllers``:: @@ -53,7 +53,7 @@ Path: ``application/controllers``:: } } -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- Path: ``app/Controllers``:: diff --git a/user_guide_src/source/installation/upgrade_database.rst b/user_guide_src/source/installation/upgrade_database.rst index 798b24a1c6c0..221a52b7a8dc 100644 --- a/user_guide_src/source/installation/upgrade_database.rst +++ b/user_guide_src/source/installation/upgrade_database.rst @@ -9,8 +9,8 @@ Upgrade Database Documentations ============== -- `Database Reference Documentation Codeigniter 3.X `_ -- :doc:`Working with Databases Documentation Codeigniter 4.X ` +- `Database Reference Documentation CodeIgniter 3.X `_ +- :doc:`Working with Databases Documentation CodeIgniter 4.X ` What has been changed @@ -46,7 +46,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -55,7 +55,7 @@ Codeigniter Version 3.11 ->limit(10, 20) ->get('mytable'); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_emails.rst b/user_guide_src/source/installation/upgrade_emails.rst index 1a65f279cfa7..41778027dc30 100644 --- a/user_guide_src/source/installation/upgrade_emails.rst +++ b/user_guide_src/source/installation/upgrade_emails.rst @@ -9,8 +9,8 @@ Upgrade Emails Documentations ============== -- `Email Documentation Codeigniter 3.X `_ -- :doc:`Email Documentation Codeigniter 4.X ` +- `Email Documentation CodeIgniter 3.X `_ +- :doc:`Email Documentation CodeIgniter 4.X ` What has been changed @@ -27,7 +27,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -43,7 +43,7 @@ Codeigniter Version 3.11 $this->email->send(); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_encryption.rst b/user_guide_src/source/installation/upgrade_encryption.rst index 7dadbba63e85..dca7fbcbc27b 100644 --- a/user_guide_src/source/installation/upgrade_encryption.rst +++ b/user_guide_src/source/installation/upgrade_encryption.rst @@ -9,8 +9,8 @@ Upgrade Encryption Documentations ============== -- `Encryption Library Documentation Codeigniter 3.X `_ -- :doc:`Encryption Service Documentation Codeigniter 4.X ` +- `Encryption Library Documentation CodeIgniter 3.X `_ +- :doc:`Encryption Service Documentation CodeIgniter 4.X ` What has been changed @@ -25,7 +25,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -38,7 +38,7 @@ Codeigniter Version 3.11 echo $this->encryption->decrypt($ciphertext); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_file_upload.rst b/user_guide_src/source/installation/upgrade_file_upload.rst index e93884f7fa81..3369442e6392 100644 --- a/user_guide_src/source/installation/upgrade_file_upload.rst +++ b/user_guide_src/source/installation/upgrade_file_upload.rst @@ -8,8 +8,8 @@ Upgrade Working with Uploaded Files Documentations ============== -- `Output Class Documentation Codeigniter 3.X `_ -- :doc:`Working with Uploaded Files Documentation Codeigniter 4.X ` +- `Output Class Documentation CodeIgniter 3.X `_ +- :doc:`Working with Uploaded Files Documentation CodeIgniter 4.X ` What has been changed ===================== @@ -25,7 +25,7 @@ You have to change your file uploading code to match the new methods. Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -69,7 +69,7 @@ Codeigniter Version 3.11 } } -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_html_tables.rst b/user_guide_src/source/installation/upgrade_html_tables.rst index f8563c0ca9a5..9fc98e1fd838 100644 --- a/user_guide_src/source/installation/upgrade_html_tables.rst +++ b/user_guide_src/source/installation/upgrade_html_tables.rst @@ -9,8 +9,8 @@ Upgrade HTML Tables Documentations ============== -- `HTML Table Documentation Codeigniter 3.X `_ -- :doc:`HTML Table Documentation Codeigniter 4.X ` +- `HTML Table Documentation CodeIgniter 3.X `_ +- :doc:`HTML Table Documentation CodeIgniter 4.X ` What has been changed @@ -26,7 +26,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -40,7 +40,7 @@ Codeigniter Version 3.11 echo $this->table->generate(); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_localization.rst b/user_guide_src/source/installation/upgrade_localization.rst index bb01d0057228..b974570f5939 100644 --- a/user_guide_src/source/installation/upgrade_localization.rst +++ b/user_guide_src/source/installation/upgrade_localization.rst @@ -9,8 +9,8 @@ Upgrade Localization Documentations ============== -- `Language Documentation Codeigniter 3.X `_ -- :doc:`Localization Documentation Codeigniter 4.X ` +- `Language Documentation CodeIgniter 3.X `_ +- :doc:`Localization Documentation CodeIgniter 4.X ` What has been changed @@ -31,7 +31,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -45,7 +45,7 @@ Codeigniter Version 3.11 $this->lang->load('error', $lang); echo $this->lang->line('error_email_missing'); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_migrations.rst b/user_guide_src/source/installation/upgrade_migrations.rst index 66bfcbaabc1d..10a75bf23f2d 100644 --- a/user_guide_src/source/installation/upgrade_migrations.rst +++ b/user_guide_src/source/installation/upgrade_migrations.rst @@ -8,8 +8,8 @@ Upgrade Migrations Documentations ============== -- `Database Migrations Documentation Codeigniter 3.X `_ -- :doc:`Database Migrations Documentation Codeigniter 4.X ` +- `Database Migrations Documentation CodeIgniter 3.X `_ +- :doc:`Database Migrations Documentation CodeIgniter 4.X ` What has been changed ===================== @@ -48,7 +48,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ Path: ``application/migrations``:: @@ -87,7 +87,7 @@ Path: ``application/migrations``:: } } -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- Path: ``app/Database/Migrations``:: diff --git a/user_guide_src/source/installation/upgrade_models.rst b/user_guide_src/source/installation/upgrade_models.rst index 6b4f78a2b856..7100f6ca9202 100644 --- a/user_guide_src/source/installation/upgrade_models.rst +++ b/user_guide_src/source/installation/upgrade_models.rst @@ -8,8 +8,8 @@ Upgrade Models Documentations ============== -- `Model Documentation Codeigniter 3.X `_ -- :doc:`Model Documentation Codeigniter 4.X ` +- `Model Documentation CodeIgniter 3.X `_ +- :doc:`Model Documentation CodeIgniter 4.X ` What has been changed @@ -38,7 +38,7 @@ You can find more information to those methods :doc:`here `. Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ Path: ``application/models``:: @@ -57,7 +57,7 @@ Path: ``application/models``:: } } -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- Path: ``app/Models``:: diff --git a/user_guide_src/source/installation/upgrade_pagination.rst b/user_guide_src/source/installation/upgrade_pagination.rst index 8151e82465e5..4743bb985cf2 100644 --- a/user_guide_src/source/installation/upgrade_pagination.rst +++ b/user_guide_src/source/installation/upgrade_pagination.rst @@ -9,8 +9,8 @@ Upgrade Pagination Documentations ============== -- `Pagination Class Documentation Codeigniter 3.X `_ -- :doc:`Pagination Documentation Codeigniter 4.X ` +- `Pagination Class Documentation CodeIgniter 3.X `_ +- :doc:`Pagination Documentation CodeIgniter 4.X ` What has been changed @@ -34,7 +34,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -50,7 +50,7 @@ Codeigniter Version 3.11 $this->load->view('posts/index', $data); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_responses.rst b/user_guide_src/source/installation/upgrade_responses.rst index 6b5cc1b4ef7b..aafcf9731faa 100644 --- a/user_guide_src/source/installation/upgrade_responses.rst +++ b/user_guide_src/source/installation/upgrade_responses.rst @@ -8,8 +8,8 @@ Upgrade HTTP Responses Documentations ============== -- `Output Class Documentation Codeigniter 3.X `_ -- :doc:`HTTP Responses Documentation Codeigniter 4.X ` +- `Output Class Documentation CodeIgniter 3.X `_ +- :doc:`HTTP Responses Documentation CodeIgniter 4.X ` What has been changed ===================== @@ -23,7 +23,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -35,7 +35,7 @@ Codeigniter Version 3.11 ->set_content_type('application/json') ->set_output(json_encode(array('foo' => 'bar'))); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_routing.rst b/user_guide_src/source/installation/upgrade_routing.rst index 7243d41345db..bd840b06a82c 100644 --- a/user_guide_src/source/installation/upgrade_routing.rst +++ b/user_guide_src/source/installation/upgrade_routing.rst @@ -9,8 +9,8 @@ Upgrade Routing Documentations ============== -- `URI Routing Documentation Codeigniter 3.X `_ -- :doc:`URI Routing Documentation Codeigniter 4.X ` +- `URI Routing Documentation CodeIgniter 3.X `_ +- :doc:`URI Routing Documentation CodeIgniter 4.X ` What has been changed @@ -28,7 +28,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ Path: ``application/config/routes.php``:: @@ -45,7 +45,7 @@ Path: ``application/config/routes.php``:: $route['drivers/update'] = 'drivers/update'; $route['posts/(:any)'] = 'posts/view/$1'; -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- Path: ``app/Config/Routes.php``:: diff --git a/user_guide_src/source/installation/upgrade_security.rst b/user_guide_src/source/installation/upgrade_security.rst index 7f991b0bdb47..4aeb34e513c9 100644 --- a/user_guide_src/source/installation/upgrade_security.rst +++ b/user_guide_src/source/installation/upgrade_security.rst @@ -9,8 +9,8 @@ Upgrade Security Documentations ============== -- `Security Class Documentation Codeigniter 3.X `_ -- :doc:`Security Documentation Codeigniter 4.X ` +- `Security Class Documentation CodeIgniter 3.X `_ +- :doc:`Security Documentation CodeIgniter 4.X ` .. note:: If you use the :doc:`form helper ` and enable the CSRF filter globally, then ``form_open()`` will automatically insert a hidden CSRF field in your forms. So you do not have to upgrade this by yourself. @@ -36,7 +36,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -56,7 +56,7 @@ Codeigniter Version 3.11 -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_sessions.rst b/user_guide_src/source/installation/upgrade_sessions.rst index 3aa085a016ff..23688000ff96 100644 --- a/user_guide_src/source/installation/upgrade_sessions.rst +++ b/user_guide_src/source/installation/upgrade_sessions.rst @@ -9,8 +9,8 @@ Upgrade Sessions Documentations ============== -- `Session Library Documentation Codeigniter 3.X `_ -- :doc:`Session Library Documentation Codeigniter 4.X ` +- `Session Library Documentation CodeIgniter 3.X `_ +- :doc:`Session Library Documentation CodeIgniter 4.X ` What has been changed @@ -30,7 +30,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -40,7 +40,7 @@ Codeigniter Version 3.11 $this->session->item; $this->session->userdata('item'); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_validations.rst b/user_guide_src/source/installation/upgrade_validations.rst index 0bc0928ee32e..5e2b1a2bf942 100644 --- a/user_guide_src/source/installation/upgrade_validations.rst +++ b/user_guide_src/source/installation/upgrade_validations.rst @@ -9,8 +9,8 @@ Upgrade Validations Documentations of Library ========================= -- `Form Validation Documentation Codeigniter 3.X `_ -- :doc:`Validation Documentation Codeigniter 4.X ` +- `Form Validation Documentation CodeIgniter 3.X `_ +- :doc:`Validation Documentation CodeIgniter 4.X ` What has been changed @@ -44,7 +44,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ Path: ``application/views``:: @@ -102,7 +102,7 @@ Path: ``application/controllers/``:: } } -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- Path: ``app/Views``:: diff --git a/user_guide_src/source/installation/upgrade_view_parser.rst b/user_guide_src/source/installation/upgrade_view_parser.rst index f3147bbcd6fd..94bd5ac67f19 100644 --- a/user_guide_src/source/installation/upgrade_view_parser.rst +++ b/user_guide_src/source/installation/upgrade_view_parser.rst @@ -9,8 +9,8 @@ Upgrade View Parser Documentations ============== -- `Template Parser Documentation Codeigniter 3.X `_ -- :doc:`View Parser Documentation Codeigniter 4.X ` +- `Template Parser Documentation CodeIgniter 3.X `_ +- :doc:`View Parser Documentation CodeIgniter 4.X ` What has been changed @@ -26,7 +26,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ :: @@ -40,7 +40,7 @@ Codeigniter Version 3.11 $this->parser ->parse('blog_template', $data); -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- :: diff --git a/user_guide_src/source/installation/upgrade_views.rst b/user_guide_src/source/installation/upgrade_views.rst index 4da9ce84301d..554a0a83ffc3 100644 --- a/user_guide_src/source/installation/upgrade_views.rst +++ b/user_guide_src/source/installation/upgrade_views.rst @@ -8,8 +8,8 @@ Upgrade Views Documentations ============== -- `View Documentation Codeigniter 3.X `_ -- :doc:`View Documentation Codeigniter 4.X ` +- `View Documentation CodeIgniter 3.X `_ +- :doc:`View Documentation CodeIgniter 4.X ` What has been changed ===================== @@ -30,7 +30,7 @@ Upgrade Guide Code Example ============ -Codeigniter Version 3.11 +CodeIgniter Version 3.11 ------------------------ Path: ``application/views``:: @@ -53,7 +53,7 @@ Path: ``application/views``:: -Codeigniter Version 4.x +CodeIgniter Version 4.x ----------------------- Path: ``app/Views``:: From b835b01a0e1eff4b408a582c8246de969ca30fca Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 15:27:00 +0900 Subject: [PATCH 075/407] docs: add example file names --- user_guide_src/source/outgoing/view_layouts.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/outgoing/view_layouts.rst b/user_guide_src/source/outgoing/view_layouts.rst index a0e47ab94499..da14a4400bbe 100644 --- a/user_guide_src/source/outgoing/view_layouts.rst +++ b/user_guide_src/source/outgoing/view_layouts.rst @@ -19,7 +19,7 @@ Creating A Layout Layouts are views like any other. The only difference is their intended usage. Layouts are the only view files that would make use of the ``renderSection()`` method. This method acts as a placeholder for content. -:: +E.g. **app/Views/default.php**:: @@ -50,7 +50,9 @@ other PSR-4 defined namespaces. You can include a namespace to locate the view i All content within a view that extends a layout must be included within ``section($name)`` and ``endSection()`` method calls. Any content between these calls will be inserted into the layout wherever the ``renderSection($name)`` call that -matches the section name exists.:: +matches the section name exists. + +E.g. **app/Views/some_view.php**:: extend('default') ?> From 73b7c412c527c0f6a9ce885fc419fef64a1e1867 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 15:27:24 +0900 Subject: [PATCH 076/407] docs: add file names in explanation --- user_guide_src/source/outgoing/view_layouts.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/outgoing/view_layouts.rst b/user_guide_src/source/outgoing/view_layouts.rst index da14a4400bbe..18a0f963c9e3 100644 --- a/user_guide_src/source/outgoing/view_layouts.rst +++ b/user_guide_src/source/outgoing/view_layouts.rst @@ -85,6 +85,8 @@ Rendering the view and it's layout is done exactly as any other view would be di echo view('some_view'); } +It renders the View **app/Views/some_view.php** and if it extends ``default``, +the Layout **app/Views/default.php** is also used automatically. The renderer is smart enough to detect whether the view should be rendered on its own, or if it needs a layout. *********************** From de3f788f90600a2399e036a2e268a0abcd6ebd3a Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 15:28:25 +0900 Subject: [PATCH 077/407] docs: decorate method name with '``' --- user_guide_src/source/outgoing/view_layouts.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/outgoing/view_layouts.rst b/user_guide_src/source/outgoing/view_layouts.rst index 18a0f963c9e3..8bc8f6df829c 100644 --- a/user_guide_src/source/outgoing/view_layouts.rst +++ b/user_guide_src/source/outgoing/view_layouts.rst @@ -31,7 +31,7 @@ E.g. **app/Views/default.php**:: -The renderSection() method only has one argument - the name of the section. That way any child views know +The ``renderSection()`` method only has one argument - the name of the section. That way any child views know what to name the content section. ********************** @@ -42,7 +42,7 @@ Whenever a view wants to be inserted into a layout, it must use the ``extend()`` extend('default') ?> -The extend method takes the name of any view file that you wish to use. Since they are standard views, they will +The ``extend()`` method takes the name of any view file that you wish to use. Since they are standard views, they will be located just like a view. By default, it will look in the application's View directory, but will also scan other PSR-4 defined namespaces. You can include a namespace to locate the view in particular namespace View directory:: @@ -106,5 +106,5 @@ view to view. When using view layouts you must use ``$this->include()`` to inclu include('sidebar') ?> endSection() ?> -When calling the include() method, you can pass it all of the same options that can when rendering a normal view, including +When calling the ``include()`` method, you can pass it all of the same options that can when rendering a normal view, including cache directives, etc. From f95e75fcfbb63715af4bb3e7229704ec1e969cfc Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 09:15:08 +0900 Subject: [PATCH 078/407] refactor: rename variable names To make it easier to identify binary or hex --- system/Security/Security.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system/Security/Security.php b/system/Security/Security.php index ef06661966f8..1224bc16f0ac 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -348,14 +348,14 @@ public function getHash(): ?string */ protected function randomize(string $hash): string { - $key = random_bytes(self::CSRF_HASH_BYTES); - $value = hex2bin($hash); + $keyBinary = random_bytes(self::CSRF_HASH_BYTES); + $hashBinary = hex2bin($hash); - if ($value === false) { + if ($hashBinary === false) { throw new LogicException('$hash is invalid: ' . $hash); } - return bin2hex(($value ^ $key) . $key); + return bin2hex(($hashBinary ^ $keyBinary) . $keyBinary); } /** From 1037f7f431ebc4cff7600314e9101bc7f907bab2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 09:22:31 +0900 Subject: [PATCH 079/407] refactor: CSRF_HASH_BYTES can be overridden Because the use case where users want to increase the value is assumed. --- system/Security/Security.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/system/Security/Security.php b/system/Security/Security.php index 1224bc16f0ac..fc8c1ac334c8 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -31,7 +31,7 @@ class Security implements SecurityInterface { public const CSRF_PROTECTION_COOKIE = 'cookie'; public const CSRF_PROTECTION_SESSION = 'session'; - public const CSRF_HASH_BYTES = 16; + protected const CSRF_HASH_BYTES = 16; /** * CSRF Protection Method @@ -348,7 +348,7 @@ public function getHash(): ?string */ protected function randomize(string $hash): string { - $keyBinary = random_bytes(self::CSRF_HASH_BYTES); + $keyBinary = random_bytes(static::CSRF_HASH_BYTES); $hashBinary = hex2bin($hash); if ($hashBinary === false) { @@ -363,8 +363,8 @@ protected function randomize(string $hash): string */ protected function derandomize(string $token): string { - $key = substr($token, -self::CSRF_HASH_BYTES * 2); - $value = substr($token, 0, self::CSRF_HASH_BYTES * 2); + $key = substr($token, -static::CSRF_HASH_BYTES * 2); + $value = substr($token, 0, static::CSRF_HASH_BYTES * 2); return bin2hex(hex2bin($value) ^ hex2bin($key)); } @@ -498,7 +498,7 @@ protected function generateHash(): string return $this->hash = $this->session->get($this->tokenName); } - $this->hash = bin2hex(random_bytes(self::CSRF_HASH_BYTES)); + $this->hash = bin2hex(random_bytes(static::CSRF_HASH_BYTES)); if ($this->isCSRFCookie()) { $this->saveHashInCookie(); From 1811d00c636266dfa95f5b43b61a964eb757a1d1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 09:42:16 +0900 Subject: [PATCH 080/407] test: add $this->expectExceptionMessage(); --- .../Security/SecurityCSRFSessionRandomizeTokenTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php b/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php index 00623d3db9f1..c90007bec74c 100644 --- a/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php +++ b/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php @@ -111,6 +111,7 @@ public function testHashIsReadFromSession() public function testCSRFVerifyPostThrowsExceptionOnNoMatch() { $this->expectException(SecurityException::class); + $this->expectExceptionMessage('The action you requested is not allowed.'); $_SERVER['REQUEST_METHOD'] = 'POST'; $_POST['csrf_test_name'] = '8b9218a55906f9dcc1dc263dce7f005b'; @@ -147,6 +148,8 @@ public function testCSRFVerifyPOSTHeaderThrowsExceptionOnNoMatch() $security = new Security(new MockAppConfig()); $this->expectException(SecurityException::class); + $this->expectExceptionMessage('The action you requested is not allowed.'); + $security->verify($request); } @@ -175,6 +178,8 @@ public function testCSRFVerifyPUTHeaderThrowsExceptionOnNoMatch() $security = new Security(new MockAppConfig()); $this->expectException(SecurityException::class); + $this->expectExceptionMessage('The action you requested is not allowed.'); + $security->verify($request); } @@ -194,6 +199,7 @@ public function testCSRFVerifyPUTHeaderReturnsSelfOnMatch() public function testCSRFVerifyJsonThrowsExceptionOnNoMatch() { $this->expectException(SecurityException::class); + $this->expectExceptionMessage('The action you requested is not allowed.'); $_SERVER['REQUEST_METHOD'] = 'POST'; From b1bc7ba1f41f3b7b626b6cd94fa5bca9f1e262ad Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 10:53:14 +0900 Subject: [PATCH 081/407] docs: add Token Randomization to user guide --- user_guide_src/source/libraries/security.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index a7ee6e141f78..b14535003648 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -79,6 +79,20 @@ It is also possible to enable the CSRF filter only for specific methods:: 'post' => ['csrf'], ]; +Token Randomization +=================== + +To mitigate compression side-channel attacks like `BREACH`_, and prevent an attacker from guessing the CSRF tokens, you can configure token randomization (default off). + +If you enable it, a random mask is added to the token and used to scramble it. + +.. _`BREACH`: https://en.wikipedia.org/wiki/BREACH + +You can enable it by editing the following config parameter value in +**app/Config/Security.php**:: + + public $tokenRandomize = true; + HTML Forms ========== From 29bfacf68166922ff7b5ff0051c2ff978baecc68 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 11:04:35 +0900 Subject: [PATCH 082/407] test: fix assertions --- .../system/Security/SecurityCSRFSessionRandomizeTokenTest.php | 4 ++-- tests/system/Security/SecurityCSRFSessionTest.php | 4 ++-- tests/system/Security/SecurityTest.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php b/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php index c90007bec74c..2717e26a40e8 100644 --- a/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php +++ b/tests/system/Security/SecurityCSRFSessionRandomizeTokenTest.php @@ -135,7 +135,7 @@ public function testCSRFVerifyPostReturnsSelfOnMatch() $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); - $this->assertTrue(count($_POST) === 1); + $this->assertCount(1, $_POST); } public function testCSRFVerifyPOSTHeaderThrowsExceptionOnNoMatch() @@ -222,7 +222,7 @@ public function testCSRFVerifyJsonReturnsSelfOnMatch() $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); - $this->assertTrue($request->getBody() === '{"foo":"bar"}'); + $this->assertSame('{"foo":"bar"}', $request->getBody()); } public function testRegenerateWithFalseSecurityRegenerateProperty() diff --git a/tests/system/Security/SecurityCSRFSessionTest.php b/tests/system/Security/SecurityCSRFSessionTest.php index c0ec2c066c40..ca07bf1f30b7 100644 --- a/tests/system/Security/SecurityCSRFSessionTest.php +++ b/tests/system/Security/SecurityCSRFSessionTest.php @@ -124,7 +124,7 @@ public function testCSRFVerifyPostReturnsSelfOnMatch() $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); - $this->assertTrue(count($_POST) === 1); + $this->assertCount(1, $_POST); } public function testCSRFVerifyPOSTHeaderThrowsExceptionOnNoMatch() @@ -206,7 +206,7 @@ public function testCSRFVerifyJsonReturnsSelfOnMatch() $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); - $this->assertTrue($request->getBody() === '{"foo":"bar"}'); + $this->assertSame('{"foo":"bar"}', $request->getBody()); } public function testRegenerateWithFalseSecurityRegenerateProperty() diff --git a/tests/system/Security/SecurityTest.php b/tests/system/Security/SecurityTest.php index ba6a4ada5024..cc9fcf753853 100644 --- a/tests/system/Security/SecurityTest.php +++ b/tests/system/Security/SecurityTest.php @@ -115,7 +115,7 @@ public function testCSRFVerifyPostReturnsSelfOnMatch() $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); - $this->assertTrue(count($_POST) === 1); + $this->assertCount(1, $_POST); } public function testCSRFVerifyHeaderThrowsExceptionOnNoMatch() @@ -176,7 +176,7 @@ public function testCSRFVerifyJsonReturnsSelfOnMatch() $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); - $this->assertTrue($request->getBody() === '{"foo":"bar"}'); + $this->assertSame('{"foo":"bar"}', $request->getBody()); } public function testSanitizeFilename() From 899d7d4c06dfa6d43fcc8610112ee36730148577 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 11:04:58 +0900 Subject: [PATCH 083/407] test: refactor MockSecurity --- system/Test/Mock/MockSecurity.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/Test/Mock/MockSecurity.php b/system/Test/Mock/MockSecurity.php index 0e782304a2e7..a078154b7ff9 100644 --- a/system/Test/Mock/MockSecurity.php +++ b/system/Test/Mock/MockSecurity.php @@ -22,9 +22,9 @@ protected function doSendCookie(): void protected function randomize(string $hash): string { - $key = hex2bin('005513c290126d34d41bf41c5265e0f1'); - $value = hex2bin($hash); + $keyBinary = hex2bin('005513c290126d34d41bf41c5265e0f1'); + $hashBinary = hex2bin($hash); - return bin2hex(($value ^ $key) . $key); + return bin2hex(($hashBinary ^ $keyBinary) . $keyBinary); } } From d923f6c9e74643b957ece7ae06abb56fc811f1c0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:34:04 +0900 Subject: [PATCH 084/407] docs: fix out-of-dated explanation There is no $useKint. --- user_guide_src/source/testing/debugging.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/testing/debugging.rst b/user_guide_src/source/testing/debugging.rst index fbd0f8eed440..bdacb68e89d3 100644 --- a/user_guide_src/source/testing/debugging.rst +++ b/user_guide_src/source/testing/debugging.rst @@ -19,10 +19,9 @@ and much, much more. Enabling Kint ============= -By default, Kint is enabled in **development** and **testing** :doc:`environments ` only. This can be altered by modifying -the ``$useKint`` value in the environment configuration section of the main **index.php** file:: - - $useKint = true; +By default, Kint is enabled in **development** and **testing** :doc:`environments ` only. +It will be enabled whenever the constant ``CI_DEBUG`` is defined and its value is truthy. +This is defined in the boot files (e.g. **app/Config/Boot/development.php**). Using Kint ========== From b255726410c8a8e0bd558b923498dbee6a3ff935 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:35:36 +0900 Subject: [PATCH 085/407] docs: decorate constant with '``' --- user_guide_src/source/testing/debugging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/testing/debugging.rst b/user_guide_src/source/testing/debugging.rst index bdacb68e89d3..3e456d118793 100644 --- a/user_guide_src/source/testing/debugging.rst +++ b/user_guide_src/source/testing/debugging.rst @@ -59,7 +59,7 @@ Enabling the Toolbar ==================== The toolbar is enabled by default in any :doc:`environment ` *except* **production**. It will be shown whenever the -constant CI_DEBUG is defined and its value is truthy. This is defined in the boot files (e.g. +constant ``CI_DEBUG`` is defined and its value is truthy. This is defined in the boot files (e.g. **app/Config/Boot/development.php**) and can be modified there to determine what environment to show. .. note:: The Debug Toolbar is not displayed when your ``baseURL`` setting (in **app/Config/App.php** or ``app.baseURL`` in **.env**) does not match your actual URL. From f7fe38ad16b0d53d4c370ef0e7a5bef014cfa262 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:39:59 +0900 Subject: [PATCH 086/407] docs: fix coding style in sample code --- user_guide_src/source/libraries/publisher.rst | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/user_guide_src/source/libraries/publisher.rst b/user_guide_src/source/libraries/publisher.rst index fd75c09e99e4..39978648de77 100644 --- a/user_guide_src/source/libraries/publisher.rst +++ b/user_guide_src/source/libraries/publisher.rst @@ -152,12 +152,9 @@ You can set up :doc:`Custom Command ` to run daily that will { $publisher = new Publisher('/path/to/photos/', FCPATH . 'assets/images'); - try - { + try { $publisher->addPath('daily_photo.jpg')->copy(true); // `true` to enable overwrites - } - catch (Throwable $e) - { + } catch (Throwable $e) { $this->showError($e); } } @@ -281,24 +278,20 @@ into an application for use:: $publisher = new Publisher($source, APPATH); - try - { + try { // Add only the desired components $publisher->addPaths([ 'Controllers', 'Database/Migrations', 'Models', ])->merge(false); // Be careful not to overwrite anything - } - catch (Throwable $e) - { + } catch (Throwable $e) { $this->showError($e); return; } // If publication succeeded then update namespaces - foreach ($publisher->getPublished() as $file) - { + foreach ($publisher->getPublished() as $file) { // Replace the namespace $contents = file_get_contents($file); $contents = str_replace('namespace Math\\Auth', 'namespace ' . APP_NAMESPACE, ); From 1f7254cc74734b70637dd8862d1c72e8a7b576b5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:40:52 +0900 Subject: [PATCH 087/407] docs: fix sample code The third argument is missing. --- user_guide_src/source/libraries/publisher.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/publisher.rst b/user_guide_src/source/libraries/publisher.rst index 39978648de77..c5928edc1e0a 100644 --- a/user_guide_src/source/libraries/publisher.rst +++ b/user_guide_src/source/libraries/publisher.rst @@ -294,7 +294,7 @@ into an application for use:: foreach ($publisher->getPublished() as $file) { // Replace the namespace $contents = file_get_contents($file); - $contents = str_replace('namespace Math\\Auth', 'namespace ' . APP_NAMESPACE, ); + $contents = str_replace('namespace Math\\Auth', 'namespace ' . APP_NAMESPACE, $contents); file_put_contents($file, $contents); } } From f24f1aadf693dc343b76fc69cf8a44609c747c45 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:41:46 +0900 Subject: [PATCH 088/407] docs: fix RST style --- user_guide_src/source/libraries/publisher.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/publisher.rst b/user_guide_src/source/libraries/publisher.rst index c5928edc1e0a..429e2c59a440 100644 --- a/user_guide_src/source/libraries/publisher.rst +++ b/user_guide_src/source/libraries/publisher.rst @@ -13,7 +13,7 @@ Loading the Library ******************* Because Publisher instances are specific to their source and destination this library is not available -through ``Services`` but should be instantiated or extended directly. E.g. +through ``Services`` but should be instantiated or extended directly. E.g.:: $publisher = new \CodeIgniter\Publisher\Publisher(); From 48f53ae12c90c11d92fe2574511219d52826c8d4 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:43:14 +0900 Subject: [PATCH 089/407] docs: adjust the notation of method signatures --- user_guide_src/source/libraries/publisher.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/libraries/publisher.rst b/user_guide_src/source/libraries/publisher.rst index 429e2c59a440..b32f0d64838a 100644 --- a/user_guide_src/source/libraries/publisher.rst +++ b/user_guide_src/source/libraries/publisher.rst @@ -336,18 +336,18 @@ Returns success or failure. Returns the temporary workspace, creating it if necessary. Some operations use intermediate storage to stage files and changes, and this provides the path to a transient, writable directory that you may use as well. -**getErrors(): array** +**getErrors(): array** Returns any errors from the last write operation. The array keys are the files that caused the error, and the values are the Throwable that was caught. Use ``getMessage()`` on the Throwable to get the error message. -**addPath(string $path, bool $recursive = true)** +**addPath(string $path, bool $recursive = true)** / **addPaths(array $path, bool $recursive = true)** Adds all files indicated by the relative paths. Paths are references to actual files or directories relative to ``$source``. If the relative path resolves to a directory then ``$recursive`` will include sub-directories. -**addUri(string $uri)** +**addUri(string $uri)** / **addUris(array $uris)** Downloads the contents of a URI using ``CURLRequest`` into the scratch workspace then adds the resulting From 6365b40c1850b2031d486567e8508d305b963c22 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:48:50 +0900 Subject: [PATCH 090/407] docs: fix namespaced classnames Adding `\` in front of the namespaces. --- user_guide_src/source/testing/controllers.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/testing/controllers.rst b/user_guide_src/source/testing/controllers.rst index 4333ad26ec0e..e99a24d935f9 100644 --- a/user_guide_src/source/testing/controllers.rst +++ b/user_guide_src/source/testing/controllers.rst @@ -96,7 +96,7 @@ If you do not provide one, the application's App config file will be used. Allows you to provide an **IncomingRequest** instance tailored to your testing needs:: - $request = new CodeIgniter\HTTP\IncomingRequest(new Config\App(), new URI('http://example.com')); + $request = new \CodeIgniter\HTTP\IncomingRequest(new \Config\App(), new URI('http://example.com')); $request->setLocale($locale); $results = $this->withRequest($request) @@ -110,7 +110,7 @@ into your controller. Allows you to provide a **Response** instance:: - $response = new CodeIgniter\HTTP\Response(new Config\App()); + $response = new \CodeIgniter\HTTP\Response(new \Config\App()); $results = $this->withResponse($response) ->controller(\App\Controllers\ForumController::class) @@ -123,7 +123,7 @@ into your controller. Allows you to provide a **Logger** instance:: - $logger = new CodeIgniter\Log\Handlers\FileHandler(); + $logger = new \CodeIgniter\Log\Handlers\FileHandler(); $results = $this->withResponse($response) ->withLogger($logger) From 1f570bd463e12a68f3d709b909330711b9e50b4e Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:53:02 +0900 Subject: [PATCH 091/407] docs: fix coding style in sample code --- user_guide_src/source/concepts/services.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/concepts/services.rst b/user_guide_src/source/concepts/services.rst index 779f533800b1..8ede85bfbd62 100644 --- a/user_guide_src/source/concepts/services.rst +++ b/user_guide_src/source/concepts/services.rst @@ -98,7 +98,7 @@ to find the views at ``APPPATH.views/``. We want the developer to have the optio changing that path, though, if their needs require it. So the class accepts the ``$viewPath`` as a constructor parameter. The service method looks like this:: - public static function renderer($viewPath=APPPATH.'views/') + public static function renderer($viewPath = APPPATH . 'views/') { return new \CodeIgniter\View\View($viewPath); } @@ -121,8 +121,7 @@ within the class, and, if not, creates a new one. All of the factory methods pro { public static function routes($getShared = false) { - if (! $getShared) - { + if (! $getShared) { return new \CodeIgniter\Router\RouteCollection(); } From 3d8e01da567aed313969a4e9e7afcadcba09f1e1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 12:57:02 +0900 Subject: [PATCH 092/407] docs: decorate variables and methods with '``' --- user_guide_src/source/testing/feature.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/testing/feature.rst b/user_guide_src/source/testing/feature.rst index 5d68543d241a..79d0b9d51c76 100644 --- a/user_guide_src/source/testing/feature.rst +++ b/user_guide_src/source/testing/feature.rst @@ -74,7 +74,7 @@ Shorthand methods for each of the HTTP verbs exist to ease typing and make thing $this->delete($path, $params); $this->options($path, $params); -.. note:: The $params array does not make sense for every HTTP verb, but is included for consistency. +.. note:: The ``$params`` array does not make sense for every HTTP verb, but is included for consistency. Setting Different Routes ------------------------ @@ -96,7 +96,7 @@ Setting Session Values ---------------------- You can set custom session values to use during a single test with the ``withSession()`` method. This takes an array -of key/value pairs that should exist within the $_SESSION variable when this request is made, or ``null` to indicate +of key/value pairs that should exist within the ``$_SESSION`` variable when this request is made, or ``null`` to indicate that the current values of ``$_SESSION`` should be used. This is handy for testing authentication and more. :: @@ -136,7 +136,7 @@ Formatting The Request ----------------------- You can set the format of your request's body using the ``withBodyFormat()`` method. Currently this supports either -`json` or `xml`. This will take the parameters passed into ``call(), post(), get()...`` and assign them to the +`json` or `xml`. This will take the parameters passed into ``call()``, ``post()``, ``get()``... and assign them to the body of the request in the given format. This will also set the `Content-Type` header for your request accordingly. This is useful when testing JSON or XML API's so that you can set the request in the form that the controller will expect. :: From 4bb36351b7efa7b9fa5519891b8c93b4af7e5169 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Nov 2021 10:20:51 +0900 Subject: [PATCH 093/407] chore: add PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD to rector https://github.com/rectorphp/rector-phpunit --- rector.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rector.php b/rector.php index 4a5fde83a45c..4996a4817af8 100644 --- a/rector.php +++ b/rector.php @@ -42,6 +42,7 @@ use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; +use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\LevelSetList; use Rector\Set\ValueObject\SetList; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; @@ -53,6 +54,7 @@ return static function (ContainerConfigurator $containerConfigurator): void { $containerConfigurator->import(SetList::DEAD_CODE); $containerConfigurator->import(LevelSetList::UP_TO_PHP_73); + $containerConfigurator->import(PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD); $parameters = $containerConfigurator->parameters(); From 4a17e69ca773e8e7ff71342ff4e4abfc00335d96 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 10:47:46 +0900 Subject: [PATCH 094/407] chore: skip AssertIssetToSpecificMethodRector in two test classes --- rector.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rector.php b/rector.php index 4996a4817af8..d5b7e1eec4f6 100644 --- a/rector.php +++ b/rector.php @@ -42,6 +42,7 @@ use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; +use Rector\PHPUnit\Rector\MethodCall\AssertIssetToSpecificMethodRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\LevelSetList; use Rector\Set\ValueObject\SetList; @@ -111,6 +112,15 @@ // use mt_rand instead of random_int on purpose on non-cryptographically random RandomFunctionRector::class, + + // $this->assertTrue(isset($bar['foo'])) + // and $this->assertArrayHasKey('foo', $bar) + // or $this->assertObjectHasAttribute('foo', $bar); + // are not the same + AssertIssetToSpecificMethodRector::class => [ + __DIR__ . '/tests/system/Entity/EntityTest.php', + __DIR__ . '/tests/system/Session/SessionTest.php', + ], ]); // auto import fully qualified class names From dd4024ff1ee50884772523b7e205e4ea9d2a523e Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 11:13:11 +0900 Subject: [PATCH 095/407] chore: skip AssertFalseStrposToContainsRector --- rector.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rector.php b/rector.php index d5b7e1eec4f6..829ec303e0f4 100644 --- a/rector.php +++ b/rector.php @@ -42,6 +42,7 @@ use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; +use Rector\PHPUnit\Rector\MethodCall\AssertFalseStrposToContainsRector; use Rector\PHPUnit\Rector\MethodCall\AssertIssetToSpecificMethodRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\LevelSetList; @@ -121,6 +122,9 @@ __DIR__ . '/tests/system/Entity/EntityTest.php', __DIR__ . '/tests/system/Session/SessionTest.php', ], + + // assertContains() to string can't be used in PHPUnit 9.1 + AssertFalseStrposToContainsRector::class, ]); // auto import fully qualified class names From c4f0fbb22c940faf5c8a5c977189f8024a8840a2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 11:13:52 +0900 Subject: [PATCH 096/407] test: refactor: vendor/bin/rector process tests/system/ --- tests/system/API/ResponseTraitTest.php | 2 +- tests/system/CLI/ConsoleTest.php | 2 +- tests/system/CommonSingleServiceTest.php | 6 +++--- tests/system/Config/ConfigTest.php | 2 +- tests/system/Config/ServicesTest.php | 2 +- tests/system/Cookie/CookieTest.php | 8 ++++---- tests/system/Database/Live/ConnectTest.php | 2 +- tests/system/Database/Live/DbUtilsTest.php | 2 +- tests/system/Database/Live/GetTest.php | 4 ++-- tests/system/Database/Live/PretendTest.php | 2 +- .../system/Database/Live/SQLite/AlterTableTest.php | 6 +++--- tests/system/Filters/FiltersTest.php | 14 +++++++------- tests/system/HTTP/IncomingRequestTest.php | 4 ++-- tests/system/HTTP/ResponseTest.php | 6 +++--- tests/system/I18n/TimeTest.php | 2 +- tests/system/Images/BaseHandlerTest.php | 10 +++++----- tests/system/Images/ImageMagickHandlerTest.php | 4 ++-- tests/system/Language/LanguageTest.php | 6 +++--- tests/system/Log/LoggerTest.php | 4 ++-- tests/system/Models/InsertModelTest.php | 2 +- tests/system/Models/MiscellaneousModelTest.php | 2 +- tests/system/Models/UpdateModelTest.php | 2 +- tests/system/Models/ValidationModelTest.php | 2 +- tests/system/Test/FeatureTestTraitTest.php | 4 ++-- tests/system/Test/TestResponseTest.php | 8 ++++---- tests/system/View/ViewTest.php | 4 ++-- 26 files changed, 56 insertions(+), 56 deletions(-) diff --git a/tests/system/API/ResponseTraitTest.php b/tests/system/API/ResponseTraitTest.php index 958be5434689..1db28686eafe 100644 --- a/tests/system/API/ResponseTraitTest.php +++ b/tests/system/API/ResponseTraitTest.php @@ -488,7 +488,7 @@ public function testXMLFormatter() $this->formatter = new XMLFormatter(); $controller = $this->makeController(); - $this->assertSame('CodeIgniter\Format\XMLFormatter', get_class($this->formatter)); + $this->assertInstanceOf('CodeIgniter\Format\XMLFormatter', $this->formatter); $controller->respondCreated(['id' => 3], 'A Custom Reason'); $expected = <<<'EOH' diff --git a/tests/system/CLI/ConsoleTest.php b/tests/system/CLI/ConsoleTest.php index a5b3dd1e9783..087c28c12072 100644 --- a/tests/system/CLI/ConsoleTest.php +++ b/tests/system/CLI/ConsoleTest.php @@ -67,7 +67,7 @@ public function testHeader() $console = new Console($this->app); $console->showHeader(); $result = CITestStreamFilter::$buffer; - $this->assertTrue(strpos($result, sprintf('CodeIgniter v%s Command Line Tool', CodeIgniter::CI_VERSION)) > 0); + $this->assertGreaterThan(0, strpos($result, sprintf('CodeIgniter v%s Command Line Tool', CodeIgniter::CI_VERSION))); } public function testNoHeader() diff --git a/tests/system/CommonSingleServiceTest.php b/tests/system/CommonSingleServiceTest.php index bc2f4a1f60c8..7d078a6f9a2e 100644 --- a/tests/system/CommonSingleServiceTest.php +++ b/tests/system/CommonSingleServiceTest.php @@ -34,7 +34,7 @@ public function testSingleServiceWithNoParamsSupplied(string $service): void $service1 = single_service($service); $service2 = single_service($service); - $this->assertSame(get_class($service1), get_class($service2)); + $this->assertInstanceOf(get_class($service1), $service2); $this->assertNotSame($service1, $service2); } @@ -62,7 +62,7 @@ public function testSingleServiceWithAtLeastOneParamSupplied(string $service): v $service1 = single_service($service, ...$params); $service2 = single_service($service, ...$params); - $this->assertSame(get_class($service1), get_class($service2)); + $this->assertInstanceOf(get_class($service1), $service2); $this->assertNotSame($service1, $service2); if ($service === 'commands') { @@ -77,7 +77,7 @@ public function testSingleServiceWithAllParamsSupplied(): void // Assert that even passing true as last param this will // not create a shared instance. - $this->assertSame(get_class($cache1), get_class($cache2)); + $this->assertInstanceOf(get_class($cache1), $cache2); $this->assertNotSame($cache1, $cache2); } diff --git a/tests/system/Config/ConfigTest.php b/tests/system/Config/ConfigTest.php index 7f64a4851205..a784280bdc12 100644 --- a/tests/system/Config/ConfigTest.php +++ b/tests/system/Config/ConfigTest.php @@ -41,7 +41,7 @@ public function testCreateSharedInstance() $Config = Config::get('DocTypes'); $Config2 = Config::get('Config\\DocTypes'); - $this->assertTrue($Config === $Config2); + $this->assertSame($Config2, $Config); } public function testCreateNonConfig() diff --git a/tests/system/Config/ServicesTest.php b/tests/system/Config/ServicesTest.php index 77a0c77097fc..7fed04f53aa3 100644 --- a/tests/system/Config/ServicesTest.php +++ b/tests/system/Config/ServicesTest.php @@ -316,7 +316,7 @@ public function testReset() $response2 = service('response'); $this->assertInstanceOf(MockResponse::class, $response2); - $this->assertTrue($response !== $response2); + $this->assertNotSame($response2, $response); } /** diff --git a/tests/system/Cookie/CookieTest.php b/tests/system/Cookie/CookieTest.php index 781373755529..02a820218868 100644 --- a/tests/system/Cookie/CookieTest.php +++ b/tests/system/Cookie/CookieTest.php @@ -268,13 +268,13 @@ public function testArrayAccessOfCookie(): void { $cookie = new Cookie('cookie', 'monster'); - $this->assertTrue(isset($cookie['expire'])); + $this->assertArrayHasKey('expire', $cookie); $this->assertSame($cookie['expire'], $cookie->getExpiresTimestamp()); - $this->assertTrue(isset($cookie['httponly'])); + $this->assertArrayHasKey('httponly', $cookie); $this->assertSame($cookie['httponly'], $cookie->isHTTPOnly()); - $this->assertTrue(isset($cookie['samesite'])); + $this->assertArrayHasKey('samesite', $cookie); $this->assertSame($cookie['samesite'], $cookie->getSameSite()); - $this->assertTrue(isset($cookie['path'])); + $this->assertArrayHasKey('path', $cookie); $this->assertSame($cookie['path'], $cookie->getPath()); $this->expectException(InvalidArgumentException::class); diff --git a/tests/system/Database/Live/ConnectTest.php b/tests/system/Database/Live/ConnectTest.php index 5ee18a6f25eb..743b5450cca3 100644 --- a/tests/system/Database/Live/ConnectTest.php +++ b/tests/system/Database/Live/ConnectTest.php @@ -103,6 +103,6 @@ public function testConnectWithFailover() $db1 = Database::connect($this->tests); $this->assertSame($this->tests['failover'][0]['DBDriver'], $this->getPrivateProperty($db1, 'DBDriver')); - $this->assertTrue(count($db1->listTables()) >= 0); + $this->assertGreaterThanOrEqual(0, count($db1->listTables())); } } diff --git a/tests/system/Database/Live/DbUtilsTest.php b/tests/system/Database/Live/DbUtilsTest.php index c9b93242f4d1..2e8beda5f82f 100644 --- a/tests/system/Database/Live/DbUtilsTest.php +++ b/tests/system/Database/Live/DbUtilsTest.php @@ -79,7 +79,7 @@ public function testUtilsListDatabases() if (in_array($this->db->DBDriver, ['MySQLi', 'Postgre', 'SQLSRV'], true)) { $databases = $util->listDatabases(); - $this->assertTrue(in_array($this->db->getDatabase(), $databases, true)); + $this->assertContains($this->db->getDatabase(), $databases); } elseif ($this->db->DBDriver === 'SQLite3') { $this->expectException(DatabaseException::class); $this->expectExceptionMessage('Unsupported feature of the database platform you are using.'); diff --git a/tests/system/Database/Live/GetTest.php b/tests/system/Database/Live/GetTest.php index 2682f12e57ca..63f5ee9afd0c 100644 --- a/tests/system/Database/Live/GetTest.php +++ b/tests/system/Database/Live/GetTest.php @@ -78,8 +78,8 @@ public function testGetFieldNames() { $jobs = $this->db->table('job')->get()->getFieldNames(); - $this->assertTrue(in_array('name', $jobs, true)); - $this->assertTrue(in_array('description', $jobs, true)); + $this->assertContains('name', $jobs); + $this->assertContains('description', $jobs); } public function testGetFieldData() diff --git a/tests/system/Database/Live/PretendTest.php b/tests/system/Database/Live/PretendTest.php index b313f41fb7cb..3eae20e97cd2 100644 --- a/tests/system/Database/Live/PretendTest.php +++ b/tests/system/Database/Live/PretendTest.php @@ -36,7 +36,7 @@ public function testPretendReturnsQueryObject() ->table('user') ->get(); - $this->assertFalse($result instanceof Query); + $this->assertNotInstanceOf(Query::class, $result); $result = $this->db->pretend(true) ->table('user') diff --git a/tests/system/Database/Live/SQLite/AlterTableTest.php b/tests/system/Database/Live/SQLite/AlterTableTest.php index 029c764269a8..2816008a2a54 100644 --- a/tests/system/Database/Live/SQLite/AlterTableTest.php +++ b/tests/system/Database/Live/SQLite/AlterTableTest.php @@ -133,9 +133,9 @@ public function testDropColumnSuccess() $columns = $this->db->getFieldNames('foo'); - $this->assertFalse(in_array('name', $columns, true)); - $this->assertTrue(in_array('id', $columns, true)); - $this->assertTrue(in_array('email', $columns, true)); + $this->assertNotContains('name', $columns); + $this->assertContains('id', $columns); + $this->assertContains('email', $columns); } public function testDropColumnMaintainsKeys() diff --git a/tests/system/Filters/FiltersTest.php b/tests/system/Filters/FiltersTest.php index 6f5a94941f81..be5e04c5098e 100644 --- a/tests/system/Filters/FiltersTest.php +++ b/tests/system/Filters/FiltersTest.php @@ -553,7 +553,7 @@ public function testShortCircuit() $uri = 'admin/foo/bar'; $response = $filters->run($uri, 'before'); - $this->assertTrue($response instanceof ResponseInterface); + $this->assertInstanceOf(ResponseInterface::class, $response); $this->assertSame('http://google.com', $response->csp); } @@ -737,7 +737,7 @@ public function testAddFilter() $filters = $filters->initialize('admin/foo/bar'); $filters = $filters->getFilters(); - $this->assertTrue(in_array('some_alias', $filters['before'], true)); + $this->assertContains('some_alias', $filters['before']); } public function testAddFilterSection() @@ -753,7 +753,7 @@ public function testAddFilterSection() ->initialize('admin/foo/bar') ->getFilters(); - $this->assertTrue(in_array('another', $list['before'], true)); + $this->assertContains('another', $list['before']); } public function testInitializeTwice() @@ -770,7 +770,7 @@ public function testInitializeTwice() ->initialize() ->getFilters(); - $this->assertTrue(in_array('another', $list['before'], true)); + $this->assertContains('another', $list['before']); } public function testEnableFilter() @@ -791,7 +791,7 @@ public function testEnableFilter() $filters->enableFilter('google', 'before'); $filters = $filters->getFilters(); - $this->assertTrue(in_array('google', $filters['before'], true)); + $this->assertContains('google', $filters['before']); } public function testEnableFilterWithArguments() @@ -813,7 +813,7 @@ public function testEnableFilterWithArguments() $filters->enableFilter('role:admin , super', 'after'); $found = $filters->getFilters(); - $this->assertTrue(in_array('role', $found['before'], true)); + $this->assertContains('role', $found['before']); $this->assertSame(['admin', 'super'], $filters->getArguments('role')); $this->assertSame(['role' => ['admin', 'super']], $filters->getArguments()); @@ -845,7 +845,7 @@ public function testEnableFilterWithNoArguments() $filters->enableFilter('role', 'after'); $found = $filters->getFilters(); - $this->assertTrue(in_array('role', $found['before'], true)); + $this->assertContains('role', $found['before']); $response = $filters->run('admin/foo/bar', 'before'); diff --git a/tests/system/HTTP/IncomingRequestTest.php b/tests/system/HTTP/IncomingRequestTest.php index 1e975359a120..b467c9ca3e1a 100644 --- a/tests/system/HTTP/IncomingRequestTest.php +++ b/tests/system/HTTP/IncomingRequestTest.php @@ -544,8 +544,8 @@ public function testWithFalseBody() // Use `false` here to simulate file_get_contents returning a false value $request = new IncomingRequest(new App(), new URI(), false, new UserAgent()); - $this->assertTrue($request->getBody() !== false); - $this->assertTrue($request->getBody() === null); + $this->assertNotFalse($request->getBody()); + $this->assertNull($request->getBody()); } /** diff --git a/tests/system/HTTP/ResponseTest.php b/tests/system/HTTP/ResponseTest.php index dc50aa432140..64eab48dc0fa 100644 --- a/tests/system/HTTP/ResponseTest.php +++ b/tests/system/HTTP/ResponseTest.php @@ -63,7 +63,7 @@ public function testConstructWithCSPEnabled() $config->CSPEnabled = true; $response = new Response($config); - $this->assertTrue($response instanceof Response); + $this->assertInstanceOf(Response::class, $response); } public function testSetStatusCodeSetsReason() @@ -327,7 +327,7 @@ public function testJSONWithArray() $response->setJSON($body); $this->assertSame($expected, $response->getJSON()); - $this->assertTrue(strpos($response->getHeaderLine('content-type'), 'application/json') !== false); + $this->assertNotFalse(strpos($response->getHeaderLine('content-type'), 'application/json')); } public function testJSONGetFromNormalBody() @@ -364,7 +364,7 @@ public function testXMLWithArray() $response->setXML($body); $this->assertSame($expected, $response->getXML()); - $this->assertTrue(strpos($response->getHeaderLine('content-type'), 'application/xml') !== false); + $this->assertNotFalse(strpos($response->getHeaderLine('content-type'), 'application/xml')); } public function testXMLGetFromNormalBody() diff --git a/tests/system/I18n/TimeTest.php b/tests/system/I18n/TimeTest.php index e1e683c98d07..205a98098724 100644 --- a/tests/system/I18n/TimeTest.php +++ b/tests/system/I18n/TimeTest.php @@ -1023,7 +1023,7 @@ public function testCreateFromInstance() { $datetime = new DateTime(); $time = Time::createFromInstance($datetime); - $this->assertTrue($time instanceof Time); + $this->assertInstanceOf(Time::class, $time); $this->assertTrue($time->sameAs($datetime)); } diff --git a/tests/system/Images/BaseHandlerTest.php b/tests/system/Images/BaseHandlerTest.php index 708e4ef50d3a..8504779c44eb 100644 --- a/tests/system/Images/BaseHandlerTest.php +++ b/tests/system/Images/BaseHandlerTest.php @@ -58,7 +58,7 @@ protected function setUp(): void public function testNew() { $handler = Services::image('gd', null, false); - $this->assertTrue($handler instanceof BaseHandler); + $this->assertInstanceOf(BaseHandler::class, $handler); } public function testWithFile() @@ -68,7 +68,7 @@ public function testWithFile() $handler->withFile($path); $image = $handler->getFile(); - $this->assertTrue($image instanceof Image); + $this->assertInstanceOf(Image::class, $image); $this->assertSame(155, $image->origWidth); $this->assertSame($path, $image->getPathname()); } @@ -104,15 +104,15 @@ public function testFileTypes() $handler = Services::image('gd', null, false); $handler->withFile($this->start . 'ci-logo.png'); $image = $handler->getFile(); - $this->assertTrue($image instanceof Image); + $this->assertInstanceOf(Image::class, $image); $handler->withFile($this->start . 'ci-logo.jpeg'); $image = $handler->getFile(); - $this->assertTrue($image instanceof Image); + $this->assertInstanceOf(Image::class, $image); $handler->withFile($this->start . 'ci-logo.gif'); $image = $handler->getFile(); - $this->assertTrue($image instanceof Image); + $this->assertInstanceOf(Image::class, $image); } // Something handled by our Image diff --git a/tests/system/Images/ImageMagickHandlerTest.php b/tests/system/Images/ImageMagickHandlerTest.php index 02d02e305634..c79283b3f8fe 100644 --- a/tests/system/Images/ImageMagickHandlerTest.php +++ b/tests/system/Images/ImageMagickHandlerTest.php @@ -58,8 +58,8 @@ public function testGetVersion() // make sure that the call worked $this->assertNotFalse($version); // we should have a numeric version, greater than 6 - $this->assertTrue(version_compare($version, '6.0.0') >= 0); - $this->assertTrue(version_compare($version, '99.0.0') < 0); + $this->assertGreaterThanOrEqual(0, version_compare($version, '6.0.0')); + $this->assertLessThan(0, version_compare($version, '99.0.0')); } public function testImageProperties() diff --git a/tests/system/Language/LanguageTest.php b/tests/system/Language/LanguageTest.php index fcf4beea6257..0a501ea7947e 100644 --- a/tests/system/Language/LanguageTest.php +++ b/tests/system/Language/LanguageTest.php @@ -165,7 +165,7 @@ public function testLanguageFileLoading() $this->lang = new SecondMockLanguage('en'); $this->lang->loadem('More', 'en'); - $this->assertTrue(in_array('More', $this->lang->loaded(), true)); + $this->assertContains('More', $this->lang->loaded()); $this->lang->loadem('More', 'en'); $this->assertCount(1, $this->lang->loaded()); // should only be there once @@ -176,11 +176,11 @@ public function testLanguageFileLoadingReturns() $this->lang = new SecondMockLanguage('en'); $result = $this->lang->loadem('More', 'en', true); - $this->assertFalse(in_array('More', $this->lang->loaded(), true)); + $this->assertNotContains('More', $this->lang->loaded()); $this->assertCount(3, $result); $result = $this->lang->loadem('More', 'en'); - $this->assertTrue(in_array('More', $this->lang->loaded(), true)); + $this->assertContains('More', $this->lang->loaded()); $this->assertCount(1, $this->lang->loaded()); } diff --git a/tests/system/Log/LoggerTest.php b/tests/system/Log/LoggerTest.php index b092cb31041b..a97e16a51f1a 100644 --- a/tests/system/Log/LoggerTest.php +++ b/tests/system/Log/LoggerTest.php @@ -203,7 +203,7 @@ public function testLogInterpolatesFileAndLine() $logs = TestHandler::getLogs(); - $this->assertTrue(strpos($logs[0], $expected) > 1); + $this->assertGreaterThan(1, strpos($logs[0], $expected)); } public function testLogInterpolatesExceptions() @@ -222,7 +222,7 @@ public function testLogInterpolatesExceptions() $logs = TestHandler::getLogs(); $this->assertCount(1, $logs); - $this->assertTrue(strpos($logs[0], $expected) === 0); + $this->assertSame(0, strpos($logs[0], $expected)); } public function testEmergencyLogsCorrectly() diff --git a/tests/system/Models/InsertModelTest.php b/tests/system/Models/InsertModelTest.php index 521dec8fbadd..d08db6f87ac8 100644 --- a/tests/system/Models/InsertModelTest.php +++ b/tests/system/Models/InsertModelTest.php @@ -74,7 +74,7 @@ public function testInsertBatchValidationFail(): void $this->assertFalse($this->model->insertBatch($jobData)); $error = $this->model->errors(); - $this->assertTrue(isset($error['description'])); + $this->assertArrayHasKey('description', $error); } public function testInsertBatchSetsIntTimestamps(): void diff --git a/tests/system/Models/MiscellaneousModelTest.php b/tests/system/Models/MiscellaneousModelTest.php index e70ff51c4789..c513c023ab2c 100644 --- a/tests/system/Models/MiscellaneousModelTest.php +++ b/tests/system/Models/MiscellaneousModelTest.php @@ -93,7 +93,7 @@ public function testGetValidationMessagesForReplace(): void $this->assertFalse($this->model->replace($jobData)); $error = $this->model->errors(); - $this->assertTrue(isset($error['description'])); + $this->assertArrayHasKey('description', $error); } public function testUndefinedTypeInTransformDataToArray(): void diff --git a/tests/system/Models/UpdateModelTest.php b/tests/system/Models/UpdateModelTest.php index 888c019eca1e..5b6c9ca75972 100644 --- a/tests/system/Models/UpdateModelTest.php +++ b/tests/system/Models/UpdateModelTest.php @@ -153,7 +153,7 @@ public function testUpdateBatchValidationFail(): void $this->assertFalse($this->model->updateBatch($data, 'name')); $error = $this->model->errors(); - $this->assertTrue(isset($error['country'])); + $this->assertArrayHasKey('country', $error); } public function testUpdateBatchWithEntity(): void diff --git a/tests/system/Models/ValidationModelTest.php b/tests/system/Models/ValidationModelTest.php index b97532a09d68..0d60d36524ac 100644 --- a/tests/system/Models/ValidationModelTest.php +++ b/tests/system/Models/ValidationModelTest.php @@ -284,7 +284,7 @@ public function testRequiredWithValidationTrue(): void 'description' => 'just because we have to', ]; - $this->assertTrue($this->model->insert($data) !== false); + $this->assertNotFalse($this->model->insert($data)); } /** diff --git a/tests/system/Test/FeatureTestTraitTest.php b/tests/system/Test/FeatureTestTraitTest.php index 70952b89b96d..572ebe3d4244 100644 --- a/tests/system/Test/FeatureTestTraitTest.php +++ b/tests/system/Test/FeatureTestTraitTest.php @@ -366,7 +366,7 @@ public function testSetupRequestBodyWithParams() $request = $this->withBodyFormat('json')->setRequestBody($request, ['foo1' => 'bar1']); $this->assertJsonStringEqualsJsonString(json_encode(['foo1' => 'bar1']), $request->getBody()); - $this->assertTrue($request->header('Content-Type')->getValue() === 'application/json'); + $this->assertSame('application/json', $request->header('Content-Type')->getValue()); } public function testSetupRequestBodyWithXml() @@ -380,7 +380,7 @@ public function testSetupRequestBodyWithXml() '; $this->assertSame($expectedXml, $request->getBody()); - $this->assertTrue($request->header('Content-Type')->getValue() === 'application/xml'); + $this->assertSame('application/xml', $request->header('Content-Type')->getValue()); } public function testSetupRequestBodyWithBody() diff --git a/tests/system/Test/TestResponseTest.php b/tests/system/Test/TestResponseTest.php index 5bb3da21f1e7..cef63bd63af4 100644 --- a/tests/system/Test/TestResponseTest.php +++ b/tests/system/Test/TestResponseTest.php @@ -152,7 +152,7 @@ public function testAssertRedirectFail() { $this->getTestResponse('

Hello World

'); - $this->assertFalse($this->testResponse->response() instanceof RedirectResponse); + $this->assertNotInstanceOf(RedirectResponse::class, $this->testResponse->response()); $this->assertFalse($this->testResponse->isRedirect()); $this->testResponse->assertNotRedirect(); } @@ -162,7 +162,7 @@ public function testAssertRedirectSuccess() $this->getTestResponse('

Hello World

'); $this->testResponse->setResponse(new RedirectResponse(new App())); - $this->assertTrue($this->testResponse->response() instanceof RedirectResponse); + $this->assertInstanceOf(RedirectResponse::class, $this->testResponse->response()); $this->assertTrue($this->testResponse->isRedirect()); $this->testResponse->assertRedirect(); } @@ -172,7 +172,7 @@ public function testAssertRedirectSuccessWithoutRedirectResponse() $this->getTestResponse('

Hello World

'); $this->response->redirect('foo/bar'); - $this->assertFalse($this->testResponse->response() instanceof RedirectResponse); + $this->assertNotInstanceOf(RedirectResponse::class, $this->testResponse->response()); $this->assertTrue($this->testResponse->isRedirect()); $this->testResponse->assertRedirect(); $this->assertSame('foo/bar', $this->testResponse->getRedirectUrl()); @@ -345,7 +345,7 @@ public function testInvalidJSON() $this->response->setBody($tmp); // this should be FALSE - invalid JSON - will see if this is working that way ;-) - $this->assertFalse($this->response->getBody() === $this->testResponse->getJSON()); + $this->assertNotSame($this->testResponse->getJSON(), $this->response->getBody()); } public function testGetXML() diff --git a/tests/system/View/ViewTest.php b/tests/system/View/ViewTest.php index 7abeff5793e6..435c4d8f9578 100644 --- a/tests/system/View/ViewTest.php +++ b/tests/system/View/ViewTest.php @@ -316,8 +316,8 @@ public function testRenderLayoutWithInclude() $content = $view->render('extend_include'); - $this->assertTrue(strpos($content, '

Open

') !== false); - $this->assertTrue(strpos($content, '

Hello World

') !== false); + $this->assertNotFalse(strpos($content, '

Open

')); + $this->assertNotFalse(strpos($content, '

Hello World

')); $this->assertSame(2, substr_count($content, 'Hello World')); } From fa57efc742edff4b203597c7fc8a1bd10ab144f0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 12:04:16 +0900 Subject: [PATCH 097/407] docs: add space to method signatures --- user_guide_src/source/outgoing/view_parser.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/user_guide_src/source/outgoing/view_parser.rst b/user_guide_src/source/outgoing/view_parser.rst index 96b5440887b5..d35ba11f241a 100644 --- a/user_guide_src/source/outgoing/view_parser.rst +++ b/user_guide_src/source/outgoing/view_parser.rst @@ -55,7 +55,7 @@ can instantiate it directly:: Then you can use any of the three standard rendering methods that it provides: **render(viewpath, options, save)**, **setVar(name, value, context)** and **setData(data, context)**. You will also be able to specify delimiters directly, -through the **setDelimiters(left,right)** method. +through the **setDelimiters(left, right)** method. Using the ``Parser``, your view templates are processed only by the Parser itself, and not like a conventional view PHP script. PHP code in such a script @@ -696,7 +696,7 @@ Class Reference .. php:class:: CodeIgniter\\View\\Parser - .. php:method:: render($view[, $options[, $saveData=false]]) + .. php:method:: render($view[, $options[, $saveData = false]]) :param string $view: File name of the view source :param array $options: Array of options, as key/value pairs @@ -720,7 +720,7 @@ Class Reference Any conditional substitutions are performed first, then remaining substitutions are performed for each data pair. - .. php:method:: renderString($template[, $options[, $saveData=false]]) + .. php:method:: renderString($template[, $options[, $saveData = false]]) :param string $template: View source provided as a string :param array $options: Array of options, as key/value pairs @@ -734,7 +734,7 @@ Class Reference Options supported, and behavior, as above. - .. php:method:: setData([$data[, $context=null]]) + .. php:method:: setData([$data[, $context = null]]) :param array $data: Array of view data strings, as key/value pairs :param string $context: The context to use for data escaping. @@ -743,12 +743,12 @@ Class Reference Sets several pieces of view data at once:: - $renderer->setData(['name'=>'George', 'position'=>'Boss']); + $renderer->setData(['name' => 'George', 'position' => 'Boss']); Supported escape contexts: html, css, js, url, or attr or raw. If 'raw', no escaping will happen. - .. php:method:: setVar($name[, $value=null[, $context=null]]) + .. php:method:: setVar($name[, $value = null[, $context = null]]) :param string $name: Name of the view data variable :param mixed $value: The value of this view data From 58e6ff71842e5c4f75add798b8b1d30143249a10 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 12:04:48 +0900 Subject: [PATCH 098/407] docs: decorate variables with '``' --- user_guide_src/source/outgoing/view_parser.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/outgoing/view_parser.rst b/user_guide_src/source/outgoing/view_parser.rst index d35ba11f241a..c8f0c1fd5285 100644 --- a/user_guide_src/source/outgoing/view_parser.rst +++ b/user_guide_src/source/outgoing/view_parser.rst @@ -97,7 +97,7 @@ like this:: View parameters are passed to ``setData()`` as an associative array of data to be replaced in the template. In the above example, the -template would contain two variables: {blog_title} and {blog_heading} +template would contain two variables: ``{blog_title}`` and ``{blog_heading}`` The first parameter to ``render()`` contains the name of the :doc:`view file `, Where *blog_template* is the name of your view file. @@ -177,8 +177,8 @@ at the top of the page:: -In the above code you'll notice a pair of variables: {blog_entries} -data... {/blog_entries}. In a case like this, the entire chunk of data +In the above code you'll notice a pair of variables: ``{blog_entries}`` +data... ``{/blog_entries}``. In a case like this, the entire chunk of data between these pairs would be repeated multiple times, corresponding to the number of rows in the "blog_entries" element of the parameters array. From 6f1879e1c2d0af8cea85ccf7f99ecda08aebbec2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 12:05:25 +0900 Subject: [PATCH 099/407] docs: decorate filename with ** --- user_guide_src/source/outgoing/view_parser.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/outgoing/view_parser.rst b/user_guide_src/source/outgoing/view_parser.rst index c8f0c1fd5285..8bf3db46bb83 100644 --- a/user_guide_src/source/outgoing/view_parser.rst +++ b/user_guide_src/source/outgoing/view_parser.rst @@ -252,7 +252,7 @@ The value for the pseudo-variable ``blog_entry`` is an associative array. The key/value pairs defined inside it will be exposed inside the variable pair loop for that variable. -A ``blog_template`` that might work for the above:: +A **blog_template.php** that might work for the above::

{blog_title} - {blog_heading}

{blog_entry} From 8539b7ce0de7639a73c809186273c8c38efaf42e Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 12:42:27 +0900 Subject: [PATCH 100/407] docs: add sample code to show error flash message --- user_guide_src/source/libraries/security.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index b14535003648..81210975f687 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -151,7 +151,11 @@ Redirection on Failure ====================== When a request fails the CSRF validation check, it will redirect to the previous page by default, -setting an ``error`` flash message that you can display to the end user. This provides a nicer experience +setting an ``error`` flash message that you can display to the end user with the following code in your view:: + + getFlashdata('error') ?> + +This provides a nicer experience than simply crashing. This can be turned off by editing the following config parameter value in **app/Config/Security.php**:: From 413dfda51b617972199964734bdf46438447fd04 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 12:47:31 +0900 Subject: [PATCH 101/407] docs; add the section Config for CSRF, and move contents to it --- user_guide_src/source/libraries/security.rst | 93 ++++++++++---------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index 81210975f687..94845224a9e1 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -6,7 +6,7 @@ The Security Class contains methods that help protect your site against Cross-Si .. contents:: :local: - :depth: 2 + :depth: 3 ******************* Loading the Library @@ -26,8 +26,11 @@ Cross-site request forgery (CSRF) .. warning:: The CSRF Protection is only available for **POST/PUT/PATCH/DELETE** requests. Requests for other methods are not protected. +Config for CSRF +=============== + CSRF Protection Methods -======================= +----------------------- By default, the Cookie based CSRF Protection is used. It is `Double Submit Cookie `_ @@ -41,6 +44,49 @@ You can set to use the Session based CSRF protection by editing the following co public $csrfProtection = 'session'; +Token Randomization +------------------- + +To mitigate compression side-channel attacks like `BREACH`_, and prevent an attacker from guessing the CSRF tokens, you can configure token randomization (default off). + +If you enable it, a random mask is added to the token and used to scramble it. + +.. _`BREACH`: https://en.wikipedia.org/wiki/BREACH + +You can enable it by editing the following config parameter value in +**app/Config/Security.php**:: + + public $tokenRandomize = true; + +Token Regeneration +------------------ + +Tokens may be either regenerated on every submission (default) or +kept the same throughout the life of the CSRF cookie. The default +regeneration of tokens provides stricter security, but may result +in usability concerns as other tokens become invalid (back/forward +navigation, multiple tabs/windows, asynchronous actions, etc). You +may alter this behavior by editing the following config parameter value in +**app/Config/Security.php**:: + + public $regenerate = true; + +Redirection on Failure +---------------------- + +When a request fails the CSRF validation check, it will redirect to the previous page by default, +setting an ``error`` flash message that you can display to the end user with the following code in your view:: + + getFlashdata('error') ?> + +This provides a nicer experience +than simply crashing. This can be turned off by editing the following config parameter value in +**app/Config/Security.php**:: + + public $redirect = false; + +Even when the redirect value is ``true``, AJAX calls will not redirect, but will throw an error. + Enable CSRF Protection ====================== @@ -79,20 +125,6 @@ It is also possible to enable the CSRF filter only for specific methods:: 'post' => ['csrf'], ]; -Token Randomization -=================== - -To mitigate compression side-channel attacks like `BREACH`_, and prevent an attacker from guessing the CSRF tokens, you can configure token randomization (default off). - -If you enable it, a random mask is added to the token and used to scramble it. - -.. _`BREACH`: https://en.wikipedia.org/wiki/BREACH - -You can enable it by editing the following config parameter value in -**app/Config/Security.php**:: - - public $tokenRandomize = true; - HTML Forms ========== @@ -134,35 +166,6 @@ The order of checking the availability of the CSRF token is as follows: 2. HTTP header 3. ``php://input`` (JSON request) - bear in mind that this approach is the slowest one since we have to decode JSON and then re-encode it -Token Regeneration -=================== - -Tokens may be either regenerated on every submission (default) or -kept the same throughout the life of the CSRF cookie. The default -regeneration of tokens provides stricter security, but may result -in usability concerns as other tokens become invalid (back/forward -navigation, multiple tabs/windows, asynchronous actions, etc). You -may alter this behavior by editing the following config parameter value in -**app/Config/Security.php**:: - - public $regenerate = true; - -Redirection on Failure -====================== - -When a request fails the CSRF validation check, it will redirect to the previous page by default, -setting an ``error`` flash message that you can display to the end user with the following code in your view:: - - getFlashdata('error') ?> - -This provides a nicer experience -than simply crashing. This can be turned off by editing the following config parameter value in -**app/Config/Security.php**:: - - public $redirect = false; - -Even when the redirect value is ``true``, AJAX calls will not redirect, but will throw an error. - ********************* Other Helpful Methods ********************* From 12728c0d578d414f6ab8b65bd85f3298dac66a09 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 16:09:29 +0900 Subject: [PATCH 102/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/libraries/security.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index 94845224a9e1..9b317a75ea91 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -47,7 +47,7 @@ You can set to use the Session based CSRF protection by editing the following co Token Randomization ------------------- -To mitigate compression side-channel attacks like `BREACH`_, and prevent an attacker from guessing the CSRF tokens, you can configure token randomization (default off). +To mitigate compression side-channel attacks like `BREACH`_, and prevent an attacker from guessing the CSRF tokens, you can configure token randomization (off by default). If you enable it, a random mask is added to the token and used to scramble it. From 80b3340f31150236d1a1c3260a320f99ccdbf6e2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 16:42:56 +0900 Subject: [PATCH 103/407] test: refactor: isset() tests Separete Arrange, Act, and Assert. --- tests/system/Entity/EntityTest.php | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tests/system/Entity/EntityTest.php b/tests/system/Entity/EntityTest.php index 94d71849c679..026b58121f78 100644 --- a/tests/system/Entity/EntityTest.php +++ b/tests/system/Entity/EntityTest.php @@ -69,11 +69,19 @@ public function testIssetWorksLikeTraditionalIsset() { $entity = $this->getEntity(); - $this->assertFalse(isset($entity->foo)); + $issetReturn = isset($entity->foo); + + $this->assertFalse($issetReturn); $attributes = $this->getPrivateProperty($entity, 'attributes'); - $this->assertFalse(isset($attributes['foo'])); - $this->assertTrue(isset($attributes['default'])); + + $issetReturn = isset($attributes['foo']); + + $this->assertFalse($issetReturn); + + $issetReturn = isset($attributes['default']); + + $this->assertTrue($issetReturn); } public function testFill() @@ -905,13 +913,17 @@ public function testHasChangedKeyNotExists() public function testIssetKeyMap() { - $entity = $this->getEntity(); - + $entity = $this->getEntity(); $entity->created_at = '12345678'; - $this->assertTrue(isset($entity->createdAt)); + $entity->bar = 'foo'; - $entity->bar = 'foo'; - $this->assertTrue(isset($entity->FakeBar)); + $issetReturn = isset($entity->createdAt); + + $this->assertTrue($issetReturn); + + $issetReturn = isset($entity->FakeBar); + + $this->assertTrue($issetReturn); } public function testJsonSerializableEntity() From bd8ddfab17db44d51fb1aef89defeaf03a2918e9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 17:14:17 +0900 Subject: [PATCH 104/407] test: refactor: separete Arrange, Act, and Assert --- tests/system/Entity/EntityTest.php | 135 ++++++++++++++--------------- 1 file changed, 66 insertions(+), 69 deletions(-) diff --git a/tests/system/Entity/EntityTest.php b/tests/system/Entity/EntityTest.php index 026b58121f78..b423f244499d 100644 --- a/tests/system/Entity/EntityTest.php +++ b/tests/system/Entity/EntityTest.php @@ -75,13 +75,11 @@ public function testIssetWorksLikeTraditionalIsset() $attributes = $this->getPrivateProperty($entity, 'attributes'); - $issetReturn = isset($attributes['foo']); + $issetFooReturn = isset($attributes['foo']); + $issetDefaultReturn = isset($attributes['default']); - $this->assertFalse($issetReturn); - - $issetReturn = isset($attributes['default']); - - $this->assertTrue($issetReturn); + $this->assertFalse($issetFooReturn); + $this->assertTrue($issetDefaultReturn); } public function testFill() @@ -124,11 +122,9 @@ public function testDataMappingConvertsOriginalName() // Check mapped field $this->assertSame('made it', $entity->foo); - // Should also get from original name // since Model's would be looking for the original name $this->assertSame('made it', $entity->bar); - // But it shouldn't actually set a class property for the original name... $this->expectException(ReflectionException::class); $this->getPrivateProperty($entity, 'bar'); @@ -156,7 +152,6 @@ public function testIssetWorksWithMapping() $entity->bar = 'here'; $attributes = $this->getPrivateProperty($entity, 'attributes'); - $this->assertArrayHasKey('foo', $attributes); $this->assertArrayNotHasKey('bar', $attributes); } @@ -164,17 +159,18 @@ public function testIssetWorksWithMapping() public function testUnsetWorksWithMapping() { $entity = $this->getMappedEntity(); - // maps to 'foo' $entity->bar = 'here'; // doesn't work on original name unset($entity->bar); + $this->assertSame('here', $entity->bar); $this->assertSame('here', $entity->foo); // does work on mapped field unset($entity->foo); + $this->assertNull($entity->foo); $this->assertNull($entity->bar); } @@ -193,8 +189,7 @@ public function testDateMutationFromString() public function testDateMutationFromTimestamp() { - $stamp = time(); - + $stamp = time(); $entity = $this->getEntity(); $attributes = ['created_at' => $stamp]; $this->setPrivateProperty($entity, 'attributes', $attributes); @@ -238,7 +233,6 @@ public function testDateMutationStringToTime() $entity->created_at = '2017-07-15 13:23:34'; $time = $this->getPrivateProperty($entity, 'attributes')['created_at']; - $this->assertInstanceOf(Time::class, $time); $this->assertSame('2017-07-15 13:23:34', $time->format('Y-m-d H:i:s')); } @@ -251,7 +245,6 @@ public function testDateMutationTimestampToTime() $entity->created_at = $stamp; $time = $this->getPrivateProperty($entity, 'attributes')['created_at']; - $this->assertInstanceOf(Time::class, $time); $this->assertCloseEnoughString(date('Y-m-d H:i:s'), $time->format('Y-m-d H:i:s')); } @@ -264,7 +257,6 @@ public function testDateMutationDatetimeToTime() $entity->created_at = $dt; $time = $this->getPrivateProperty($entity, 'attributes')['created_at']; - $this->assertInstanceOf(Time::class, $time); $this->assertCloseEnoughString($dt->format('Y-m-d H:i:s'), $time->format('Y-m-d H:i:s')); } @@ -277,7 +269,6 @@ public function testDateMutationTimeToTime() $entity->created_at = $dt; $time = $this->getPrivateProperty($entity, 'attributes')['created_at']; - $this->assertInstanceOf(Time::class, $time); $this->assertCloseEnoughString($dt->format('Y-m-d H:i:s'), $time->format('Y-m-d H:i:s')); } @@ -287,10 +278,12 @@ public function testCastInteger() $entity = $this->getCastEntity(); $entity->first = 3.1; + $this->assertIsInt($entity->first); $this->assertSame(3, $entity->first); $entity->first = 3.6; + $this->assertSame(3, $entity->first); } @@ -299,10 +292,12 @@ public function testCastFloat() $entity = $this->getCastEntity(); $entity->second = 3; + $this->assertIsFloat($entity->second); $this->assertSame(3.0, $entity->second); $entity->second = '3.6'; + $this->assertIsFloat($entity->second); $this->assertSame(3.6, $entity->second); } @@ -312,10 +307,12 @@ public function testCastDouble() $entity = $this->getCastEntity(); $entity->third = 3; + $this->assertIsFloat($entity->third); $this->assertSame(3.0, $entity->third); $entity->third = '3.6'; + $this->assertIsFloat($entity->third); $this->assertSame(3.6, $entity->third); } @@ -325,6 +322,7 @@ public function testCastString() $entity = $this->getCastEntity(); $entity->fourth = 3.1415; + $this->assertIsString($entity->fourth); $this->assertSame('3.1415', $entity->fourth); } @@ -334,23 +332,24 @@ public function testCastBoolean() $entity = $this->getCastEntity(); $entity->fifth = 1; + $this->assertIsBool($entity->fifth); $this->assertTrue($entity->fifth); $entity->fifth = 0; + $this->assertIsBool($entity->fifth); $this->assertFalse($entity->fifth); } public function testCastCSV() { - $entity = $this->getCastEntity(); - - $data = ['foo', 'bar', 'bam']; - + $entity = $this->getCastEntity(); + $data = ['foo', 'bar', 'bam']; $entity->twelfth = $data; $result = $entity->toRawArray(); + $this->assertIsString($result['twelfth']); $this->assertSame('foo,bar,bam', $result['twelfth']); @@ -362,9 +361,9 @@ public function testCastObject() { $entity = $this->getCastEntity(); - $data = ['foo' => 'bar']; - + $data = ['foo' => 'bar']; $entity->sixth = $data; + $this->assertIsObject($entity->sixth); $this->assertInstanceOf(stdClass::class, $entity->sixth); $this->assertSame($data, (array) $entity->sixth); @@ -375,6 +374,7 @@ public function testCastDateTime() $entity = $this->getCastEntity(); $entity->eighth = 'March 12, 2017'; + $this->assertInstanceOf('DateTime', $entity->eighth); $this->assertSame('2017-03-12', $entity->eighth->format('Y-m-d')); } @@ -383,22 +383,21 @@ public function testCastTimestamp() { $entity = $this->getCastEntity(); - $date = 'March 12, 2017'; - + $date = 'March 12, 2017'; $entity->ninth = $date; + $this->assertIsInt($entity->ninth); $this->assertSame(strtotime($date), $entity->ninth); } public function testCastTimestampException() { - $entity = $this->getCastEntity(); - - $entity->ninth = 'some string'; - $this->expectException(CastException::class); $this->expectErrorMessage('Type casting "timestamp" expects a correct timestamp.'); + $entity = $this->getCastEntity(); + $entity->ninth = 'some string'; + $entity->ninth; } @@ -410,7 +409,6 @@ public function testCastArray() $check = $this->getPrivateProperty($entity, 'attributes')['seventh']; $this->assertSame(serialize(['foo' => 'bar']), $check); - $this->assertSame(['foo' => 'bar'], $entity->seventh); } @@ -445,27 +443,23 @@ public function testCastArrayByFill() $entity = $this->getCastEntity(); $data = ['seventh' => [1, 2, 3]]; - $entity->fill($data); // Check if serialiazed $check = $this->getPrivateProperty($entity, 'attributes')['seventh']; $this->assertSame(serialize([1, 2, 3]), $check); - // Check if unserialized $this->assertSame([1, 2, 3], $entity->seventh); } public function testCastArrayByConstructor() { - $data = ['seventh' => [1, 2, 3]]; - + $data = ['seventh' => [1, 2, 3]]; $entity = $this->getCastEntity($data); // Check if serialiazed $check = $this->getPrivateProperty($entity, 'attributes')['seventh']; $this->assertSame(serialize([1, 2, 3]), $check); - // Check if unserialized $this->assertSame([1, 2, 3], $entity->seventh); } @@ -485,9 +479,9 @@ public function testCastURI() { $entity = $this->getCastEntity(); - $data = 'https://codeigniter.com/banana'; - + $data = 'https://codeigniter.com/banana'; $entity->thirteenth = $data; + $this->assertInstanceOf(URI::class, $entity->thirteenth); $this->assertSame($data, (string) $entity->thirteenth); $this->assertSame('/banana', $entity->thirteenth->getPath()); @@ -497,9 +491,9 @@ public function testURICastURI() { $entity = $this->getCastEntity(); - $data = 'https://codeigniter.com/banana'; - + $data = 'https://codeigniter.com/banana'; $entity->thirteenth = new URI($data); + $this->assertInstanceOf(URI::class, $entity->thirteenth); $this->assertSame($data, (string) $entity->thirteenth); $this->assertSame('/banana', $entity->thirteenth->getPath()); @@ -523,8 +517,7 @@ public function testCastAsJSONArray() { $entity = $this->getCastEntity(); - $data = ['Sun', 'Mon', 'Tue']; - + $data = ['Sun', 'Mon', 'Tue']; $entity->eleventh = $data; // Should be a JSON-encoded string now... @@ -537,14 +530,13 @@ public function testCastAsJSONArray() public function testCastAsJsonByFill() { $entity = $this->getCastEntity(); - $data = ['eleventh' => [1, 2, 3]]; + $data = ['eleventh' => [1, 2, 3]]; $entity->fill($data); // Check if serialiazed $check = $this->getPrivateProperty($entity, 'attributes')['eleventh']; $this->assertSame(json_encode([1, 2, 3]), $check); - // Check if unserialized $this->assertSame([1, 2, 3], $entity->eleventh); } @@ -557,13 +549,15 @@ public function testCastAsJsonByConstructor() // Check if serialiazed $check = $this->getPrivateProperty($entity, 'attributes')['eleventh']; $this->assertSame(json_encode([1, 2, 3]), $check); - // Check if unserialized $this->assertSame([1, 2, 3], $entity->eleventh); } public function testCastAsJSONErrorDepth() { + $this->expectException(CastException::class); + $this->expectExceptionMessage('Maximum stack depth exceeded'); + $entity = $this->getCastEntity(); // Create array with depth 513 to get depth error @@ -576,24 +570,18 @@ public function testCastAsJSONErrorDepth() foreach ($keys as $key) { $current = &$current[$key]; } - - $current = $value; - $this->expectException(CastException::class); - $this->expectExceptionMessage('Maximum stack depth exceeded'); - + $current = $value; $entity->tenth = $array; - $this->getPrivateProperty($entity, 'tenth'); } public function testCastAsJSONErrorUTF8() { - $entity = $this->getCastEntity(); - $this->expectException(CastException::class); $this->expectExceptionMessage('Malformed UTF-8 characters, possibly incorrectly encoded'); + $entity = $this->getCastEntity(); + $entity->tenth = "\xB1\x31"; - $this->getPrivateProperty($entity, 'tenth'); } public function testCastAsJSONSyntaxError() @@ -615,7 +603,6 @@ public function testCastAsJSONAnotherErrorDepth() $this->expectExceptionMessage('Maximum stack depth exceeded'); $string = '{' . str_repeat('"test":{', 513) . '"test":"value"' . str_repeat('}', 513) . '}'; - (Closure::bind(static function (string $value) { $entity = new Entity(); $entity->casts['dummy'] = 'json[array]'; @@ -630,7 +617,6 @@ public function testCastAsJSONControlCharCheck() $this->expectExceptionMessage('Unexpected control character found'); $string = "{\n\t\"property1\": \"The quick brown fox\njumps over the lazy dog\",\n\t\"property2\":\"value2\"\n}"; - (Closure::bind(static function (string $value) { $entity = new Entity(); $entity->casts['dummy'] = 'json[array]'; @@ -645,7 +631,6 @@ public function testCastAsJSONStateMismatch() $this->expectExceptionMessage('Underflow or the modes mismatch'); $string = '[{"name":"jack","product_id":"1234"]'; - (Closure::bind(static function (string $value) { $entity = new Entity(); $entity->casts['dummy'] = 'json[array]'; @@ -656,16 +641,17 @@ public function testCastAsJSONStateMismatch() public function testCastSetter() { - $string = '321 String with numbers 123'; - $entity = $this->getCastEntity(); - + $string = '321 String with numbers 123'; + $entity = $this->getCastEntity(); $entity->first = $string; $entity->cast(false); + $this->assertIsString($entity->first); $this->assertSame($string, $entity->first); $entity->cast(true); + $this->assertIsInt($entity->first); $this->assertSame((int) $string, $entity->first); } @@ -684,18 +670,17 @@ public function testCustomCast() $entity->first = 'base 64'; $fieldValue = $this->getPrivateProperty($entity, 'attributes')['first']; - $this->assertSame(base64_encode('base 64'), $fieldValue); - $this->assertSame('base 64', $entity->first); } public function testCustomCastException() { - $entity = $this->getCustomCastEntity(); - $this->expectException(CastException::class); $this->expectErrorMessage('The "Tests\Support\Entity\Cast\NotExtendsBaseCast" class must inherit the "CodeIgniter\Entity\Cast\BaseCast" class'); + + $entity = $this->getCustomCastEntity(); + $entity->second = 'throw Exception'; } @@ -708,14 +693,17 @@ public function testCustomCastParams() $this->assertSame('value:["param1","param2","param3"]', $entity->third); $entity->fourth = 'test_nullable_type'; + $this->assertSame('test_nullable_type:["nullable"]', $entity->fourth); } public function testAsArray() { $entity = $this->getEntity(); + $result = $entity->toArray(); + // @TODO arguments are reversed $this->assertSame($result, [ 'foo' => null, 'bar' => ':bar', @@ -748,8 +736,10 @@ public function testAsArrayRecursive() public function testAsArrayMapped() { $entity = $this->getMappedEntity(); + $result = $entity->toArray(); + // @TODO arguments are reversed $this->assertSame($result, [ 'bar' => null, 'orig' => ':oo', @@ -759,8 +749,10 @@ public function testAsArrayMapped() public function testAsArraySwapped() { $entity = $this->getSwappedEntity(); + $result = $entity->toArray(); + // @TODO arguments are reversed $this->assertSame($result, [ 'bar' => 'foo', 'foo' => 'bar', @@ -779,6 +771,7 @@ public function testToArraySkipAttributesWithUnderscoreInFirstCharacter() $result = $entity->toArray(); + // @TODO arguments are reversed $this->assertSame($result, [ 'bar' => null, ]); @@ -786,12 +779,12 @@ public function testToArraySkipAttributesWithUnderscoreInFirstCharacter() public function testAsArrayOnlyChanged() { - $entity = $this->getEntity(); - + $entity = $this->getEntity(); $entity->bar = 'foo'; $result = $entity->toArray(true); + // @TODO arguments are reversed $this->assertSame($result, [ 'bar' => 'bar:foo:bar', ]); @@ -803,6 +796,7 @@ public function testToRawArray() $result = $entity->toRawArray(); + // @TODO arguments are reversed $this->assertSame($result, [ 'foo' => null, 'bar' => null, @@ -818,6 +812,7 @@ public function testToRawArrayRecursive() $result = $entity->toRawArray(false, true); + // @TODO arguments are reversed $this->assertSame($result, [ 'foo' => null, 'bar' => null, @@ -834,12 +829,12 @@ public function testToRawArrayRecursive() public function testToRawArrayOnlyChanged() { - $entity = $this->getEntity(); - + $entity = $this->getEntity(); $entity->bar = 'foo'; $result = $entity->toRawArray(true); + // @TODO arguments are reversed $this->assertSame($result, [ 'bar' => 'bar:foo', ]); @@ -851,17 +846,17 @@ public function testFilledConstruction() 'foo' => 'bar', 'bar' => 'baz', ]; - $something = new SomeEntity($data); + $this->assertSame('bar', $something->foo); $this->assertSame('baz', $something->bar); } public function testChangedArray() { - $data = ['bar' => 'baz']; - + $data = ['bar' => 'baz']; $something = new SomeEntity($data); + $this->assertSame($data, $something->toArray(true)); $something->magic = 'rockin'; @@ -908,6 +903,7 @@ public function testHasChangedWholeEntity() public function testHasChangedKeyNotExists() { $entity = $this->getEntity(); + $this->assertFalse($entity->hasChanged('xxx')); } @@ -930,6 +926,7 @@ public function testJsonSerializableEntity() { $entity = $this->getEntity(); $entity->setBar('foo'); + $this->assertSame(json_encode($entity->toArray()), json_encode($entity)); } From 76bd940514d8543e80aa67ba8f926574b5a7678c Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 17:26:09 +0900 Subject: [PATCH 105/407] test: refactor: isset() tests --- tests/system/Session/SessionTest.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/system/Session/SessionTest.php b/tests/system/Session/SessionTest.php index bb5afaacf515..c295e26ba7d3 100644 --- a/tests/system/Session/SessionTest.php +++ b/tests/system/Session/SessionTest.php @@ -245,20 +245,22 @@ public function testIssetReturnsTrueOnSuccess() { $session = $this->getInstance(); $session->start(); - $_SESSION['foo'] = 'bar'; - $this->assertTrue(isset($session->foo)); + $issetReturn = isset($session->foo); + + $this->assertTrue($issetReturn); } public function testIssetReturnsFalseOnNotFound() { $session = $this->getInstance(); $session->start(); - $_SESSION['foo'] = 'bar'; - $this->assertFalse(isset($session->bar)); + $issetReturn = isset($session->bar); + + $this->assertFalse($issetReturn); } public function testPushNewValueIntoArraySessionValue() @@ -400,7 +402,8 @@ public function testUnmarkFlashDataRemovesData() // Should still be here $this->assertTrue($session->has('foo')); // but no longer marked as flash - $this->assertFalse(isset($_SESSION['__ci_vars']['foo'])); + $issetReturn = isset($_SESSION['__ci_vars']['foo']); + $this->assertFalse($issetReturn); } public function testGetFlashKeysOnlyReturnsFlashKeys() From 0f97dcde9ef5397fe96011fd2cb2c86564176397 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 17:41:41 +0900 Subject: [PATCH 106/407] test: fix assert argument order --- tests/system/Entity/EntityTest.php | 40 ++++++++++++------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/tests/system/Entity/EntityTest.php b/tests/system/Entity/EntityTest.php index b423f244499d..15ae33371bb2 100644 --- a/tests/system/Entity/EntityTest.php +++ b/tests/system/Entity/EntityTest.php @@ -703,13 +703,12 @@ public function testAsArray() $result = $entity->toArray(); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'foo' => null, 'bar' => ':bar', 'default' => 'sumfin', 'createdAt' => null, - ]); + ], $result, ); } public function testAsArrayRecursive() @@ -739,11 +738,10 @@ public function testAsArrayMapped() $result = $entity->toArray(); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'bar' => null, 'orig' => ':oo', - ]); + ], $result); } public function testAsArraySwapped() @@ -752,12 +750,11 @@ public function testAsArraySwapped() $result = $entity->toArray(); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'bar' => 'foo', 'foo' => 'bar', 'original_bar' => 'bar', - ]); + ], $result); } public function testToArraySkipAttributesWithUnderscoreInFirstCharacter() @@ -771,10 +768,9 @@ public function testToArraySkipAttributesWithUnderscoreInFirstCharacter() $result = $entity->toArray(); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'bar' => null, - ]); + ], $result); } public function testAsArrayOnlyChanged() @@ -784,10 +780,9 @@ public function testAsArrayOnlyChanged() $result = $entity->toArray(true); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'bar' => 'bar:foo:bar', - ]); + ], $result); } public function testToRawArray() @@ -796,13 +791,12 @@ public function testToRawArray() $result = $entity->toRawArray(); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'foo' => null, 'bar' => null, 'default' => 'sumfin', 'created_at' => null, - ]); + ], $result); } public function testToRawArrayRecursive() @@ -812,8 +806,7 @@ public function testToRawArrayRecursive() $result = $entity->toRawArray(false, true); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'foo' => null, 'bar' => null, 'default' => 'sumfin', @@ -824,7 +817,7 @@ public function testToRawArrayRecursive() 'default' => 'sumfin', 'created_at' => null, ], - ]); + ], $result); } public function testToRawArrayOnlyChanged() @@ -834,10 +827,9 @@ public function testToRawArrayOnlyChanged() $result = $entity->toRawArray(true); - // @TODO arguments are reversed - $this->assertSame($result, [ + $this->assertSame([ 'bar' => 'bar:foo', - ]); + ], $result); } public function testFilledConstruction() From 18d32d86754790f8c0d24ea029aec598bae0dcb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Nov 2021 15:03:02 +0000 Subject: [PATCH 107/407] chore(deps-dev): update rector/rector requirement from 0.12.3 to 0.12.4 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/0.12.3...0.12.4) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 93286a4f93f8..4e3ebda66819 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.12.3" + "rector/rector": "0.12.4" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" From e33f1467b0f0c45de8b0ca9c412adaa95700e153 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell Date: Mon, 15 Nov 2021 23:15:19 -0600 Subject: [PATCH 108/407] Display file:line and trace information to database queries in debug toolbar --- system/Debug/Toolbar/Collectors/Database.php | 24 +++++++++++++++--- system/Debug/Toolbar/Views/_database.tpl | 11 ++++++++- system/Debug/Toolbar/Views/toolbar.css | 4 ++- system/Debug/Toolbar/Views/toolbar.js | 26 ++++++++++++++++++-- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/system/Debug/Toolbar/Collectors/Database.php b/system/Debug/Toolbar/Collectors/Database.php index d8445b80364f..639ba73be3e0 100644 --- a/system/Debug/Toolbar/Collectors/Database.php +++ b/system/Debug/Toolbar/Collectors/Database.php @@ -89,6 +89,7 @@ public static function collect(Query $query) 'query' => $query, 'string' => $queryString, 'duplicate' => in_array($queryString, array_column(static::$queries, 'string', null), true), + 'trace' => debug_backtrace(), ]; } } @@ -133,11 +134,26 @@ public function display(): array $data['queries'] = array_map(static function (array $query) { $isDuplicate = $query['duplicate'] === true; + // Find the first line that doesn't include `system` in the backtrace + $line = []; + + foreach ($query['trace'] as $traceLine) { + if (strpos($traceLine['file'], 'system/') !== false) { + continue; + } + $line = $traceLine; + break; + } + return [ - 'hover' => $isDuplicate ? 'This query was called more than once.' : '', - 'class' => $isDuplicate ? 'duplicate' : '', - 'duration' => ((float) $query['query']->getDuration(5) * 1000) . ' ms', - 'sql' => $query['query']->debugToolbarDisplay(), + 'hover' => $isDuplicate ? 'This query was called more than once.' : '', + 'class' => $isDuplicate ? 'duplicate' : '', + 'duration' => ((float) $query['query']->getDuration(5) * 1000) . ' ms', + 'sql' => $query['query']->debugToolbarDisplay(), + 'trace' => $query['trace'], + 'trace-file' => str_replace(ROOTPATH, '/', $line['file'] ?? ''), + 'trace-line' => $line['line'] ?? '', + 'qid' => md5((string) $query['query'] . microtime()), ]; }, static::$queries); diff --git a/system/Debug/Toolbar/Views/_database.tpl b/system/Debug/Toolbar/Views/_database.tpl index a373b56b5256..a2f5bd9808f1 100644 --- a/system/Debug/Toolbar/Views/_database.tpl +++ b/system/Debug/Toolbar/Views/_database.tpl @@ -7,9 +7,18 @@ {queries} - + {duration} {! sql !} + {trace-file}:{trace-line} + + + + + {trace} + {file}:{line}
+ {/trace} + {/queries} diff --git a/system/Debug/Toolbar/Views/toolbar.css b/system/Debug/Toolbar/Views/toolbar.css index b5a223b55d70..50ec4bff9e28 100644 --- a/system/Debug/Toolbar/Views/toolbar.css +++ b/system/Debug/Toolbar/Views/toolbar.css @@ -344,6 +344,8 @@ .debug-view.show-view { border-color: #DD8615; } +#debug-bar tr[data-toggle] { + cursor: pointer; } .debug-view-path { background-color: #FDC894; @@ -407,7 +409,7 @@ #debug-bar .muted { color: #DFDFDF; } #debug-bar .muted td { - color: #434343; } + color: #797979; } #debug-bar .muted:hover td { color: #DFDFDF; } #debug-bar #toolbar-position, diff --git a/system/Debug/Toolbar/Views/toolbar.js b/system/Debug/Toolbar/Views/toolbar.js index 690535f2de0d..b6883d4b9f3b 100644 --- a/system/Debug/Toolbar/Views/toolbar.js +++ b/system/Debug/Toolbar/Views/toolbar.js @@ -58,6 +58,13 @@ var ciDebugBar = { { buttons[i].addEventListener('click', ciDebugBar.showTab, true); } + + // Hook up generic toggle via data attributes `data-toggle="foo"` + var links = document.querySelectorAll('[data-toggle]'); + for (var i = 0; i < links.length; i++) + { + links[i].addEventListener('click', ciDebugBar.toggleRows, true); + } }, showTab: function () { @@ -124,6 +131,21 @@ var ciDebugBar = { } }, + /** + * Toggle display of another object based on + * the data-toggle value of this object + * + * @param event + */ + toggleRows : function(event) { + if(event.target) + { + let row = event.target.closest('tr'); + let target = document.getElementById(row.getAttribute('data-toggle')); + target.style.display = target.style.display === 'none' ? 'table-row' : 'none'; + } + }, + /** * Toggle display of a data table * @@ -137,7 +159,7 @@ var ciDebugBar = { if (obj) { - obj.style.display = obj.style.display == 'none' ? 'block' : 'none'; + obj.style.display = obj.style.display === 'none' ? 'block' : 'none'; } }, @@ -155,7 +177,7 @@ var ciDebugBar = { if (par && obj) { - obj.style.display = obj.style.display == 'none' ? '' : 'none'; + obj.style.display = obj.style.display === 'none' ? '' : 'none'; par.classList.toggle('timeline-parent-open'); } }, From 0ff83f2863c7d35638db4d003e4624ed60dc5de0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:18:24 +0900 Subject: [PATCH 109/407] docs: decorate variable names with '``' --- user_guide_src/source/models/model.rst | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index 18545f92f1bf..32fe2cf207c9 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -100,7 +100,7 @@ Connecting to the Database When the class is first instantiated, if no database connection instance is passed to the constructor, it will automatically connect to the default database group, as set in the configuration. You can -modify which group is used on a per-model basis by adding the DBGroup property to your class. +modify which group is used on a per-model basis by adding the ``$DBGroup`` property to your class. This ensures that within the model any references to ``$this->db`` are made through the appropriate connection. :: @@ -221,11 +221,11 @@ Leave it empty to avoid updating it (even if ``$useTimestamps`` is enabled) **$updatedField** Specifies which database field should use for keep data record update timestamp. -Leave it empty to avoid update it (even useTimestamps is enabled) +Leave it empty to avoid update it (even ``$useTimestamps`` is enabled). **$dateFormat** -This value works with $useTimestamps and $useSoftDeletes to ensure that the correct type of +This value works with ``$useTimestamps`` and ``$useSoftDeletes`` to ensure that the correct type of date value gets inserted into the database. By default, this creates DATETIME values, but valid options are: datetime, date, or int (a PHP timestamp). Using 'useSoftDeletes' or 'useTimestamps' with an invalid or missing dateFormat will cause an exception. @@ -277,7 +277,7 @@ Returns a single row where the primary key matches the value passed in as the fi $user = $userModel->find($user_id); -The value is returned in the format specified in $returnType. +The value is returned in the format specified in ``$returnType``. You can specify more than one row to return by passing an array of primaryKey values instead of just one:: @@ -293,7 +293,7 @@ Returns null or an indexed array of column values:: $user = $userModel->findColumn($column_name); -$column_name should be a name of single column else you will get the DataException. +``$column_name`` should be a name of single column else you will get the DataException. **findAll()** @@ -344,7 +344,7 @@ Saving Data **insert()** An associative array of data is passed into this method as the only parameter to create a new -row of data in the database. The array's keys must match the name of the columns in a $table, while +row of data in the database. The array's keys must match the name of the columns in a ``$table``, while the array's values are the values to save for that key:: $data = [ @@ -476,7 +476,7 @@ Takes a primary key value as the first parameter and deletes the matching record $userModel->delete(12); -If the model's $useSoftDeletes value is true, this will update the row to set ``deleted_at`` to the current +If the model's ``$useSoftDeletes`` value is true, this will update the row to set ``deleted_at`` to the current date and time. You can force a permanent delete by setting the second parameter as true. An array of primary keys can be passed in as the first parameter to delete multiple records at once:: @@ -642,7 +642,7 @@ Validation Placeholders The model provides a simple method to replace parts of your rules based on data that's being passed into it. This sounds fairly obscure but can be especially handy with the ``is_unique`` validation rule. Placeholders are simply -the name of the field (or array key) that was passed in as $data surrounded by curly brackets. It will be +the name of the field (or array key) that was passed in as ``$data`` surrounded by curly brackets. It will be replaced by the **value** of the matched incoming field. An example should clarify this:: protected $validationRules = [ @@ -694,7 +694,7 @@ need it:: $builder = $userModel->builder(); -This builder is already set up with the model's $table. If you need access to another table +This builder is already set up with the model's ``$table``. If you need access to another table you can pass it in as a parameter, but be aware that this will not return a shared instance:: $groupBuilder = $userModel->builder('groups'); @@ -757,14 +757,14 @@ Model Events There are several points within the model's execution that you can specify multiple callback methods to run. These methods can be used to normalize data, hash passwords, save related entities, and much more. The following -points in the model's execution can be affected, each through a class property: **$beforeInsert**, **$afterInsert**, -**$beforeUpdate**, **$afterUpdate**, **$afterFind**, and **$afterDelete**. +points in the model's execution can be affected, each through a class property: ``$beforeInsert``, ``$afterInsert``, +``$beforeUpdate``, ``$afterUpdate``, ``$afterFind``, and ``$afterDelete``. Defining Callbacks ------------------ You specify the callbacks by first creating a new class method in your model to use. This class will always -receive a $data array as its only parameter. The exact contents of the $data array will vary between events, but +receive a ``$data`` array as its only parameter. The exact contents of the ``$data`` array will vary between events, but will always contain a key named **data** that contains the primary data passed to the original method. In the case of the insert* or update* methods, that will be the key/value pairs that are being inserted into the database. The main array will also contain the other values passed to the method, and be detailed later. The callback method @@ -785,14 +785,14 @@ must return the original $data array so other callbacks have the full informatio Specifying Callbacks To Run --------------------------- -You specify when to run the callbacks by adding the method name to the appropriate class property (beforeInsert, afterUpdate, +You specify when to run the callbacks by adding the method name to the appropriate class property (``$beforeInsert``, ``$afterUpdate``, etc). Multiple callbacks can be added to a single event and they will be processed one after the other. You can use the same callback in multiple events:: protected $beforeInsert = ['hashPassword']; protected $beforeUpdate = ['hashPassword']; -Additionally, each model may allow (default) or deny callbacks class-wide by setting its $allowCallbacks property:: +Additionally, each model may allow (default) or deny callbacks class-wide by setting its ``$allowCallbacks`` property:: protected $allowCallbacks = false; @@ -804,7 +804,7 @@ You may also change this setting temporarily for a single model call sing the `` Event Parameters ---------------- -Since the exact data passed to each callback varies a bit, here are the details on what is in the $data parameter +Since the exact data passed to each callback varies a bit, here are the details on what is in the ``$data`` parameter passed to each event: ================ ========================================================================================================= From e21445f737df749cbef80a8642dec275b105d03a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:19:16 +0900 Subject: [PATCH 110/407] docs: fix coding style --- user_guide_src/source/models/model.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index 32fe2cf207c9..ca020ca686a4 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -591,17 +591,16 @@ The other way to set the validation message to fields by functions, Now, whenever you call the ``insert()``, ``update()``, or ``save()`` methods, the data will be validated. If it fails, the model will return boolean **false**. You can use the ``errors()`` method to retrieve the validation errors:: - if ($model->save($data) === false) - { + if ($model->save($data) === false) { return view('updateUser', ['errors' => $model->errors()]); } This returns an array with the field names and their associated errors that can be used to either show all of the errors at the top of the form, or to display them individually:: - +
- $error) : ?> + $error): ?>

@@ -774,7 +773,9 @@ must return the original $data array so other callbacks have the full informatio protected function hashPassword(array $data) { - if (! isset($data['data']['password'])) return $data; + if (! isset($data['data']['password'])) { + return $data; + } $data['data']['password_hash'] = password_hash($data['data']['password'], PASSWORD_DEFAULT); unset($data['data']['password']); From 00480eb7c1ac94f8ac9a93963fd287c384e5caf8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:23:17 +0900 Subject: [PATCH 111/407] docs: decorate method names with '``' --- user_guide_src/source/models/model.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index ca020ca686a4..97045ceb3787 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -201,8 +201,8 @@ configured to any name of your choice by using $deletedField property. **$allowedFields** -This array should be updated with the field names that can be set during save, insert, or -update methods. Any field names other than these will be discarded. This helps to protect +This array should be updated with the field names that can be set during ``save()``, ``insert()``, or +``update()`` methods. Any field names other than these will be discarded. This helps to protect against just taking input from a form and throwing it all at the model, resulting in potential mass assignment vulnerabilities. @@ -268,8 +268,8 @@ Working With Data Finding Data ------------ -Several functions are provided for doing basic CRUD work on your tables, including find(), -insert(), update(), delete() and more. +Several functions are provided for doing basic CRUD work on your tables, including ``find()``, +``insert()``, ``update()``, ``delete()`` and more. **find()** @@ -285,7 +285,7 @@ of just one:: $users = $userModel->find([1,2,3]); If no parameters are passed in, will return all rows in that model's table, effectively acting -like findAll(), though less explicit. +like ``findAll()``, though less explicit. **findColumn()** From 38047b5f23a102e16d48b8b264a02ca755bfe8e9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:30:13 +0900 Subject: [PATCH 112/407] docs: replace find*() with **find*()** --- user_guide_src/source/models/model.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index 97045ceb3787..bbb0d029f833 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -716,18 +716,18 @@ You can specify the format that data should be returned as when using the find*( $returnType. There may be times that you would like the data back in a different format, though. The Model provides methods that allow you to do just that. -.. note:: These methods only change the return type for the next find*() method call. After that, +.. note:: These methods only change the return type for the next **find*()** method call. After that, it is reset to its default value. **asArray()** -Returns data from the next find*() method as associative arrays:: +Returns data from the next **find*()** method as associative arrays:: $users = $userModel->asArray()->where('status', 'active')->findAll(); **asObject()** -Returns data from the next find*() method as standard objects or custom class intances:: +Returns data from the next **find*()** method as standard objects or custom class intances:: // Return as standard objects $users = $userModel->asObject()->where('status', 'active')->findAll(); From c80adce3bc0b5d7a35cec9ccf6eb4996bb5b5f82 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:31:48 +0900 Subject: [PATCH 113/407] docs: add comma --- user_guide_src/source/models/model.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index bbb0d029f833..2018f735f3c9 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -175,7 +175,7 @@ Specifies if the table uses an auto-increment feature for ``$primaryKey``. If se then you are responsible for providing primary key value for every record in the table. This feature may be handy when we want to implement 1:1 relation or use UUIDs for our model. -.. note:: If you set ``$useAutoIncrement`` to ``false`` then make sure to set your primary +.. note:: If you set ``$useAutoIncrement`` to ``false``, then make sure to set your primary key in the database to ``unique``. This way you will make sure that all of Model's features will still work the same as before. From 96664fead007f921c5bf6d9f5086e3b6e8cb381a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:32:20 +0900 Subject: [PATCH 114/407] docs: add period --- user_guide_src/source/models/model.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index 2018f735f3c9..f94a76d416de 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -216,7 +216,7 @@ data type. **$createdField** Specifies which database field to use for data record create timestamp. -Leave it empty to avoid updating it (even if ``$useTimestamps`` is enabled) +Leave it empty to avoid updating it (even if ``$useTimestamps`` is enabled). **$updatedField** From 57dc194602d5e0d1d335b8b6580cad7513442831 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:34:45 +0900 Subject: [PATCH 115/407] docs: emphasize table A Model is for a specific table. --- user_guide_src/source/models/model.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index f94a76d416de..2e592106ad92 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -9,7 +9,7 @@ Using CodeIgniter's Model Models ====== -Models provide a way to interact with a specific table in your database. They come out of the box with helper +Models provide a way to interact with a specific **table** in your database. They come out of the box with helper methods for much of the standard ways you would need to interact with a database table, including finding records, updating records, deleting records, and more. From e5519e48956fbf58ef1550091798060b84a6cf06 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:35:54 +0900 Subject: [PATCH 116/407] docs: fix delete* with delete() There is only one delete() method in the Model. --- user_guide_src/source/models/model.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index 2e592106ad92..5198818d0ec9 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -189,7 +189,7 @@ method. **$useSoftDeletes** -If true, then any delete* method calls will set ``deleted_at`` in the database, instead of +If true, then any ``delete()`` method calls will set ``deleted_at`` in the database, instead of actually deleting the row. This can preserve data when it might be referenced elsewhere, or can maintain a "recycle bin" of objects that can be restored, or even simply preserve it as part of a security trail. If true, the find* methods will only return non-deleted rows, unless From ab03da999e48312721643284b03e070a33572c0d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 16 Nov 2021 15:38:04 +0900 Subject: [PATCH 117/407] docs: decorate variable names, method names, etc --- user_guide_src/source/models/model.rst | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst index 5198818d0ec9..f3a75ef41056 100644 --- a/user_guide_src/source/models/model.rst +++ b/user_guide_src/source/models/model.rst @@ -183,8 +183,8 @@ feature may be handy when we want to implement 1:1 relation or use UUIDs for our The Model's CRUD methods will take a step of work away from you and automatically return the resulting data, instead of the Result object. This setting allows you to define -the type of data that is returned. Valid values are 'array', 'object', or the fully -qualified name of a class that can be used with the Result object's getCustomResultObject() +the type of data that is returned. Valid values are '**array**' (the default), '**object**', or the **fully +qualified name of a class** that can be used with the Result object's ``getCustomResultObject()`` method. **$useSoftDeletes** @@ -192,12 +192,12 @@ method. If true, then any ``delete()`` method calls will set ``deleted_at`` in the database, instead of actually deleting the row. This can preserve data when it might be referenced elsewhere, or can maintain a "recycle bin" of objects that can be restored, or even simply preserve it as -part of a security trail. If true, the find* methods will only return non-deleted rows, unless -the withDeleted() method is called prior to calling the find* method. +part of a security trail. If true, the **find*()** methods will only return non-deleted rows, unless +the ``withDeleted()`` method is called prior to calling the **find*()** method. This requires either a DATETIME or INTEGER field in the database as per the model's -$dateFormat setting. The default field name is ``deleted_at`` however this name can be -configured to any name of your choice by using $deletedField property. +``$dateFormat`` setting. The default field name is ``deleted_at`` however this name can be +configured to any name of your choice by using ``$deletedField`` property. **$allowedFields** @@ -209,8 +209,8 @@ potential mass assignment vulnerabilities. **$useTimestamps** This boolean value determines whether the current date is automatically added to all inserts -and updates. If true, will set the current time in the format specified by $dateFormat. This -requires that the table have columns named 'created_at' and 'updated_at' in the appropriate +and updates. If true, will set the current time in the format specified by ``$dateFormat``. This +requires that the table have columns named **created_at** and **updated_at** in the appropriate data type. **$createdField** @@ -227,8 +227,8 @@ Leave it empty to avoid update it (even ``$useTimestamps`` is enabled). This value works with ``$useTimestamps`` and ``$useSoftDeletes`` to ensure that the correct type of date value gets inserted into the database. By default, this creates DATETIME values, but -valid options are: datetime, date, or int (a PHP timestamp). Using 'useSoftDeletes' or -'useTimestamps' with an invalid or missing dateFormat will cause an exception. +valid options are: ``'datetime'``, ``'date'``, or ``'int'`` (a PHP timestamp). Using **useSoftDeletes** or +**useTimestamps** with an invalid or missing dateFormat will cause an exception. **$validationRules** @@ -243,7 +243,7 @@ described in :ref:`validation-custom-errors`. Described in more detail below. **$skipValidation** -Whether validation should be skipped during all ``inserts`` and ``updates``. The default +Whether validation should be skipped during all **inserts** and **updates**. The default value is false, meaning that data will always attempt to be validated. This is primarily used by the ``skipValidation()`` method, but may be changed to ``true`` so this model will never validate. @@ -321,8 +321,8 @@ Returns the first row in the result set. This is best used in combination with t **withDeleted()** -If $useSoftDeletes is true, then the find* methods will not return any rows where 'deleted_at IS NOT null'. -To temporarily override this, you can use the withDeleted() method prior to calling the find* method. +If ``$useSoftDeletes`` is true, then the **find*()** methods will not return any rows where 'deleted_at IS NOT NULL'. +To temporarily override this, you can use the ``withDeleted()`` method prior to calling the **find*()** method. :: // Only gets non-deleted rows (deleted = 0) @@ -333,8 +333,8 @@ To temporarily override this, you can use the withDeleted() method prior to call **onlyDeleted()** -Whereas withDeleted() will return both deleted and not-deleted rows, this method modifies -the next find* methods to return only soft deleted rows:: +Whereas ``withDeleted()`` will return both deleted and not-deleted rows, this method modifies +the next **find*()** methods to return only soft deleted rows:: $deletedUsers = $userModel->onlyDeleted()->findAll(); @@ -356,9 +356,9 @@ the array's values are the values to save for that key:: **update()** -Updates an existing record in the database. The first parameter is the $primaryKey of the record to update. +Updates an existing record in the database. The first parameter is the ``$primaryKey`` of the record to update. An associative array of data is passed into this method as the second parameter. The array's keys must match the name -of the columns in a $table, while the array's values are the values to save for that key:: +of the columns in a ``$table``, while the array's values are the values to save for that key:: $data = [ 'username' => 'darth', @@ -385,8 +385,8 @@ update command, with the added benefit of validation, events, etc:: **save()** -This is a wrapper around the insert() and update() methods that handle inserting or updating the record -automatically, based on whether it finds an array key matching the $primaryKey value:: +This is a wrapper around the ``insert()`` and ``update()`` methods that handle inserting or updating the record +automatically, based on whether it finds an array key matching the **primary key** value:: // Defined as a model property $primaryKey = 'id'; @@ -628,7 +628,7 @@ method directly, with options:: $rules = $model->getValidationRules($options); The ``$options`` parameter is an associative array with one element, -whose key is either "except" or "only", and which has as its +whose key is either ``'except'`` or ``'only'``, and which has as its value an array of fieldnames of interest.:: // get the rules for all but the "username" field @@ -712,8 +712,8 @@ very elegant use:: Runtime Return Type Changes ---------------------------- -You can specify the format that data should be returned as when using the find*() methods as the class property, -$returnType. There may be times that you would like the data back in a different format, though. The Model +You can specify the format that data should be returned as when using the **find*()** methods as the class property, +``$returnType``. There may be times that you would like the data back in a different format, though. The Model provides methods that allow you to do just that. .. note:: These methods only change the return type for the next **find*()** method call. After that, From e78e6c7c6a1241a2a7728ebb024b706d6d5b86d0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 17 Nov 2021 11:44:55 +0900 Subject: [PATCH 118/407] docs: fix execute() explanation --- user_guide_src/source/testing/controllers.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/testing/controllers.rst b/user_guide_src/source/testing/controllers.rst index e99a24d935f9..94ef7dad1135 100644 --- a/user_guide_src/source/testing/controllers.rst +++ b/user_guide_src/source/testing/controllers.rst @@ -69,13 +69,15 @@ Specifies the class name of the controller to test. The first parameter must be $this->controller(\App\Controllers\ForumController::class); -**execute($method)** +**execute(string $method, ...$params)** -Executes the specified method within the controller. The only parameter is the name of the method to run:: +Executes the specified method within the controller. The first parameter is the name of the method to run:: $results = $this->controller(\App\Controllers\ForumController::class) ->execute('showCategories'); +By specifying the second and subsequent parameters, you can pass them to the controller method. + This returns a new helper class that provides a number of routines for checking the response itself. See below for details. From 58644197b6cc4cbcbf94c12f11ead23ddd655042 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 17 Nov 2021 11:45:31 +0900 Subject: [PATCH 119/407] docs: fix withURI() signature --- user_guide_src/source/testing/controllers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/testing/controllers.rst b/user_guide_src/source/testing/controllers.rst index 94ef7dad1135..1f16cd615fc2 100644 --- a/user_guide_src/source/testing/controllers.rst +++ b/user_guide_src/source/testing/controllers.rst @@ -135,7 +135,7 @@ Allows you to provide a **Logger** instance:: If you do not provide one, a new Logger instance with the default configuration values will be passed into your controller. -**withURI($uri)** +**withURI(string $uri)** Allows you to provide a new URI that simulates the URL the client was visiting when this controller was run. This is helpful if you need to check URI segments within your controller. The only parameter is a string From 2d867408f32f0e033c09904f1adbb232ffe41234 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 17 Nov 2021 11:45:53 +0900 Subject: [PATCH 120/407] docs: elaborate on isOK() --- user_guide_src/source/testing/response.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/testing/response.rst b/user_guide_src/source/testing/response.rst index e5e0f34852ff..c5f7d9c34fbe 100644 --- a/user_guide_src/source/testing/response.rst +++ b/user_guide_src/source/testing/response.rst @@ -37,7 +37,7 @@ Checking Response Status **isOK()** Returns a boolean true/false based on whether the response is perceived to be "ok". This is primarily determined by -a response status code in the 200 or 300's. +a response status code in the 200 or 300's. An empty body is not considered valid, unless in redirects. :: if ($result->isOK()) { From 978089a058b4aa18017b0ba5fd7042b156624ee2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 17 Nov 2021 14:53:48 +0900 Subject: [PATCH 121/407] test: fix: move loading helper to setUp() If you run one test method, it fails. --- tests/system/Helpers/FilesystemHelperTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/Helpers/FilesystemHelperTest.php b/tests/system/Helpers/FilesystemHelperTest.php index 25a1cb1680bd..6492cab98708 100644 --- a/tests/system/Helpers/FilesystemHelperTest.php +++ b/tests/system/Helpers/FilesystemHelperTest.php @@ -37,11 +37,12 @@ protected function setUp(): void 'simpleFile' => 'A tap-tap-tapping upon my door', '.hidden' => 'There is no spoon', ]; + + helper('filesystem'); } public function testDirectoryMapDefaults() { - helper('filesystem'); $this->assertTrue(function_exists('directory_map')); $expected = [ @@ -65,7 +66,6 @@ public function testDirectoryMapDefaults() public function testDirectoryMapShowsHiddenFiles() { - helper('filesystem'); $this->assertTrue(function_exists('directory_map')); $expected = [ From a4a92edfff280d48a64ded19df56941e59ee906a Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 17 Nov 2021 14:54:53 +0900 Subject: [PATCH 122/407] test: fix: incorrect function name in assertions --- tests/system/Helpers/FilesystemHelperTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/Helpers/FilesystemHelperTest.php b/tests/system/Helpers/FilesystemHelperTest.php index 6492cab98708..c48ccd1ff328 100644 --- a/tests/system/Helpers/FilesystemHelperTest.php +++ b/tests/system/Helpers/FilesystemHelperTest.php @@ -257,7 +257,7 @@ public function testDeleteFilesFailure() public function testGetFilenames() { - $this->assertTrue(function_exists('delete_files')); + $this->assertTrue(function_exists('get_filenames')); // Not sure the directory names should actually show up // here but this matches v3.x results. @@ -279,7 +279,7 @@ public function testGetFilenames() public function testGetFilenamesWithHidden() { - $this->assertTrue(function_exists('delete_files')); + $this->assertTrue(function_exists('get_filenames')); // Not sure the directory names should actually show up // here but this matches v3.x results. From e97b95b2ffc8b11a4a97202cab12d6a839ddca93 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell Date: Wed, 17 Nov 2021 00:00:12 -0600 Subject: [PATCH 123/407] Fix rector error and cleanup up filename displays for Debug toolbar database tab. --- system/Debug/Toolbar/Collectors/Database.php | 15 ++++++++++----- system/Debug/Toolbar/Views/toolbar.css | 6 +++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/system/Debug/Toolbar/Collectors/Database.php b/system/Debug/Toolbar/Collectors/Database.php index 639ba73be3e0..a3fc7e435d56 100644 --- a/system/Debug/Toolbar/Collectors/Database.php +++ b/system/Debug/Toolbar/Collectors/Database.php @@ -137,12 +137,17 @@ public function display(): array // Find the first line that doesn't include `system` in the backtrace $line = []; - foreach ($query['trace'] as $traceLine) { - if (strpos($traceLine['file'], 'system/') !== false) { + foreach ($query['trace'] as &$traceLine) { + // Clean up the file paths + $traceLine['file'] = str_ireplace(APPPATH, 'APPPATH/', $traceLine['file']); + $traceLine['file'] = str_ireplace(SYSTEMPATH, 'SYSTEMPATH/', $traceLine['file']); + $traceLine['file'] = str_ireplace(VENDORPATH, 'VENDORPATH/', $traceLine['file']); + $traceLine['file'] = str_ireplace(ROOTPATH, 'ROOTPATH/', $traceLine['file']); + + if (strpos($traceLine['file'], 'APPPATH') === false) { continue; } - $line = $traceLine; - break; + $line = empty($line) ? $traceLine : $line; } return [ @@ -153,7 +158,7 @@ public function display(): array 'trace' => $query['trace'], 'trace-file' => str_replace(ROOTPATH, '/', $line['file'] ?? ''), 'trace-line' => $line['line'] ?? '', - 'qid' => md5((string) $query['query'] . microtime()), + 'qid' => md5($query['query'] . microtime()), ]; }, static::$queries); diff --git a/system/Debug/Toolbar/Views/toolbar.css b/system/Debug/Toolbar/Views/toolbar.css index 50ec4bff9e28..ed4230be0988 100644 --- a/system/Debug/Toolbar/Views/toolbar.css +++ b/system/Debug/Toolbar/Views/toolbar.css @@ -498,7 +498,7 @@ #toolbarContainer.dark #debug-bar .muted { color: #DFDFDF; } #toolbarContainer.dark #debug-bar .muted td { - color: #434343; } + color: #797979; } #toolbarContainer.dark #debug-bar .muted:hover td { color: #DFDFDF; } #toolbarContainer.dark #debug-bar #toolbar-position, @@ -589,9 +589,9 @@ -moz-box-shadow: 0 1px 4px #DFDFDF; -webkit-box-shadow: 0 1px 4px #DFDFDF; } #toolbarContainer.light #debug-bar .muted { - color: #434343; } + color: #797979; } #toolbarContainer.light #debug-bar .muted td { - color: #DFDFDF; } + color: #797979; } #toolbarContainer.light #debug-bar .muted:hover td { color: #434343; } #toolbarContainer.light #debug-bar #toolbar-position, From ccc4a5e8f45072de35b07da9e639f6f120880532 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell Date: Wed, 17 Nov 2021 00:02:22 -0600 Subject: [PATCH 124/407] Added note to changelog --- system/Debug/Toolbar/Collectors/Database.php | 2 +- user_guide_src/source/changelogs/v4.1.6.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Debug/Toolbar/Collectors/Database.php b/system/Debug/Toolbar/Collectors/Database.php index a3fc7e435d56..db13e14e920e 100644 --- a/system/Debug/Toolbar/Collectors/Database.php +++ b/system/Debug/Toolbar/Collectors/Database.php @@ -144,7 +144,7 @@ public function display(): array $traceLine['file'] = str_ireplace(VENDORPATH, 'VENDORPATH/', $traceLine['file']); $traceLine['file'] = str_ireplace(ROOTPATH, 'ROOTPATH/', $traceLine['file']); - if (strpos($traceLine['file'], 'APPPATH') === false) { + if (strpos($traceLine['file'], 'SYSTEMPATH') !== false) { continue; } $line = empty($line) ? $traceLine : $line; diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 80800ecbc94b..093ea6ca8aec 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -14,6 +14,7 @@ BREAKING Enhancements ============ +- Database pane on debug toolbar now displays location where Query was called from. Also displays full backtrace. Changes ======= From 328aa7670c7636db5775f88a6f39d374d098bf6f Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 08:48:44 +0900 Subject: [PATCH 125/407] chore: add seach example in Issue Form --- .github/ISSUE_TEMPLATE/bug_report.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 2c28200c36aa..cadb186f71ac 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -13,6 +13,9 @@ body: whether still open or closed, related to your report**. If there is, your report will be closed promptly. + For example, if you get the error "*Undefined property: Config\\Exceptions::$sensitiveDataInTrace*", + you can search the GitHub repository with the keyword "[$sensitiveDataInTrace](https://github.com/codeigniter4/CodeIgniter4/search?q=%24sensitiveDataInTrace&type=issues)". + --- - type: dropdown From e8db9099c65e0ac8cf81f81730a54d10a00ee8ad Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 08:49:31 +0900 Subject: [PATCH 126/407] chore: add codeigniter-installation in Issue Form --- .github/ISSUE_TEMPLATE/bug_report.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index cadb186f71ac..9dc91d2cc42a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -43,6 +43,19 @@ body: validations: required: true + - type: dropdown + id: codeigniter-installation + attributes: + label: CodeIgniter4 Installation + multiple: false + options: + - Composer; appstarter + - Composer; Adding CI4 to an Existing Project + - Manual (zip or tar.gz) + - Git + validations: + required: true + - type: dropdown id: operating-systems attributes: From 431546710ee21b8c409c78a48d9fe54b4f3da3b6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 09:35:32 +0900 Subject: [PATCH 127/407] docs: add @TODO See #5344 --- system/HTTP/IncomingRequest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index 128d6ee1c432..3ac25b6df5fd 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -64,6 +64,8 @@ class IncomingRequest extends Request * AFTER the script name. So, if hosted in a sub-folder this will * appear different than actual URL. If you need that use getPath(). * + * @TODO should be protected. Use getUri() instead. + * * @var URI */ public $uri; From 05ce6cb92a6822177a50f479620c6dd276c15ce7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 09:36:14 +0900 Subject: [PATCH 128/407] docs: don't use $request->uri See #5344 --- user_guide_src/source/concepts/http.rst | 2 +- user_guide_src/source/incoming/incomingrequest.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/concepts/http.rst b/user_guide_src/source/concepts/http.rst index 2696c91223d3..8ae030fc1811 100644 --- a/user_guide_src/source/concepts/http.rst +++ b/user_guide_src/source/concepts/http.rst @@ -75,7 +75,7 @@ is an object-oriented representation of the HTTP request. It provides everything $request = service('request'); // the URI being requested (i.e., /about) - $request->uri->getPath(); + $request->getUri()->getPath(); // Retrieve $_GET and $_POST variables $request->getGet('foo'); diff --git a/user_guide_src/source/incoming/incomingrequest.rst b/user_guide_src/source/incoming/incomingrequest.rst index e9f494961233..d08bf8470f70 100644 --- a/user_guide_src/source/incoming/incomingrequest.rst +++ b/user_guide_src/source/incoming/incomingrequest.rst @@ -249,13 +249,13 @@ The Request URL --------------- You can retrieve a :doc:`URI ` object that represents the current URI for this request through the -``$request->uri`` property. You can cast this object as a string to get a full URL for the current request:: +``$request->getUri()`` method. You can cast this object as a string to get a full URL for the current request:: - $uri = (string)$request->uri; + $uri = (string) $request->getUri(); The object gives you full abilities to grab any part of the request on it's own:: - $uri = $request->uri; + $uri = $request->getUri(); echo $uri->getScheme(); // http echo $uri->getAuthority(); // snoopy:password@example.com:88 From 19454015570810287529b88ef2dcf73ab2409e77 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 10:00:25 +0900 Subject: [PATCH 129/407] refactor: replace $request->uri with $request->getUri() See #5344 --- app/Views/errors/html/error_exception.php | 2 +- system/Common.php | 6 +++--- tests/system/HTTP/IncomingRequestTest.php | 2 +- tests/system/HTTP/URITest.php | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/Views/errors/html/error_exception.php b/app/Views/errors/html/error_exception.php index 4477ee08ff8b..693afed491f5 100644 --- a/app/Views/errors/html/error_exception.php +++ b/app/Views/errors/html/error_exception.php @@ -195,7 +195,7 @@ Path - uri) ?> + getUri()) ?> HTTP Method diff --git a/system/Common.php b/system/Common.php index 7c150a01c1d4..32943189b56b 100644 --- a/system/Common.php +++ b/system/Common.php @@ -480,9 +480,9 @@ function force_https(int $duration = 31536000, ?RequestInterface $request = null $uri = URI::createURIString( 'https', $baseURL, - $request->uri->getPath(), // Absolute URIs should use a "/" for an empty path - $request->uri->getQuery(), - $request->uri->getFragment() + $request->getUri()->getPath(), // Absolute URIs should use a "/" for an empty path + $request->getUri()->getQuery(), + $request->getUri()->getFragment() ); // Set an HSTS header diff --git a/tests/system/HTTP/IncomingRequestTest.php b/tests/system/HTTP/IncomingRequestTest.php index b467c9ca3e1a..3b14c6a03357 100644 --- a/tests/system/HTTP/IncomingRequestTest.php +++ b/tests/system/HTTP/IncomingRequestTest.php @@ -650,6 +650,6 @@ public function testSetPathUpdatesURI() $request->setPath('apples'); - $this->assertSame('apples', $request->uri->getPath()); + $this->assertSame('apples', $request->getUri()->getPath()); } } diff --git a/tests/system/HTTP/URITest.php b/tests/system/HTTP/URITest.php index acd491bccb9d..0438505aea2e 100644 --- a/tests/system/HTTP/URITest.php +++ b/tests/system/HTTP/URITest.php @@ -876,14 +876,14 @@ public function testBasedNoIndex() // going through request $this->assertSame('http://example.com/ci/v4/controller/method', (string) $request->uri); - $this->assertSame('/ci/v4/controller/method', $request->uri->getPath()); + $this->assertSame('/ci/v4/controller/method', $request->getUri()->getPath()); // standalone $uri = new URI('http://example.com/ci/v4/controller/method'); $this->assertSame('http://example.com/ci/v4/controller/method', (string) $uri); $this->assertSame('/ci/v4/controller/method', $uri->getPath()); - $this->assertSame($uri->getPath(), $request->uri->getPath()); + $this->assertSame($uri->getPath(), $request->getUri()->getPath()); } public function testBasedWithIndex() @@ -902,15 +902,15 @@ public function testBasedWithIndex() Services::injectMock('request', $request); // going through request - $this->assertSame('http://example.com/ci/v4/index.php/controller/method', (string) $request->uri); - $this->assertSame('/ci/v4/index.php/controller/method', $request->uri->getPath()); + $this->assertSame('http://example.com/ci/v4/index.php/controller/method', (string) $request->getUri()); + $this->assertSame('/ci/v4/index.php/controller/method', $request->getUri()->getPath()); // standalone $uri = new URI('http://example.com/ci/v4/index.php/controller/method'); $this->assertSame('http://example.com/ci/v4/index.php/controller/method', (string) $uri); $this->assertSame('/ci/v4/index.php/controller/method', $uri->getPath()); - $this->assertSame($uri->getPath(), $request->uri->getPath()); + $this->assertSame($uri->getPath(), $request->getUri()->getPath()); } public function testForceGlobalSecureRequests() @@ -933,13 +933,13 @@ public function testForceGlobalSecureRequests() Services::injectMock('request', $request); // Detected by request - $this->assertSame('https://example.com/ci/v4/controller/method', (string) $request->uri); + $this->assertSame('https://example.com/ci/v4/controller/method', (string) $request->getUri()); // Standalone $uri = new URI('http://example.com/ci/v4/controller/method'); $this->assertSame('https://example.com/ci/v4/controller/method', (string) $uri); - $this->assertSame(trim($uri->getPath(), '/'), trim($request->uri->getPath(), '/')); + $this->assertSame(trim($uri->getPath(), '/'), trim($request->getUri()->getPath(), '/')); } public function testZeroAsURIPath() From f4eed93bb01bf64b733c0d9afbae75be0592cf76 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 11:46:42 +0900 Subject: [PATCH 130/407] docs: remove /docs, because no such directory --- user_guide_src/source/concepts/structure.rst | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/user_guide_src/source/concepts/structure.rst b/user_guide_src/source/concepts/structure.rst index 14bb3a59304b..b55a3eac9ff1 100644 --- a/user_guide_src/source/concepts/structure.rst +++ b/user_guide_src/source/concepts/structure.rst @@ -8,8 +8,8 @@ can change to meet the needs of your application. Default Directories =================== -A fresh install has six directories: ``/app``, ``/system``, ``/public``, -``/writable``, ``/tests`` and possibly ``/docs``. +A fresh install has five directories: ``/app``, ``/public``, +``/writable``, ``/tests`` and ``/system`` or ``/vendor``. Each of these directories has a very specific part to play. app @@ -75,11 +75,6 @@ This directory is set up to hold your test files. The ``_support`` directory hol utilities that you can use while writing your tests. This directory does not need to be transferred to your production servers. -docs ----- -If this directory is part of your project, it holds a local copy of the CodeIgniter4 -User Guide. - Modifying Directory Locations ----------------------------- From ee08712be5b78f8ce0961b1615088821e2a9e7f8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 11:47:26 +0900 Subject: [PATCH 131/407] docs: add note when composer installation --- user_guide_src/source/concepts/structure.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/user_guide_src/source/concepts/structure.rst b/user_guide_src/source/concepts/structure.rst index b55a3eac9ff1..5c94b8542758 100644 --- a/user_guide_src/source/concepts/structure.rst +++ b/user_guide_src/source/concepts/structure.rst @@ -44,6 +44,9 @@ All files in this directory live under the ``App`` namespace, though you are fre system ------ + +.. note:: If you install CodeIgniter with Composer, the ``system`` is located in ``vendor/codeigniter4/framework/system``. + This directory stores the files that make up the framework, itself. While you have a lot of flexibility in how you use the application directory, the files in the system directory should never be modified. Instead, you should extend the classes, or create new classes, to provide the desired functionality. From 73371c46ac43828703c8d990d4a79656ed2c6f6c Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 11:55:47 +0900 Subject: [PATCH 132/407] docs: update sample code It is recommended to use BaseController instead of Controller. --- user_guide_src/source/tutorial/static_pages.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/tutorial/static_pages.rst b/user_guide_src/source/tutorial/static_pages.rst index d6874bc9fbe9..1763d1fae624 100644 --- a/user_guide_src/source/tutorial/static_pages.rst +++ b/user_guide_src/source/tutorial/static_pages.rst @@ -39,9 +39,7 @@ code. namespace App\Controllers; - use CodeIgniter\Controller; - - class Pages extends Controller + class Pages extends BaseController { public function index() { @@ -66,7 +64,7 @@ displays the CodeIgniter welcome page. Both are *technically* a function. But when you create a function in a class, it's called a method. -The ``Pages`` class is extending the +The ``Pages`` class is extending the ``BaseController`` class that extends the ``CodeIgniter\Controller`` class. This means that the new Pages class can access the methods and variables defined in the ``CodeIgniter\Controller`` class (**system/Controller.php**). From c0fedce2429ff332316f330c4c89bf8710cbe35b Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 11:56:45 +0900 Subject: [PATCH 133/407] docs: add CSRF error display in sample code --- .../source/tutorial/create_news_items.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/tutorial/create_news_items.rst b/user_guide_src/source/tutorial/create_news_items.rst index b4506b4dc322..604c2373314e 100644 --- a/user_guide_src/source/tutorial/create_news_items.rst +++ b/user_guide_src/source/tutorial/create_news_items.rst @@ -33,6 +33,7 @@ the slug from our title in the model. Create a new view at

+ getFlashdata('error') ?> listErrors() ?>
@@ -47,10 +48,15 @@ the slug from our title in the model. Create a new view at
-There are probably only two things here that look unfamiliar. The -``service('validation')->listErrors()`` function is used to report -errors related to form validation. The ``csrf_field()`` function creates -a hidden input with a CSRF token that helps protect against some common attacks. +There are probably only three things here that look unfamiliar. + +The ``getFlashdata('error') ?>`` function is used to report +errors related to CSRF protection. + +The ``service('validation')->listErrors()`` function is used to report +errors related to form validation. + +The ``csrf_field()`` function creates a hidden input with a CSRF token that helps protect against some common attacks. Go back to your ``News`` controller. You're going to do two things here, check whether the form was submitted and whether the submitted data From 88c4968fb3147cd33613d7cafaa31084e2d9a907 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 13:20:08 +0900 Subject: [PATCH 134/407] chore: fix script to copy tests directory --- .github/scripts/deploy-framework | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/scripts/deploy-framework b/.github/scripts/deploy-framework index c3f7e39fa1b7..9396ed88aa04 100644 --- a/.github/scripts/deploy-framework +++ b/.github/scripts/deploy-framework @@ -28,6 +28,8 @@ done # Copy repo-specific files cp -Rf ${SOURCE}/admin/framework/. ./ +# Copy tests files +cp -Rf ${SOURCE}/admin/starter/tests/. ./tests/ # Commit the changes git add . From d5c90f1668eafc4baa857f304668458526ec6c78 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 17:20:57 +0900 Subject: [PATCH 135/407] docs: make view filename lowercase Capital letters can also be used, but they are often lowercased. --- user_guide_src/source/outgoing/views.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/outgoing/views.rst b/user_guide_src/source/outgoing/views.rst index 19121c98b86a..4f865f6aaecb 100644 --- a/user_guide_src/source/outgoing/views.rst +++ b/user_guide_src/source/outgoing/views.rst @@ -19,7 +19,7 @@ Using the example controller you created in the controller page, let’s add a v Creating a View =============== -Using your text editor, create a file called ``BlogView.php`` and put this in it:: +Using your text editor, create a file called ``blogview.php`` and put this in it:: @@ -53,7 +53,7 @@ Now, open the controller file you made earlier called ``Blog.php``, and replace { public function index() { - echo view('BlogView'); + echo view('blogview'); } } @@ -111,7 +111,7 @@ If you have ``Blog`` directory that has a PSR-4 mapping set up in the :doc:`Auto under the namespace ``Example\Blog``, you could retrieve view files as if they were namespaced also. Following this example, you could load the **BlogView** file from **/blog/views** by prepending the namespace to the view name:: - echo view('Example\Blog\Views\BlogView'); + echo view('Example\Blog\Views\blogview'); Caching Views ============= From 05ce8a5142dc3f4ecb72427eeedc5c5959f75e22 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 17:23:39 +0900 Subject: [PATCH 136/407] docs: fix directory name Saying that "If you have ``Blog`` directory", the directory name must be Blog, not blog. --- user_guide_src/source/outgoing/views.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/outgoing/views.rst b/user_guide_src/source/outgoing/views.rst index 4f865f6aaecb..b01466ce40da 100644 --- a/user_guide_src/source/outgoing/views.rst +++ b/user_guide_src/source/outgoing/views.rst @@ -109,7 +109,7 @@ to package your views together in a module-like fashion for easy re-use or distr If you have ``Blog`` directory that has a PSR-4 mapping set up in the :doc:`Autoloader ` living under the namespace ``Example\Blog``, you could retrieve view files as if they were namespaced also. Following this -example, you could load the **BlogView** file from **/blog/views** by prepending the namespace to the view name:: +example, you could load the **blogview.php** file from **Blog/Views** by prepending the namespace to the view name:: echo view('Example\Blog\Views\blogview'); From 5a3ba8012e09c060ca595b0c705e2229d722d426 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 17:29:12 +0900 Subject: [PATCH 137/407] docs: fix incorrect method name --- user_guide_src/source/incoming/routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 5dade8d13f3d..9778307bc4fa 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -330,7 +330,7 @@ Command-Line only Routes You can create routes that work only from the command-line, and are inaccessible from the web browser, with the ``cli()`` method. This is great for building cronjobs or CLI-only tools. Any route created by any of the HTTP-verb-based -route methods will also be inaccessible from the CLI, but routes created by the ``any()`` method will still be +route methods will also be inaccessible from the CLI, but routes created by the ``add()`` method will still be available from the command line:: $routes->cli('migrate', 'App\Database::migrate'); From b4da1c1629350bf04bd8e5eefe78a97908b3c35f Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 19 Nov 2021 13:53:30 +0900 Subject: [PATCH 138/407] chore: fix by review Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 9dc91d2cc42a..cbc27bc81a22 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -46,7 +46,7 @@ body: - type: dropdown id: codeigniter-installation attributes: - label: CodeIgniter4 Installation + label: CodeIgniter4 Installation Method multiple: false options: - Composer; appstarter From b31256fc03bccd8d0bfb8c43f40d9745c56e7bbd Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 19 Nov 2021 13:53:38 +0900 Subject: [PATCH 139/407] chore: fix by review Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index cbc27bc81a22..975c611a61c3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -49,8 +49,8 @@ body: label: CodeIgniter4 Installation Method multiple: false options: - - Composer; appstarter - - Composer; Adding CI4 to an Existing Project + - Composer (using `codeigniter4/appstarter`) + - Composer (as dependency to an existing project) - Manual (zip or tar.gz) - Git validations: From 27d216b62db26246fa08eb686347b11670dd9c77 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Nov 2021 11:22:36 +0900 Subject: [PATCH 140/407] fix: UploadedFile::hasMoved() may return incorrect value --- system/HTTP/Files/UploadedFile.php | 13 ++++-- tests/system/HTTP/Files/FileMovingTest.php | 52 +++++++++++++++++++++- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/system/HTTP/Files/UploadedFile.php b/system/HTTP/Files/UploadedFile.php index 6455a5106d8d..42bb9891f90b 100644 --- a/system/HTTP/Files/UploadedFile.php +++ b/system/HTTP/Files/UploadedFile.php @@ -141,7 +141,7 @@ public function move(string $targetPath, ?string $name = null, bool $overwrite = $destination = $overwrite ? $targetPath . $name : $this->getDestination($targetPath . $name); try { - move_uploaded_file($this->path, $destination); + $this->hasMoved = move_uploaded_file($this->path, $destination); } catch (Exception $e) { $error = error_get_last(); $message = isset($error['message']) ? strip_tags($error['message']) : ''; @@ -149,12 +149,17 @@ public function move(string $targetPath, ?string $name = null, bool $overwrite = throw HTTPException::forMoveFailed(basename($this->path), $targetPath, $message); } + if ($this->hasMoved === false) { + $message = 'move_uploaded_file() returned false'; + + throw HTTPException::forMoveFailed(basename($this->path), $targetPath, $message); + } + @chmod($targetPath, 0777 & ~umask()); // Success, so store our new information - $this->path = $targetPath; - $this->name = basename($destination); - $this->hasMoved = true; + $this->path = $targetPath; + $this->name = basename($destination); return true; } diff --git a/tests/system/HTTP/Files/FileMovingTest.php b/tests/system/HTTP/Files/FileMovingTest.php index 9797ca46c301..c9234a82dc6b 100644 --- a/tests/system/HTTP/Files/FileMovingTest.php +++ b/tests/system/HTTP/Files/FileMovingTest.php @@ -35,6 +35,9 @@ protected function setUp(): void } $_FILES = []; + + // Set the mock's return value to true + move_uploaded_file('', '', true); } protected function tearDown(): void @@ -262,7 +265,7 @@ public function testInvalidFile() $file->move($destination, $file->getName(), false); } - public function testFailedMove() + public function testFailedMoveBecauseOfWarning() { $_FILES = [ 'userfile' => [ @@ -287,6 +290,41 @@ public function testFailedMove() $this->expectException(HTTPException::class); $file->move($destination, $file->getName(), false); } + + public function testFailedMoveBecauseOfFalseReturned() + { + $finalFilename = 'fileA'; + + $_FILES = [ + 'userfile1' => [ + 'name' => $finalFilename . '.txt', + 'type' => 'text/plain', + 'size' => 124, + 'tmp_name' => '/tmp/fileA.txt', + 'error' => 0, + ], + ]; + + $collection = new FileCollection(); + + $this->assertTrue($collection->hasFile('userfile1')); + + $destination = $this->destination; + + // Create the destination if not exists + if (! is_dir($destination)) { + mkdir($destination, 0777, true); + } + + $file = $collection->getFile('userfile1'); + + // Set the mock's return value to false + move_uploaded_file('', '', false); + + $this->expectException(HTTPException::class); + + $file->move($destination, $file->getName(), false); + } } /* @@ -311,10 +349,20 @@ function is_uploaded_file($filename) * This overwrite is for testing the move operation. */ -function move_uploaded_file($filename, $destination) +function move_uploaded_file($filename, $destination, ?bool $setReturnValue = null) { + static $return = true; + + if ($setReturnValue !== null) { + $return = $setReturnValue; + + return true; + } + copy($filename, $destination); unlink($filename); + + return $return; } function rrmdir($src) From 2425b291c333c1265ce4a44c5206bb8419c028d2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 20 Nov 2021 11:47:15 +0900 Subject: [PATCH 141/407] docs: fix incorrect namespace in sample code --- user_guide_src/source/general/helpers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/helpers.rst b/user_guide_src/source/general/helpers.rst index 65d63d942631..51deea953590 100644 --- a/user_guide_src/source/general/helpers.rst +++ b/user_guide_src/source/general/helpers.rst @@ -78,7 +78,7 @@ code into its own namespace, ``Example\Blog``. The files exist on our server at **/Modules/Blog/Helpers/blog_helper.php**. Within our controller we could use the following command to load the helper for us:: - helper('Modules\Blog\blog'); + helper('Example\Blog\blog'); .. note:: The functions within files loaded this way are not truly namespaced. The namespace is simply used as a convenient way to locate the files. From 843ddb96846029c8814c121e5ae5de6394584368 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 20 Nov 2021 13:13:38 +0900 Subject: [PATCH 142/407] test: add test for table alias and table prefix --- tests/system/Database/Builder/AliasTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/system/Database/Builder/AliasTest.php b/tests/system/Database/Builder/AliasTest.php index b6789d987708..d6d2c8618741 100644 --- a/tests/system/Database/Builder/AliasTest.php +++ b/tests/system/Database/Builder/AliasTest.php @@ -84,4 +84,20 @@ public function testAliasLeftJoinWithLongTableName() $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); } + + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5360 + */ + public function testAliasSimpleLikeWithDBPrefix() + { + $this->setPrivateProperty($this->db, 'DBPrefix', 'db_'); + $builder = $this->db->table('jobs j'); + + $builder->like('j.name', 'veloper'); + + $expectedSQL = <<<'SQL' + SELECT * FROM "db_jobs" "j" WHERE "j"."name" LIKE '%veloper%' ESCAPE '!' + SQL; + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); + } } From 20411e61851493f210db2877ede2603f8000f467 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 20 Nov 2021 15:20:02 +0900 Subject: [PATCH 143/407] fix: if condition where the first segment is one of the aliases previously identified Fixes #5360 --- system/Database/BaseConnection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index ebb63b7f5827..c7f4e124d507 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1012,7 +1012,8 @@ public function protectIdentifiers($item, bool $prefixSingle = false, ?bool $pro // // NOTE: The ! empty() condition prevents this method // from breaking when QB isn't enabled. - if (! empty($this->aliasedTables) && in_array($parts[0], $this->aliasedTables, true)) { + $firstSegment = trim($parts[0], $this->escapeChar); + if (! empty($this->aliasedTables) && in_array($firstSegment, $this->aliasedTables, true)) { if ($protectIdentifiers === true) { foreach ($parts as $key => $val) { if (! in_array($val, $this->reservedIdentifiers, true)) { From 7f0e921dfe32a42b38c1b2490a624b50d1a3d0ef Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 2 Nov 2021 16:28:18 +0900 Subject: [PATCH 144/407] fix: Query builder escapes negative integers Fixes #4973 --- system/Database/BaseConnection.php | 2 +- tests/system/Database/BaseQueryTest.php | 18 ++++++++++++++++++ tests/system/Database/Live/EscapeTest.php | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index ebb63b7f5827..6279e822a10c 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1201,7 +1201,7 @@ public function escape($str) } if (is_numeric($str) && $str < 0) { - return "'{$str}'"; + return "{$str}"; } return $str ?? 'NULL'; diff --git a/tests/system/Database/BaseQueryTest.php b/tests/system/Database/BaseQueryTest.php index fe942ffeb187..a279e01dd444 100644 --- a/tests/system/Database/BaseQueryTest.php +++ b/tests/system/Database/BaseQueryTest.php @@ -345,6 +345,24 @@ public function testSetQueryBindsWithSetEscapeFalse() $this->assertSame($expected, $query->getQuery()); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/4973 + */ + public function testSetQueryBindsWithSetEscapeNegativeIntegers() + { + $query = new Query($this->db); + + $query->setQuery( + 'SELECT * FROM product WHERE date_pickup < DateAdd(month, ?, Convert(date, GetDate())', + [-6], + true + ); + + $expected = 'SELECT * FROM product WHERE date_pickup < DateAdd(month, -6, Convert(date, GetDate())'; + + $this->assertSame($expected, $query->getQuery()); + } + /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/2762 */ diff --git a/tests/system/Database/Live/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index 08265788d00e..9099115e45d0 100644 --- a/tests/system/Database/Live/EscapeTest.php +++ b/tests/system/Database/Live/EscapeTest.php @@ -40,7 +40,7 @@ protected function setUp(): void */ public function testEscapeProtectsNegativeNumbers() { - $this->assertSame("'-100'", $this->db->escape(-100)); + $this->assertSame('-100', $this->db->escape(-100)); } public function testEscape() From 034b1332a09ab876f8922b62e57c122ccf89ba53 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 2 Nov 2021 16:29:07 +0900 Subject: [PATCH 145/407] docs: add PHPDoc --- system/Database/BaseConnection.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 6279e822a10c..6902490dea1c 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -565,7 +565,7 @@ abstract protected function execute(string $sql); * * @param mixed ...$binds * - * @return BaseResult|bool|Query + * @return BaseResult|bool|Query BaseResult when “read” type query, bool when “write” type query, Query when prepared query * * @todo BC set $queryClass default as null in 4.1 */ @@ -955,6 +955,8 @@ public function getConnectDuration(int $decimals = 6): string * the correct identifiers. * * @param array|string $item + * @param bool $prefixSingle Prefix an item with no segments? + * @param bool $fieldExists Supplied $item contains a field name? * * @return array|string */ From 69e79fbe8be7eb1d4a371d051a2d5cfa2575d81b Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 2 Nov 2021 19:50:34 +0900 Subject: [PATCH 146/407] fix: remove escaping code for negative integer It is inconsistent, with negative numbers we get a string. For positive, we get numbers. --- system/Database/BaseConnection.php | 4 ---- tests/system/Database/BaseQueryTest.php | 14 ++++++++++++++ tests/system/Database/Live/EscapeTest.php | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 6902490dea1c..44654e4423a0 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1202,10 +1202,6 @@ public function escape($str) return ($str === false) ? 0 : 1; } - if (is_numeric($str) && $str < 0) { - return "{$str}"; - } - return $str ?? 'NULL'; } diff --git a/tests/system/Database/BaseQueryTest.php b/tests/system/Database/BaseQueryTest.php index a279e01dd444..d7fe4bca2819 100644 --- a/tests/system/Database/BaseQueryTest.php +++ b/tests/system/Database/BaseQueryTest.php @@ -363,6 +363,20 @@ public function testSetQueryBindsWithSetEscapeNegativeIntegers() $this->assertSame($expected, $query->getQuery()); } + public function testSetQueryNamedBindsWithNegativeIntegers() + { + $query = new Query($this->db); + + $query->setQuery( + 'SELECT * FROM product WHERE date_pickup < DateAdd(month, :num:, Convert(date, GetDate())', + ['num' => -6] + ); + + $expected = 'SELECT * FROM product WHERE date_pickup < DateAdd(month, -6, Convert(date, GetDate())'; + + $this->assertSame($expected, $query->getQuery()); + } + /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/2762 */ diff --git a/tests/system/Database/Live/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index 9099115e45d0..f0586fd820cb 100644 --- a/tests/system/Database/Live/EscapeTest.php +++ b/tests/system/Database/Live/EscapeTest.php @@ -40,7 +40,7 @@ protected function setUp(): void */ public function testEscapeProtectsNegativeNumbers() { - $this->assertSame('-100', $this->db->escape(-100)); + $this->assertSame(-100, $this->db->escape(-100)); } public function testEscape() From 127b9cf9a373be3eaf10af27cabbde96d00bebf0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 20 Nov 2021 15:41:11 +0900 Subject: [PATCH 147/407] test: fix test method name --- tests/system/Database/Live/EscapeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/Database/Live/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index f0586fd820cb..1260badcee77 100644 --- a/tests/system/Database/Live/EscapeTest.php +++ b/tests/system/Database/Live/EscapeTest.php @@ -38,7 +38,7 @@ protected function setUp(): void * * @see https://github.com/codeigniter4/CodeIgniter4/issues/606 */ - public function testEscapeProtectsNegativeNumbers() + public function testDoesNotEscapeNegativeNumbers() { $this->assertSame(-100, $this->db->escape(-100)); } From 955100eb01c99823d24e1a3e78641f6e338e2616 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 09:52:19 +0900 Subject: [PATCH 148/407] refactor: use ?? Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- system/HTTP/Files/UploadedFile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/HTTP/Files/UploadedFile.php b/system/HTTP/Files/UploadedFile.php index 42bb9891f90b..b9a672921b94 100644 --- a/system/HTTP/Files/UploadedFile.php +++ b/system/HTTP/Files/UploadedFile.php @@ -144,7 +144,7 @@ public function move(string $targetPath, ?string $name = null, bool $overwrite = $this->hasMoved = move_uploaded_file($this->path, $destination); } catch (Exception $e) { $error = error_get_last(); - $message = isset($error['message']) ? strip_tags($error['message']) : ''; + $message = strip_tags($error['message'] ?? ''); throw HTTPException::forMoveFailed(basename($this->path), $targetPath, $message); } From 5bf3492d74fa1ca85b7b5b3b350990915593ba56 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 09:55:24 +0900 Subject: [PATCH 149/407] test: add expectExceptionMessage() --- tests/system/HTTP/Files/FileMovingTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/system/HTTP/Files/FileMovingTest.php b/tests/system/HTTP/Files/FileMovingTest.php index c9234a82dc6b..67be3a5a310e 100644 --- a/tests/system/HTTP/Files/FileMovingTest.php +++ b/tests/system/HTTP/Files/FileMovingTest.php @@ -322,6 +322,7 @@ public function testFailedMoveBecauseOfFalseReturned() move_uploaded_file('', '', false); $this->expectException(HTTPException::class); + $this->expectExceptionMessage('move_uploaded_file() returned false'); $file->move($destination, $file->getName(), false); } From 3a7722c1fd7d1432dcc94d9a4b5a0e0e99ae4646 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 10:08:04 +0900 Subject: [PATCH 150/407] test: refactor: remove unneeded variable --- tests/system/HTTP/Files/FileMovingTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/system/HTTP/Files/FileMovingTest.php b/tests/system/HTTP/Files/FileMovingTest.php index 67be3a5a310e..90ba938de396 100644 --- a/tests/system/HTTP/Files/FileMovingTest.php +++ b/tests/system/HTTP/Files/FileMovingTest.php @@ -293,11 +293,9 @@ public function testFailedMoveBecauseOfWarning() public function testFailedMoveBecauseOfFalseReturned() { - $finalFilename = 'fileA'; - $_FILES = [ 'userfile1' => [ - 'name' => $finalFilename . '.txt', + 'name' => 'fileA.txt', 'type' => 'text/plain', 'size' => 124, 'tmp_name' => '/tmp/fileA.txt', From c0a8005a62df48841c9ffdccabbfedea39662a01 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 10:11:51 +0900 Subject: [PATCH 151/407] test: refactor: separate arrange, act, assert code --- tests/system/HTTP/Files/FileMovingTest.php | 39 +++++++++------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/tests/system/HTTP/Files/FileMovingTest.php b/tests/system/HTTP/Files/FileMovingTest.php index 90ba938de396..9eac8e51f1e7 100644 --- a/tests/system/HTTP/Files/FileMovingTest.php +++ b/tests/system/HTTP/Files/FileMovingTest.php @@ -55,8 +55,7 @@ protected function tearDown(): void public function testMove() { $finalFilename = 'fileA'; - - $_FILES = [ + $_FILES = [ 'userfile1' => [ 'name' => $finalFilename . '.txt', 'type' => 'text/plain', @@ -79,7 +78,6 @@ public function testMove() $this->assertTrue($collection->hasFile('userfile2')); $destination = $this->destination; - // Create the destination if not exists if (! is_dir($destination)) { mkdir($destination, 0777, true); @@ -97,8 +95,7 @@ public function testMove() public function testMoveOverwriting() { $finalFilename = 'file_with_delimiters_underscore'; - - $_FILES = [ + $_FILES = [ 'userfile1' => [ 'name' => $finalFilename . '.txt', 'type' => 'text/plain', @@ -129,7 +126,6 @@ public function testMoveOverwriting() $this->assertTrue($collection->hasFile('userfile3')); $destination = $this->destination; - // Create the destination if not exists if (! is_dir($destination)) { mkdir($destination, 0777, true); @@ -149,8 +145,7 @@ public function testMoveOverwriting() public function testMoved() { $finalFilename = 'fileA'; - - $_FILES = [ + $_FILES = [ 'userfile1' => [ 'name' => $finalFilename . '.txt', 'type' => 'text/plain', @@ -165,7 +160,6 @@ public function testMoved() $this->assertTrue($collection->hasFile('userfile1')); $destination = $this->destination; - // Create the destination if not exists if (! is_dir($destination)) { mkdir($destination, 0777, true); @@ -175,15 +169,16 @@ public function testMoved() $this->assertInstanceOf(UploadedFile::class, $file); $this->assertFalse($file->hasMoved()); + $file->move($destination, $file->getName(), false); + $this->assertTrue($file->hasMoved()); } public function testStore() { $finalFilename = 'fileA'; - - $_FILES = [ + $_FILES = [ 'userfile1' => [ 'name' => $finalFilename . '.txt', 'type' => 'text/plain', @@ -198,7 +193,6 @@ public function testStore() $this->assertTrue($collection->hasFile('userfile1')); $destination = $this->destination; - // Create the destination if not exists if (! is_dir($destination)) { mkdir($destination, 0777, true); @@ -207,15 +201,16 @@ public function testStore() $file = $collection->getFile('userfile1'); $this->assertInstanceOf(UploadedFile::class, $file); + $path = $file->store($destination, $file->getName()); + $this->assertSame($destination . '/fileA.txt', $path); } public function testAlreadyMoved() { $finalFilename = 'fileA'; - - $_FILES = [ + $_FILES = [ 'userfile1' => [ 'name' => $finalFilename . '.txt', 'type' => 'text/plain', @@ -230,7 +225,6 @@ public function testAlreadyMoved() $this->assertTrue($collection->hasFile('userfile1')); $destination = $this->destination; - // Create the destination if not exists if (! is_dir($destination)) { mkdir($destination, 0777, true); @@ -257,11 +251,11 @@ public function testInvalidFile() ]; $destination = $this->destination; - - $collection = new FileCollection(); - $file = $collection->getFile('userfile'); + $collection = new FileCollection(); $this->expectException(HTTPException::class); + + $file = $collection->getFile('userfile'); $file->move($destination, $file->getName(), false); } @@ -278,16 +272,16 @@ public function testFailedMoveBecauseOfWarning() ]; $destination = $this->destination; - // Create the destination and make it read only if (! is_dir($destination)) { mkdir($destination, 0400, true); } $collection = new FileCollection(); - $file = $collection->getFile('userfile'); $this->expectException(HTTPException::class); + + $file = $collection->getFile('userfile'); $file->move($destination, $file->getName(), false); } @@ -308,20 +302,17 @@ public function testFailedMoveBecauseOfFalseReturned() $this->assertTrue($collection->hasFile('userfile1')); $destination = $this->destination; - // Create the destination if not exists if (! is_dir($destination)) { mkdir($destination, 0777, true); } - - $file = $collection->getFile('userfile1'); - // Set the mock's return value to false move_uploaded_file('', '', false); $this->expectException(HTTPException::class); $this->expectExceptionMessage('move_uploaded_file() returned false'); + $file = $collection->getFile('userfile1'); $file->move($destination, $file->getName(), false); } } From ae6db974ba58d54b895847e6be4574d2686a3d86 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 10:37:18 +0900 Subject: [PATCH 152/407] docs: add about config() preferApp and Registrars --- user_guide_src/source/general/modules.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/user_guide_src/source/general/modules.rst b/user_guide_src/source/general/modules.rst index 91ec5554c955..150ddcfe3f60 100644 --- a/user_guide_src/source/general/modules.rst +++ b/user_guide_src/source/general/modules.rst @@ -191,6 +191,11 @@ with the ``new`` command:: Config files are automatically discovered whenever using the **config()** function that is always available. +.. note:: **config()** finds the file in **app/Config/** when there is a class with the same shortname, + even if you specify a full qualified class name like ``config(\Acme\Blog\Config\Blog::class)``. + +.. note:: Modules that need to override or add to known configurations in **app/Config/** should use :ref:`registrars`. + Migrations ========== From 525e2d95fa3e2991ab1cafade96822944b05caaa Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 11:17:01 +0900 Subject: [PATCH 153/407] docs: fix page links Do not use link like "`Feature Testing tools `_". --- user_guide_src/source/concepts/security.rst | 8 ++++---- user_guide_src/source/concepts/structure.rst | 2 +- user_guide_src/source/incoming/routing.rst | 10 ++++++---- user_guide_src/source/installation/upgrade_415.rst | 2 +- user_guide_src/source/libraries/curlrequest.rst | 2 ++ user_guide_src/source/testing/controllers.rst | 4 ++-- user_guide_src/source/testing/feature.rst | 2 +- user_guide_src/source/testing/overview.rst | 2 +- user_guide_src/source/testing/response.rst | 2 +- 9 files changed, 19 insertions(+), 15 deletions(-) diff --git a/user_guide_src/source/concepts/security.rst b/user_guide_src/source/concepts/security.rst index 63581c9510dd..9bca73026eba 100644 --- a/user_guide_src/source/concepts/security.rst +++ b/user_guide_src/source/concepts/security.rst @@ -34,7 +34,7 @@ OWASP recommendations CodeIgniter provisions ---------------------- -- `HTTP library <../incoming/incomingrequest.html>`_ provides for input field filtering & content metadata +- :doc:`HTTP library <../incoming/incomingrequest>` provides for input field filtering & content metadata - Form validation library ********************************************* @@ -56,7 +56,7 @@ OWASP recommendations CodeIgniter provisions ---------------------- -- `Session <../libraries/sessions.html>`_ library +- :doc:`Session <../libraries/sessions>` library - :doc:`Security ` library provides for CSRF validation - Easy to add third party authentication @@ -217,5 +217,5 @@ OWASP recommendations CodeIgniter provisions ---------------------- -- `HTTP library <../incoming/incomingrequest.html>`_ provides for ... -- `Session <../libraries/sessions.html>`_ library provides flashdata +- :doc:`HTTP library <../incoming/incomingrequest>` provides for ... +- :doc:`Session <../libraries/sessions>` library provides flashdata diff --git a/user_guide_src/source/concepts/structure.rst b/user_guide_src/source/concepts/structure.rst index 5c94b8542758..561cbb28f97d 100644 --- a/user_guide_src/source/concepts/structure.rst +++ b/user_guide_src/source/concepts/structure.rst @@ -84,4 +84,4 @@ Modifying Directory Locations If you've relocated any of the main directories, you can change the configuration settings inside **app/Config/Paths.php**. -Please read `Managing your Applications <../general/managing_apps.html>`_ +Please read :doc:`Managing your Applications <../general/managing_apps>`. diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 9778307bc4fa..5f18fb4960d8 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -228,7 +228,7 @@ extensive set of routes that all share the opening string, like when building an This would prefix the 'users' and 'blog" URIs with "admin", handling URLs like ``/admin/users`` and ``/admin/blog``. -If you need to assign options to a group, like a `namespace <#assigning-namespace>`_, do it before the callback:: +If you need to assign options to a group, like a :ref:`assigning-namespace`, do it before the callback:: $routes->group('api', ['namespace' => 'App\API\v1'], function ($routes) { $routes->resource('users'); @@ -236,7 +236,7 @@ If you need to assign options to a group, like a `namespace <#assigning-namespac This would handle a resource route to the ``App\API\v1\Users`` controller with the ``/api/users`` URI. -You can also use a specific `filter `_ for a group of routes. This will always +You can also use a specific :doc:`filter ` for a group of routes. This will always run the filter before or after the controller. This is especially handy during authentication or api logging:: $routes->group('api', ['filter' => 'api-auth'], function ($routes) { @@ -338,7 +338,7 @@ available from the command line:: Global Options ============== -All of the methods for creating a route (add, get, post, `resource `_ etc) can take an array of options that +All of the methods for creating a route (add, get, post, :doc:`resource ` etc) can take an array of options that can modify the generated routes, or further restrict them. The ``$options`` array is always the last parameter:: $routes->add('from', 'to', $options); @@ -363,7 +363,7 @@ The value for the filter can be a string or an array of strings: * matching the aliases defined in **app/Config/Filters.php**. * filter classnames -See `Controller filters `_ for more information on setting up filters. +See :doc:`Controller filters ` for more information on setting up filters. .. Warning:: If you set filters to routes in **app/Config/Routes.php** (not in **app/Config/Filters.php**), it is recommended to disable auto-routing. @@ -396,6 +396,8 @@ You specify an array for the filter value:: $routes->add('admin',' AdminController::index', ['filter' => ['admin-auth', \App\Filters\SomeFilter::class]]); +.. _assigning-namespace: + Assigning Namespace ------------------- diff --git a/user_guide_src/source/installation/upgrade_415.rst b/user_guide_src/source/installation/upgrade_415.rst index 3f7c7226ea0b..c7b885efa40a 100644 --- a/user_guide_src/source/installation/upgrade_415.rst +++ b/user_guide_src/source/installation/upgrade_415.rst @@ -59,7 +59,7 @@ CURLRequest header change In the previous version, if you didn't provide your own headers, ``CURLRequest`` would send the request-headers from the browser. The bug was fixed. If your requests depend on the headers, your requests might fail after upgrading. In this case, add the necessary headers manually. -See `CURLRequest Class <../libraries/curlrequest.html#headers>`_ for how to add. +See :ref:`CURLRequest Class ` for how to add. Query Builder changes --------------------- diff --git a/user_guide_src/source/libraries/curlrequest.rst b/user_guide_src/source/libraries/curlrequest.rst index 0074523d79fd..e7163133d5bc 100644 --- a/user_guide_src/source/libraries/curlrequest.rst +++ b/user_guide_src/source/libraries/curlrequest.rst @@ -299,6 +299,8 @@ if it's not already set:: Use ``form_params`` for ``application/x-www-form-urlencoded`` request, and ``multipart`` for ``multipart/form-data`` requests. +.. _curlrequest-request-options-headers: + headers ======= diff --git a/user_guide_src/source/testing/controllers.rst b/user_guide_src/source/testing/controllers.rst index 1f16cd615fc2..d5dd2d379b8b 100644 --- a/user_guide_src/source/testing/controllers.rst +++ b/user_guide_src/source/testing/controllers.rst @@ -4,7 +4,7 @@ Testing Controllers Testing your controllers is made convenient with a couple of new helper classes and traits. When testing controllers, you can execute the code within a controller, without first running through the entire application bootstrap process. -Often times, using the `Feature Testing tools `_ will be simpler, but this functionality is here in +Often times, using the :doc:`Feature Testing tools ` will be simpler, but this functionality is here in case you need it. .. note:: Because the entire framework has not been bootstrapped, there will be times when you cannot test a controller @@ -161,7 +161,7 @@ you need to set a JSON value as the body. The only parameter is a string that re Checking the Response ===================== -``ControllerTestTrait::execute()`` returns an instance of a ``TestResponse``. See `Testing Responses `_ on +``ControllerTestTrait::execute()`` returns an instance of a ``TestResponse``. See :doc:`Testing Responses ` on how to use this class to perform additional assertions and verification in your test cases. Filter Testing diff --git a/user_guide_src/source/testing/feature.rst b/user_guide_src/source/testing/feature.rst index 79d0b9d51c76..2a9eb96a348a 100644 --- a/user_guide_src/source/testing/feature.rst +++ b/user_guide_src/source/testing/feature.rst @@ -157,5 +157,5 @@ the Content-Type header for you so if you need that, you can set it with the ``w Checking the Response ===================== -``FeatureTestTrait::call()`` returns an instance of a ``TestResponse``. See `Testing Responses `_ on +``FeatureTestTrait::call()`` returns an instance of a ``TestResponse``. See :doc:`Testing Responses ` on how to use this class to perform additional assertions and verification in your test cases. diff --git a/user_guide_src/source/testing/overview.rst b/user_guide_src/source/testing/overview.rst index 0a16a07b34ac..7cfcdcb69d54 100644 --- a/user_guide_src/source/testing/overview.rst +++ b/user_guide_src/source/testing/overview.rst @@ -103,7 +103,7 @@ have the correct namespace relative to ``App``. .. note:: Namespaces are not strictly required for test classes, but they are helpful to ensure no class names collide. -When testing database results, you must use the `DatabaseTestTrait `_ in your class. +When testing database results, you must use the :doc:`DatabaseTestTrait ` in your class. Staging ------- diff --git a/user_guide_src/source/testing/response.rst b/user_guide_src/source/testing/response.rst index c5f7d9c34fbe..db709e415fff 100644 --- a/user_guide_src/source/testing/response.rst +++ b/user_guide_src/source/testing/response.rst @@ -4,7 +4,7 @@ Testing Responses The ``TestResponse`` class provides a number of helpful functions for parsing and testing responses from your test cases. Usually a ``TestResponse`` will be provided for you as a result of your -`Controller Tests `_ or `HTTP Feature Tests `_, but you can always +:doc:`Controller Tests ` or :doc:`HTTP Feature Tests `, but you can always create your own directly using any ``ResponseInterface``:: $result = new \CodeIgniter\Test\TestResponse($response); From c057adea785539ede98f7ecb2220078e132a25e2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 11:20:00 +0900 Subject: [PATCH 154/407] docs: update external URLs --- user_guide_src/source/installation/installing_manual.rst | 2 +- user_guide_src/source/testing/overview.rst | 4 ++-- user_guide_src/source/testing/response.rst | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/installation/installing_manual.rst b/user_guide_src/source/installation/installing_manual.rst index 1224e84d2830..c64f7dc5b212 100644 --- a/user_guide_src/source/installation/installing_manual.rst +++ b/user_guide_src/source/installation/installing_manual.rst @@ -10,7 +10,7 @@ will be your public-facing document root. Do not change anything inside the ``sy folder! .. note:: This is the installation technique closest to that described - for `CodeIgniter 3 `_. + for `CodeIgniter 3 `_. Installation ============ diff --git a/user_guide_src/source/testing/overview.rst b/user_guide_src/source/testing/overview.rst index 7cfcdcb69d54..4b4cdce7beed 100644 --- a/user_guide_src/source/testing/overview.rst +++ b/user_guide_src/source/testing/overview.rst @@ -216,7 +216,7 @@ Ensure that a header or cookie was actually emitted:: $this->assertHeaderEmitted("Set-Cookie: foo=bar"); Note: the test case with this should be `run as a separate process -in PHPunit `_. +in PHPunit `_. **assertHeaderNotEmitted($header, $ignoreCase = false)** @@ -231,7 +231,7 @@ Ensure that a header or cookie was not emitted:: $this->assertHeaderNotEmitted("Set-Cookie: banana"); Note: the test case with this should be `run as a separate process -in PHPunit `_. +in PHPunit `_. **assertCloseEnough($expected, $actual, $message = '', $tolerance = 1)** diff --git a/user_guide_src/source/testing/response.rst b/user_guide_src/source/testing/response.rst index db709e415fff..6c22e7e9cbdb 100644 --- a/user_guide_src/source/testing/response.rst +++ b/user_guide_src/source/testing/response.rst @@ -10,6 +10,10 @@ create your own directly using any ``ResponseInterface``:: $result = new \CodeIgniter\Test\TestResponse($response); $result->assertOK(); +.. contents:: + :local: + :depth: 2 + Testing the Response ==================== From c802bd88c5a979a04e08288cd4869614fe4b156c Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 17:20:39 +0900 Subject: [PATCH 155/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/general/modules.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/modules.rst b/user_guide_src/source/general/modules.rst index 150ddcfe3f60..c9a5607df1f2 100644 --- a/user_guide_src/source/general/modules.rst +++ b/user_guide_src/source/general/modules.rst @@ -192,7 +192,7 @@ with the ``new`` command:: Config files are automatically discovered whenever using the **config()** function that is always available. .. note:: **config()** finds the file in **app/Config/** when there is a class with the same shortname, - even if you specify a full qualified class name like ``config(\Acme\Blog\Config\Blog::class)``. + even if you specify a fully qualified class name like ``config(\Acme\Blog\Config\Blog::class)``. .. note:: Modules that need to override or add to known configurations in **app/Config/** should use :ref:`registrars`. From b367e05a3f37db4377efd5ae576e2f9e6a772256 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 21 Nov 2021 19:37:47 +0900 Subject: [PATCH 156/407] fix: unexpected array structure causes Type Error Fixes #5369 --- system/Helpers/array_helper.php | 4 ++++ tests/system/Helpers/ArrayHelperTest.php | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/system/Helpers/array_helper.php b/system/Helpers/array_helper.php index a06d4bb96c6e..423f9c266dd5 100644 --- a/system/Helpers/array_helper.php +++ b/system/Helpers/array_helper.php @@ -53,6 +53,10 @@ function _array_search_dot(array $indexes, array $array) $answer = []; foreach ($array as $value) { + if (! is_array($value)) { + return null; + } + $answer[] = _array_search_dot($indexes, $value); } diff --git a/tests/system/Helpers/ArrayHelperTest.php b/tests/system/Helpers/ArrayHelperTest.php index f6ae751e1bda..68941d670ce9 100644 --- a/tests/system/Helpers/ArrayHelperTest.php +++ b/tests/system/Helpers/ArrayHelperTest.php @@ -46,6 +46,18 @@ public function testArrayDotTooManyLevels() $this->assertSame(23, dot_array_search('foo.bar.baz', $data)); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5369 + */ + public function testArrayDotValueIsListArray() + { + $data = [ + 'arr' => [1, 2, 3], + ]; + + $this->assertNull(dot_array_search('arr.*.index', $data)); + } + public function testArrayDotEscape() { $data = [ From a2fc131e2c60605c801fb0886620361056b77e6e Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 22 Nov 2021 09:09:02 +0900 Subject: [PATCH 157/407] docs: add more explanation and link --- user_guide_src/source/concepts/factories.rst | 2 ++ user_guide_src/source/general/modules.rst | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/concepts/factories.rst b/user_guide_src/source/concepts/factories.rst index 2c5c9ea84c3d..96bf0e39a4a5 100644 --- a/user_guide_src/source/concepts/factories.rst +++ b/user_guide_src/source/concepts/factories.rst @@ -58,6 +58,8 @@ to access user records always go through that connection:: Now any time the ``UserModel`` is loaded from ``Factories`` it will in fact be returning a class instance that uses the alternate database connection. +.. _factories-options: + Factories Options ================== diff --git a/user_guide_src/source/general/modules.rst b/user_guide_src/source/general/modules.rst index c9a5607df1f2..85a1d4ae82f8 100644 --- a/user_guide_src/source/general/modules.rst +++ b/user_guide_src/source/general/modules.rst @@ -191,10 +191,12 @@ with the ``new`` command:: Config files are automatically discovered whenever using the **config()** function that is always available. +.. note:: We don't recommend you use the same short classname in modules. + Modules that need to override or add to known configurations in **app/Config/** should use :ref:`registrars`. + .. note:: **config()** finds the file in **app/Config/** when there is a class with the same shortname, even if you specify a fully qualified class name like ``config(\Acme\Blog\Config\Blog::class)``. - -.. note:: Modules that need to override or add to known configurations in **app/Config/** should use :ref:`registrars`. + This is because ``Factories``'s the default configuration. See :ref:`factories-options` for more information. Migrations ========== From 2c668d4e7552e95f43b9ab03668be8a04e06a77a Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 22 Nov 2021 09:09:52 +0900 Subject: [PATCH 158/407] docs: shorten the width of the table It is too long and difficult to see. --- user_guide_src/source/concepts/factories.rst | 22 ++++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/user_guide_src/source/concepts/factories.rst b/user_guide_src/source/concepts/factories.rst index 96bf0e39a4a5..978c6bc26fe9 100644 --- a/user_guide_src/source/concepts/factories.rst +++ b/user_guide_src/source/concepts/factories.rst @@ -67,15 +67,19 @@ The default behavior might not work for every component. For example, say your c name and its path do not align, or you need to limit instances to a certain type of class. Each component takes a set of options to direct discovery and instantiation. -========== ============== ==================================================================================================================== =================================================== -Key Type Description Default -========== ============== ==================================================================================================================== =================================================== -component string or null The name of the component (if different than the static method). This can be used to alias one component to another. ``null`` (defaults to the component name) -path string or null The relative path within the namespace/folder to look for classes. ``null`` (defaults to the component name) -instanceOf string or null A required class name to match on the returned instance. ``null`` (no filtering) -getShared boolean Whether to return a shared instance of the class or load a fresh one. ``true`` -preferApp boolean Whether a class with the same basename in the App namespace overrides other explicit class requests. ``true`` -========== ============== ==================================================================================================================== =================================================== +========== ============== ============================================================ =================================================== +Key Type Description Default +========== ============== ============================================================ =================================================== +component string or null The name of the component (if different than the static ``null`` (defaults to the component name) + method). This can be used to alias one component to another. +path string or null The relative path within the namespace/folder to look for ``null`` (defaults to the component name) + classes. +instanceOf string or null A required class name to match on the returned instance. ``null`` (no filtering) +getShared boolean Whether to return a shared instance of the class or load a ``true`` + fresh one. +preferApp boolean Whether a class with the same basename in the App namespace ``true`` + overrides other explicit class requests. +========== ============== ============================================================ =================================================== Factories Behavior ================== From cb64680cd30a6b9764e435c62682aae52eb8186a Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 22 Nov 2021 10:41:26 +0900 Subject: [PATCH 159/407] docs: replace blogview with blog_view We use snake_case view filename, e.g. welcome_message, error_404. --- user_guide_src/source/outgoing/views.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/user_guide_src/source/outgoing/views.rst b/user_guide_src/source/outgoing/views.rst index b01466ce40da..604f38731e85 100644 --- a/user_guide_src/source/outgoing/views.rst +++ b/user_guide_src/source/outgoing/views.rst @@ -19,7 +19,7 @@ Using the example controller you created in the controller page, let’s add a v Creating a View =============== -Using your text editor, create a file called ``blogview.php`` and put this in it:: +Using your text editor, create a file called ``blog_view.php`` and put this in it:: @@ -53,7 +53,7 @@ Now, open the controller file you made earlier called ``Blog.php``, and replace { public function index() { - echo view('blogview'); + echo view('blog_view'); } } @@ -109,9 +109,9 @@ to package your views together in a module-like fashion for easy re-use or distr If you have ``Blog`` directory that has a PSR-4 mapping set up in the :doc:`Autoloader ` living under the namespace ``Example\Blog``, you could retrieve view files as if they were namespaced also. Following this -example, you could load the **blogview.php** file from **Blog/Views** by prepending the namespace to the view name:: +example, you could load the **blog_view.php** file from **Blog/Views** by prepending the namespace to the view name:: - echo view('Example\Blog\Views\blogview'); + echo view('Example\Blog\Views\blog_view'); Caching Views ============= @@ -140,7 +140,7 @@ Here's an example:: 'message' => 'My Message', ]; - echo view('blogview', $data); + echo view('blog_view', $data); Let's try it with your controller file. Open it and add this code:: @@ -155,7 +155,7 @@ Let's try it with your controller file. Open it and add this code:: $data['title'] = "My Real Title"; $data['heading'] = "My Real Heading"; - echo view('blogview', $data); + echo view('blog_view', $data); } } @@ -184,7 +184,7 @@ into the `$option` array in the third parameter. 'message' => 'My Message', ]; - echo view('blogview', $data, ['saveData' => true]); + echo view('blog_view', $data, ['saveData' => true]); Additionally, if you would like the default functionality of the view function to be that it does save the data between calls, you can set ``$saveData`` to **true** in **app/Config/Views.php**. @@ -212,7 +212,7 @@ Here’s a simple example. Add this to your controller:: 'heading' => 'My Real Heading', ]; - echo view('blogview', $data); + echo view('blog_view', $data); } } From 7d15138f7d79eb21898ddd7b3ec06591d82b1c5c Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 22 Nov 2021 10:50:48 +0900 Subject: [PATCH 160/407] docs: fix namespace directory explanation --- user_guide_src/source/outgoing/views.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/outgoing/views.rst b/user_guide_src/source/outgoing/views.rst index 604f38731e85..533e3c9bead5 100644 --- a/user_guide_src/source/outgoing/views.rst +++ b/user_guide_src/source/outgoing/views.rst @@ -107,9 +107,9 @@ You can store views under a **View** directory that is namespaced, and load that PHP does not support loading non-class files from a namespace, CodeIgniter provides this feature to make it possible to package your views together in a module-like fashion for easy re-use or distribution. -If you have ``Blog`` directory that has a PSR-4 mapping set up in the :doc:`Autoloader ` living +If you have ``example/blog`` directory that has a PSR-4 mapping set up in the :doc:`Autoloader ` living under the namespace ``Example\Blog``, you could retrieve view files as if they were namespaced also. Following this -example, you could load the **blog_view.php** file from **Blog/Views** by prepending the namespace to the view name:: +example, you could load the **blog_view.php** file from **example/blog/Views** by prepending the namespace to the view name:: echo view('Example\Blog\Views\blog_view'); From 29047e92d7dcb02300ac258e039470ffe98e48d2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 18 Nov 2021 16:58:51 +0900 Subject: [PATCH 161/407] chore: add script to add "Edit this page" button in User Guide --- user_guide_src/add-edit-this-page | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100755 user_guide_src/add-edit-this-page diff --git a/user_guide_src/add-edit-this-page b/user_guide_src/add-edit-this-page new file mode 100755 index 000000000000..cb036524369d --- /dev/null +++ b/user_guide_src/add-edit-this-page @@ -0,0 +1,62 @@ +#!/usr/bin/env php +' . PHP_EOL; + echo ' e.g: ' . $argv[0] . ' user_guide_src/build/html/' . PHP_EOL; + + exit(1); +} + +$dir = realpath($argv[1]); + +if ($dir === false || ! is_dir($dir)) { + throw new RuntimeException('Cannot find directory: ' . $dir); +} + +$iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator( + $dir, + FilesystemIterator::CURRENT_AS_FILEINFO | + FilesystemIterator::KEY_AS_PATHNAME | + FilesystemIterator::SKIP_DOTS + ) +); + +$files = new RegexIterator( + $iterator, + '/\A.+\.html\z/', + RecursiveRegexIterator::MATCH +); + +foreach ($files as $filePath => $fileInfo) { + echo 'processing... ' . PHP_EOL; + + $uriPath = str_replace('.html', '.rst', str_replace($dir, '', $filePath)); + $gitHubLink = 'Edit this page'; + + $content = file_get_contents($filePath); + + $pattern = '!">Edit this page!u'; + if (preg_match($pattern, $content) === 1) { + // Move the cursor up 1 line + echo "\033[1A"; + echo 'skip: ' . $filePath . PHP_EOL; + + continue; + } + + $pattern = '/
/u'; + $content = preg_replace( + $pattern, + $gitHubLink . PHP_EOL . '
', + $content + ); + + file_put_contents($filePath, $content, LOCK_EX); + + // Move the cursor up 1 line + echo "\033[1A"; + echo 'done: ' . $filePath . PHP_EOL; +} From 414ca7718ac0525de86095a4fed8d0f143b40806 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 21 Oct 2021 14:23:49 +0900 Subject: [PATCH 162/407] feat: add controller filter to check invalid chars in user input --- system/Filters/InvalidChars.php | 120 ++++++++++++++++ tests/system/Filters/InvalidCharsTest.php | 158 ++++++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 system/Filters/InvalidChars.php create mode 100644 tests/system/Filters/InvalidCharsTest.php diff --git a/system/Filters/InvalidChars.php b/system/Filters/InvalidChars.php new file mode 100644 index 000000000000..34368b0c5380 --- /dev/null +++ b/system/Filters/InvalidChars.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Filters; + +use CodeIgniter\HTTP\RequestInterface; +use CodeIgniter\HTTP\ResponseInterface; +use RuntimeException; + +/** + * InvalidChars filter. + * + * Check if user input data ($_GET, $_POST, $_COOKIE, php://input) do not contain + * invalid characters: + * - invalid UTF-8 characters + * - control characters except line break and tab code + */ +class InvalidChars implements FilterInterface +{ + /** + * Data source + * + * @var string + */ + protected $source; + + /** + * Check invalid characters. + * + * @param array|null $arguments + * + * @return void + */ + public function before(RequestInterface $request, $arguments = null) + { + if ($request->isCLI()) { + return; + } + + $data = [ + 'get' => $request->getGet(), + 'post' => $request->getPost(), + 'cookie' => $request->getCookie(), + 'rawInput' => $request->getRawInput(), + ]; + + foreach ($data as $source => $values) { + $this->source = $source; + $this->checkEncoding($values); + $this->checkControl($values); + } + } + + /** + * We don't have anything to do here. + * + * @param array|null $arguments + * + * @return void + */ + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + { + } + + /** + * Check the character encoding is valid UTF-8. + * + * @param array|string $value + * + * @return array|string + */ + protected function checkEncoding($value) + { + if (is_array($value)) { + array_map([$this, 'checkEncoding'], $value); + + return $value; + } + + if (mb_check_encoding($value, 'UTF-8')) { + return $value; + } + + throw new RuntimeException( + 'Invalid UTF-8 characters in ' . $this->source . ': ' . $value + ); + } + + /** + * Check for the presence of control characters except line breaks and tabs. + * + * @param array|string $value + * + * @return array|string + */ + protected function checkControl($value) + { + if (is_array($value)) { + array_map([$this, 'checkControl'], $value); + + return $value; + } + + if (preg_match('/\A[\r\n\t[:^cntrl:]]*\z/u', $value) === 1) { + return $value; + } + + throw new RuntimeException( + 'Invalid Control characters in ' . $this->source . ': ' . $value + ); + } +} diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php new file mode 100644 index 000000000000..85048f1a0df8 --- /dev/null +++ b/tests/system/Filters/InvalidCharsTest.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Filters; + +use CodeIgniter\HTTP\CLIRequest; +use CodeIgniter\HTTP\IncomingRequest; +use CodeIgniter\HTTP\URI; +use CodeIgniter\HTTP\UserAgent; +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\Mock\MockAppConfig; +use RuntimeException; + +/** + * @internal + */ +final class InvalidCharsTest extends CIUnitTestCase +{ + /** + * @var InvalidChars + */ + private $invalidChars; + + /** + * @var IncomingRequest + */ + private $request; + + protected function setUp(): void + { + parent::setUp(); + + $_GET = []; + $_POST = []; + $_COOKIE = []; + + $this->request = $this->createRequest(); + $this->invalidChars = new InvalidChars(); + } + + private function createRequest(): IncomingRequest + { + $config = new MockAppConfig(); + $uri = new URI(); + $userAgent = new UserAgent(); + $request = $this->getMockBuilder(IncomingRequest::class) + ->setConstructorArgs([$config, $uri, null, $userAgent]) + ->onlyMethods(['isCLI']) + ->getMock(); + $request->method('isCLI')->willReturn(false); + + return $request; + } + + public function testBeforeDoNothingWhenCLIRequest() + { + $cliRequest = new CLIRequest(new MockAppConfig()); + + $ret = $this->invalidChars->before($cliRequest); + + $this->assertNull($ret); + } + + public function testBeforeValidString() + { + $_POST['val'] = [ + 'valid string', + ]; + $_COOKIE['val'] = 'valid string'; + + $ret = $this->invalidChars->before($this->request); + + $this->assertNull($ret); + } + + public function testBeforeInvalidUTF8StringCausesException() + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Invalid UTF-8 characters in post:'); + + $sjisString = mb_convert_encoding('SJISの文字列です。', 'SJIS'); + $_POST['val'] = [ + 'valid string', + $sjisString, + ]; + + $this->invalidChars->before($this->request); + } + + public function testBeforeInvalidControllCharCausesException() + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Invalid Control characters in cookie:'); + + $stringWithNullChar = "String contains null char and line break.\0\n"; + $_COOKIE['val'] = $stringWithNullChar; + + $this->invalidChars->before($this->request); + } + + /** + * @dataProvider stringWithLineBreakAndTabProvider + * + * @param string $input + */ + public function testCheckControlStringWithLineBreakAndTabReturnsTheString($input) + { + $_GET['val'] = $input; + + $ret = $this->invalidChars->before($this->request); + + $this->assertNull($ret); + } + + public function stringWithLineBreakAndTabProvider() + { + return [ + ["String contains \n line break."], + ["String contains \r line break."], + ["String contains \r\n line break."], + ["String contains \t tab."], + ["String contains \t and \r line \n break."], + ]; + } + + /** + * @dataProvider stringWithControlCharsProvider + * + * @param string $input + */ + public function testCheckControlStringWithControlCharsCausesException($input) + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Invalid Control characters in get:'); + + $_GET['val'] = $input; + + $ret = $this->invalidChars->before($this->request); + + $this->assertNull($ret); + } + + public function stringWithControlCharsProvider() + { + return [ + ["String contains null char.\0"], + ["String contains null char and line break.\0\n"], + ]; + } +} From 9a67840c43dcc97c8d3123f619fbbe6450d3d752 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 21 Oct 2021 17:06:51 +0900 Subject: [PATCH 163/407] test: clear super globals after testing The following test failed. It depends global state. 1) CodeIgniter\HTTP\ResponseTest::testSetLink Failed asserting that two strings are identical. --- tests/system/Filters/InvalidCharsTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php index 85048f1a0df8..3346b1adad18 100644 --- a/tests/system/Filters/InvalidCharsTest.php +++ b/tests/system/Filters/InvalidCharsTest.php @@ -46,6 +46,15 @@ protected function setUp(): void $this->invalidChars = new InvalidChars(); } + protected function tearDown(): void + { + parent::tearDown(); + + $_GET = []; + $_POST = []; + $_COOKIE = []; + } + private function createRequest(): IncomingRequest { $config = new MockAppConfig(); From 1e3a30cb6709634e4147a16f9326574b53df3a79 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 5 Nov 2021 11:37:39 +0900 Subject: [PATCH 164/407] feat: add SecurityException static consructors --- system/Filters/InvalidChars.php | 10 +++------- system/Security/Exceptions/SecurityException.php | 16 ++++++++++++++++ tests/system/Filters/InvalidCharsTest.php | 8 ++++---- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/system/Filters/InvalidChars.php b/system/Filters/InvalidChars.php index 34368b0c5380..ab5a2fef9ca4 100644 --- a/system/Filters/InvalidChars.php +++ b/system/Filters/InvalidChars.php @@ -13,7 +13,7 @@ use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use RuntimeException; +use CodeIgniter\Security\Exceptions\SecurityException; /** * InvalidChars filter. @@ -89,9 +89,7 @@ protected function checkEncoding($value) return $value; } - throw new RuntimeException( - 'Invalid UTF-8 characters in ' . $this->source . ': ' . $value - ); + throw SecurityException::forInvalidUTF8Chars($this->source, $value); } /** @@ -113,8 +111,6 @@ protected function checkControl($value) return $value; } - throw new RuntimeException( - 'Invalid Control characters in ' . $this->source . ': ' . $value - ); + throw SecurityException::forInvalidControlChars($this->source, $value); } } diff --git a/system/Security/Exceptions/SecurityException.php b/system/Security/Exceptions/SecurityException.php index 254f3ec345f5..ed118d95d5dd 100644 --- a/system/Security/Exceptions/SecurityException.php +++ b/system/Security/Exceptions/SecurityException.php @@ -20,6 +20,22 @@ public static function forDisallowedAction() return new static(lang('Security.disallowedAction'), 403); } + public static function forInvalidUTF8Chars(string $source, string $string) + { + return new static( + 'Invalid UTF-8 characters in ' . $source . ': ' . $string, + 400 + ); + } + + public static function forInvalidControlChars(string $source, string $string) + { + return new static( + 'Invalid Control characters in ' . $source . ': ' . $string, + 400 + ); + } + /** * @deprecated Use `CookieException::forInvalidSameSite()` instead. * diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php index 3346b1adad18..85fa6b91425a 100644 --- a/tests/system/Filters/InvalidCharsTest.php +++ b/tests/system/Filters/InvalidCharsTest.php @@ -15,9 +15,9 @@ use CodeIgniter\HTTP\IncomingRequest; use CodeIgniter\HTTP\URI; use CodeIgniter\HTTP\UserAgent; +use CodeIgniter\Security\Exceptions\SecurityException; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\Mock\MockAppConfig; -use RuntimeException; /** * @internal @@ -92,7 +92,7 @@ public function testBeforeValidString() public function testBeforeInvalidUTF8StringCausesException() { - $this->expectException(RuntimeException::class); + $this->expectException(SecurityException::class); $this->expectExceptionMessage('Invalid UTF-8 characters in post:'); $sjisString = mb_convert_encoding('SJISの文字列です。', 'SJIS'); @@ -106,7 +106,7 @@ public function testBeforeInvalidUTF8StringCausesException() public function testBeforeInvalidControllCharCausesException() { - $this->expectException(RuntimeException::class); + $this->expectException(SecurityException::class); $this->expectExceptionMessage('Invalid Control characters in cookie:'); $stringWithNullChar = "String contains null char and line break.\0\n"; @@ -147,7 +147,7 @@ public function stringWithLineBreakAndTabProvider() */ public function testCheckControlStringWithControlCharsCausesException($input) { - $this->expectException(RuntimeException::class); + $this->expectException(SecurityException::class); $this->expectExceptionMessage('Invalid Control characters in get:'); $_GET['val'] = $input; From 991f9537bf41d58a232e1eb749b9d4dd904007a4 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 5 Nov 2021 11:39:01 +0900 Subject: [PATCH 165/407] test: fix test code --- tests/system/Filters/InvalidCharsTest.php | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php index 85fa6b91425a..95725de07323 100644 --- a/tests/system/Filters/InvalidCharsTest.php +++ b/tests/system/Filters/InvalidCharsTest.php @@ -69,15 +69,19 @@ private function createRequest(): IncomingRequest return $request; } + /** + * @doesNotPerformAssertions + */ public function testBeforeDoNothingWhenCLIRequest() { $cliRequest = new CLIRequest(new MockAppConfig()); - $ret = $this->invalidChars->before($cliRequest); - - $this->assertNull($ret); + $this->invalidChars->before($cliRequest); } + /** + * @doesNotPerformAssertions + */ public function testBeforeValidString() { $_POST['val'] = [ @@ -85,9 +89,7 @@ public function testBeforeValidString() ]; $_COOKIE['val'] = 'valid string'; - $ret = $this->invalidChars->before($this->request); - - $this->assertNull($ret); + $this->invalidChars->before($this->request); } public function testBeforeInvalidUTF8StringCausesException() @@ -104,7 +106,7 @@ public function testBeforeInvalidUTF8StringCausesException() $this->invalidChars->before($this->request); } - public function testBeforeInvalidControllCharCausesException() + public function testBeforeInvalidControlCharCausesException() { $this->expectException(SecurityException::class); $this->expectExceptionMessage('Invalid Control characters in cookie:'); @@ -116,6 +118,8 @@ public function testBeforeInvalidControllCharCausesException() } /** + * @doesNotPerformAssertions + * * @dataProvider stringWithLineBreakAndTabProvider * * @param string $input @@ -124,9 +128,7 @@ public function testCheckControlStringWithLineBreakAndTabReturnsTheString($input { $_GET['val'] = $input; - $ret = $this->invalidChars->before($this->request); - - $this->assertNull($ret); + $this->invalidChars->before($this->request); } public function stringWithLineBreakAndTabProvider() @@ -152,9 +154,7 @@ public function testCheckControlStringWithControlCharsCausesException($input) $_GET['val'] = $input; - $ret = $this->invalidChars->before($this->request); - - $this->assertNull($ret); + $this->invalidChars->before($this->request); } public function stringWithControlCharsProvider() From 871e4996da7c57900df021f5e4a20fe56b818308 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 22 Nov 2021 11:32:22 +0900 Subject: [PATCH 166/407] config: add invalidchars to Filter.php as comment --- app/Config/Filters.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/Config/Filters.php b/app/Config/Filters.php index df90270a6480..02aaec533c17 100644 --- a/app/Config/Filters.php +++ b/app/Config/Filters.php @@ -6,6 +6,7 @@ use CodeIgniter\Filters\CSRF; use CodeIgniter\Filters\DebugToolbar; use CodeIgniter\Filters\Honeypot; +use CodeIgniter\Filters\InvalidChars; class Filters extends BaseConfig { @@ -16,9 +17,10 @@ class Filters extends BaseConfig * @var array */ public $aliases = [ - 'csrf' => CSRF::class, - 'toolbar' => DebugToolbar::class, - 'honeypot' => Honeypot::class, + 'csrf' => CSRF::class, + 'toolbar' => DebugToolbar::class, + 'honeypot' => Honeypot::class, + 'invalidchars' => InvalidChars::class, ]; /** @@ -31,6 +33,7 @@ class Filters extends BaseConfig 'before' => [ // 'honeypot', // 'csrf', + // 'invalidchars', ], 'after' => [ 'toolbar', From 97be0378e2579a7e206d531f0fba1f583fabc459 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 22 Nov 2021 11:37:05 +0900 Subject: [PATCH 167/407] docs: add InvalidChars in Provided Filters --- user_guide_src/source/incoming/filters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 259bb496e0b7..334edf188fee 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -193,6 +193,6 @@ In this example, the array ``['dual', 'noreturn']`` will be passed in ``$argumen Provided Filters **************** -Three filters are bundled with CodeIgniter4: ``Honeypot``, ``CSRF``, and ``DebugToolbar``. +These filters are bundled with CodeIgniter4: ``Honeypot``, ``CSRF``, ``DebugToolbar`` and ``InvalidChars``. .. note:: The filters are executed in the declared order that is defined in the config file, but there is one exception to this and it concerns the ``DebugToolbar``, which is always executed last. This is because ``DebugToolbar`` should be able to register everything that happens in other filters. From fb9f6ec24f99ff8f30e6aa27ac9433f7b1fbe90f Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 22 Nov 2021 11:38:38 +0900 Subject: [PATCH 168/407] refactor: add property for control code regex Users could override the property. --- system/Filters/InvalidChars.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/Filters/InvalidChars.php b/system/Filters/InvalidChars.php index ab5a2fef9ca4..4b1d8f7f9b6b 100644 --- a/system/Filters/InvalidChars.php +++ b/system/Filters/InvalidChars.php @@ -32,6 +32,13 @@ class InvalidChars implements FilterInterface */ protected $source; + /** + * Regular expressions for valid control codes + * + * @var string + */ + protected $controlCodeRegex = '/\A[\r\n\t[:^cntrl:]]*\z/u'; + /** * Check invalid characters. * @@ -107,7 +114,7 @@ protected function checkControl($value) return $value; } - if (preg_match('/\A[\r\n\t[:^cntrl:]]*\z/u', $value) === 1) { + if (preg_match($this->controlCodeRegex, $value) === 1) { return $value; } From 867322868e08e671d74c349eae7a8d30a2b638d4 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sun, 21 Nov 2021 18:32:55 +0800 Subject: [PATCH 169/407] Fix deprecated usage of `null` on `string` params of internal functions --- app/Config/Mimes.php | 2 +- system/CLI/CLI.php | 8 ++-- system/Database/BaseUtils.php | 4 +- system/Database/Forge.php | 2 +- system/Database/Postgre/Connection.php | 7 +++- system/Filters/Filters.php | 7 +--- system/HTTP/CLIRequest.php | 8 ++-- system/HTTP/CURLRequest.php | 2 +- system/HTTP/ResponseTrait.php | 2 +- system/I18n/Time.php | 18 ++++---- system/Security/Security.php | 7 ++-- system/Validation/FormatRules.php | 56 ++++++++++++------------- system/Validation/Rules.php | 58 ++++++-------------------- system/Validation/Validation.php | 20 +++------ tests/system/I18n/TimeTest.php | 3 +- 15 files changed, 82 insertions(+), 122 deletions(-) diff --git a/app/Config/Mimes.php b/app/Config/Mimes.php index 973fb3984901..786bc6a1e5c7 100644 --- a/app/Config/Mimes.php +++ b/app/Config/Mimes.php @@ -509,7 +509,7 @@ public static function guessExtensionFromType(string $type, ?string $proposedExt { $type = trim(strtolower($type), '. '); - $proposedExtension = trim(strtolower($proposedExtension)); + $proposedExtension = trim(strtolower($proposedExtension ?? '')); if ($proposedExtension !== '') { if (array_key_exists($proposedExtension, static::$mimes) && in_array($type, is_string(static::$mimes[$proposedExtension]) ? [static::$mimes[$proposedExtension]] : static::$mimes[$proposedExtension], true)) { diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index ea1e1ad85611..347a894f7578 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -865,10 +865,12 @@ public static function getOptionString(bool $useLongOpts = false, bool $trim = f $out .= "-{$name} "; } - // If there's a space, we need to group - // so it will pass correctly. + if ($value === null) { + continue; + } + if (mb_strpos($value, ' ') !== false) { - $out .= '"' . $value . '" '; + $out .= "\"{$value}\" "; } elseif ($value !== null) { $out .= "{$value} "; } diff --git a/system/Database/BaseUtils.php b/system/Database/BaseUtils.php index 5af2b54dbad7..7848ae75ecf0 100644 --- a/system/Database/BaseUtils.php +++ b/system/Database/BaseUtils.php @@ -200,7 +200,7 @@ public function repairTable(string $tableName) public function getCSVFromResult(ResultInterface $query, string $delim = ',', string $newline = "\n", string $enclosure = '"') { $out = ''; - // First generate the headings from the table column names + foreach ($query->getFieldNames() as $name) { $out .= $enclosure . str_replace($enclosure, $enclosure . $enclosure, $name) . $enclosure . $delim; } @@ -212,7 +212,7 @@ public function getCSVFromResult(ResultInterface $query, string $delim = ',', st $line = []; foreach ($row as $item) { - $line[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $item) . $enclosure; + $line[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $item ?? '') . $enclosure; } $out .= implode($delim, $line) . $newline; diff --git a/system/Database/Forge.php b/system/Database/Forge.php index 8e0b7e43c7f3..d07675401df8 100644 --- a/system/Database/Forge.php +++ b/system/Database/Forge.php @@ -462,7 +462,7 @@ public function dropKey(string $table, string $keyName) public function dropForeignKey(string $table, string $foreignName) { $sql = sprintf( - $this->dropConstraintStr, + (string) $this->dropConstraintStr, $this->db->escapeIdentifiers($this->db->DBPrefix . $table), $this->db->escapeIdentifiers($this->db->DBPrefix . $foreignName) ); diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index a768e0ecf432..d39587821036 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -433,8 +433,11 @@ protected function buildDSN() $this->DSN = "host={$this->hostname} "; } - if (! empty($this->port) && ctype_digit($this->port)) { - $this->DSN .= "port={$this->port} "; + // ctype_digit only accepts strings + $port = (string) $this->port; + + if ($port !== '' && ctype_digit($port)) { + $this->DSN .= "port={$port} "; } if ($this->username !== '') { diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index faa1df358cb4..edeb8b0571c5 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -397,13 +397,10 @@ protected function processGlobals(?string $uri = null) return; } - $uri = strtolower(trim($uri, '/ ')); + $uri = strtolower(trim($uri ?? '', '/ ')); // Add any global filters, unless they are excluded for this URI - $sets = [ - 'before', - 'after', - ]; + $sets = ['before', 'after']; foreach ($sets as $set) { if (isset($this->config->globals[$set])) { diff --git a/system/HTTP/CLIRequest.php b/system/HTTP/CLIRequest.php index b10d41884733..11bf598fd36c 100644 --- a/system/HTTP/CLIRequest.php +++ b/system/HTTP/CLIRequest.php @@ -139,11 +139,13 @@ public function getOptionString(bool $useLongOpts = false): string $out .= "-{$name} "; } - // If there's a space, we need to group - // so it will pass correctly. + if ($value === null) { + continue; + } + if (mb_strpos($value, ' ') !== false) { $out .= '"' . $value . '" '; - } elseif ($value !== null) { + } else { $out .= "{$value} "; } } diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index fffe57258a54..9a66e632783b 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -424,7 +424,7 @@ protected function applyMethod(string $method, array $curlOptions): array $this->method = $method; $curlOptions[CURLOPT_CUSTOMREQUEST] = $method; - $size = strlen($this->body); + $size = strlen($this->body ?? ''); // Have content? if ($size > 0) { diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 2b1205a5d47a..7ec5f1e69e6b 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -435,7 +435,7 @@ public function send() if ($this->CSPEnabled === true) { $this->CSP->finalize($this); } else { - $this->body = str_replace(['{csp-style-nonce}', '{csp-script-nonce}'], '', $this->body); + $this->body = str_replace(['{csp-style-nonce}', '{csp-script-nonce}'], '', $this->body ?? ''); } $this->sendHeaders(); diff --git a/system/I18n/Time.php b/system/I18n/Time.php index 919a5a391534..ca8ffc3dc72e 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -75,25 +75,23 @@ class Time extends DateTime */ public function __construct(?string $time = null, $timezone = null, ?string $locale = null) { - // If no locale was provided, grab it from Locale (set by IncomingRequest for web requests) - $this->locale = ! empty($locale) ? $locale : Locale::getDefault(); + $this->locale = $locale ?: Locale::getDefault(); - // If a test instance has been provided, use it instead. - if ($time === null && static::$testNow instanceof self) { - if (empty($timezone)) { - $timezone = static::$testNow->getTimezone(); - } + $time = $time ?? ''; - $time = static::$testNow->toDateTimeString(); + // If a test instance has been provided, use it instead. + if ($time === '' && static::$testNow instanceof self) { + $timezone = $timezone ?: static::$testNow->getTimezone(); + $time = (string) static::$testNow->toDateTimeString(); } - $timezone = ! empty($timezone) ? $timezone : date_default_timezone_get(); + $timezone = $timezone ?: date_default_timezone_get(); $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone); // If the time string was a relative string (i.e. 'next Tuesday') // then we need to adjust the time going in so that we have a current // timezone to work with. - if (! empty($time) && (is_string($time) && static::hasRelativeKeywords($time))) { + if ($time !== '' && static::hasRelativeKeywords($time)) { $instance = new DateTime('now', $this->timezone); $instance->modify($time); $time = $instance->format('Y-m-d H:i:s'); diff --git a/system/Security/Security.php b/system/Security/Security.php index fc8c1ac334c8..35e889a85d69 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -288,7 +288,7 @@ public function verify(RequestInterface $request) throw SecurityException::forDisallowedAction(); } - $json = json_decode($request->getBody()); + $json = json_decode($request->getBody() ?? ''); if (isset($_POST[$this->tokenName])) { // We kill this since we're done and we don't want to pollute the POST array. @@ -323,9 +323,10 @@ private function getPostedToken(RequestInterface $request): ?string if ($request->hasHeader($this->headerName) && ! empty($request->header($this->headerName)->getValue())) { $tokenName = $request->header($this->headerName)->getValue(); } else { - $json = json_decode($request->getBody()); + $body = (string) $request->getBody(); + $json = json_decode($body); - if (! empty($request->getBody()) && ! empty($json) && json_last_error() === JSON_ERROR_NONE) { + if ($body !== '' && ! empty($json) && json_last_error() === JSON_ERROR_NONE) { $tokenName = $json->{$this->tokenName} ?? null; } else { $tokenName = null; diff --git a/system/Validation/FormatRules.php b/system/Validation/FormatRules.php index 2167e28cba79..e28f6d6af13d 100644 --- a/system/Validation/FormatRules.php +++ b/system/Validation/FormatRules.php @@ -23,7 +23,7 @@ class FormatRules */ public function alpha(?string $str = null): bool { - return ctype_alpha($str); + return ctype_alpha($str ?? ''); } /** @@ -74,7 +74,7 @@ public function alpha_numeric_punct($str) */ public function alpha_numeric(?string $str = null): bool { - return ctype_alnum($str); + return ctype_alnum($str ?? ''); } /** @@ -83,7 +83,7 @@ public function alpha_numeric(?string $str = null): bool public function alpha_numeric_space(?string $str = null): bool { // @see https://regex101.com/r/0AZDME/1 - return (bool) preg_match('/\A[A-Z0-9 ]+\z/i', $str); + return (bool) preg_match('/\A[A-Z0-9 ]+\z/i', $str ?? ''); } /** @@ -105,7 +105,7 @@ public function string($str = null): bool public function decimal(?string $str = null): bool { // @see https://regex101.com/r/HULifl/2/ - return (bool) preg_match('/\A[-+]?\d{0,}\.?\d+\z/', $str); + return (bool) preg_match('/\A[-+]?\d{0,}\.?\d+\z/', $str ?? ''); } /** @@ -113,7 +113,7 @@ public function decimal(?string $str = null): bool */ public function hex(?string $str = null): bool { - return ctype_xdigit($str); + return ctype_xdigit($str ?? ''); } /** @@ -121,7 +121,7 @@ public function hex(?string $str = null): bool */ public function integer(?string $str = null): bool { - return (bool) preg_match('/\A[\-+]?\d+\z/', $str); + return (bool) preg_match('/\A[\-+]?\d+\z/', $str ?? ''); } /** @@ -129,7 +129,7 @@ public function integer(?string $str = null): bool */ public function is_natural(?string $str = null): bool { - return ctype_digit($str); + return ctype_digit($str ?? ''); } /** @@ -137,7 +137,7 @@ public function is_natural(?string $str = null): bool */ public function is_natural_no_zero(?string $str = null): bool { - return $str !== '0' && ctype_digit($str); + return $str !== '0' && ctype_digit($str ?? ''); } /** @@ -146,7 +146,7 @@ public function is_natural_no_zero(?string $str = null): bool public function numeric(?string $str = null): bool { // @see https://regex101.com/r/bb9wtr/2 - return (bool) preg_match('/\A[\-+]?\d*\.?\d+\z/', $str); + return (bool) preg_match('/\A[\-+]?\d*\.?\d+\z/', $str ?? ''); } /** @@ -158,7 +158,7 @@ public function regex_match(?string $str, string $pattern): bool $pattern = "/{$pattern}/"; } - return (bool) preg_match($pattern, $str); + return (bool) preg_match($pattern, $str ?? ''); } /** @@ -171,7 +171,7 @@ public function regex_match(?string $str, string $pattern): bool */ public function timezone(?string $str = null): bool { - return in_array($str, timezone_identifiers_list(), true); + return in_array($str ?? '', timezone_identifiers_list(), true); } /** @@ -184,6 +184,10 @@ public function timezone(?string $str = null): bool */ public function valid_base64(?string $str = null): bool { + if ($str === null) { + return false; + } + return base64_encode(base64_decode($str, true)) === $str; } @@ -194,7 +198,7 @@ public function valid_base64(?string $str = null): bool */ public function valid_json(?string $str = null): bool { - json_decode($str); + json_decode($str ?? ''); return json_last_error() === JSON_ERROR_NONE; } @@ -207,7 +211,7 @@ public function valid_json(?string $str = null): bool public function valid_email(?string $str = null): bool { // @see https://regex101.com/r/wlJG1t/1/ - if (function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46') && preg_match('#\A([^@]+)@(.+)\z#', $str, $matches)) { + if (function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46') && preg_match('#\A([^@]+)@(.+)\z#', $str ?? '', $matches)) { $str = $matches[1] . '@' . idn_to_ascii($matches[2], 0, INTL_IDNA_VARIANT_UTS46); } @@ -224,8 +228,9 @@ public function valid_email(?string $str = null): bool */ public function valid_emails(?string $str = null): bool { - foreach (explode(',', $str) as $email) { + foreach (explode(',', $str ?? '') as $email) { $email = trim($email); + if ($email === '') { return false; } @@ -241,8 +246,7 @@ public function valid_emails(?string $str = null): bool /** * Validate an IP address (human readable format or binary string - inet_pton) * - * @param string $ip IP Address - * @param string $which IP protocol: 'ipv4' or 'ipv6' + * @param string|null $which IP protocol: 'ipv4' or 'ipv6' */ public function valid_ip(?string $ip = null, ?string $which = null): bool { @@ -250,7 +254,7 @@ public function valid_ip(?string $ip = null, ?string $which = null): bool return false; } - switch (strtolower($which)) { + switch (strtolower($which ?? '')) { case 'ipv4': $which = FILTER_FLAG_IPV4; break; @@ -260,11 +264,11 @@ public function valid_ip(?string $ip = null, ?string $which = null): bool break; default: - $which = null; - break; + $which = 0; } - return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which) || (! ctype_print($ip) && (bool) filter_var(inet_ntop($ip), FILTER_VALIDATE_IP, $which)); + return filter_var($ip, FILTER_VALIDATE_IP, $which) !== false + || (! ctype_print($ip) && filter_var(inet_ntop($ip), FILTER_VALIDATE_IP, $which) !== false); } /** @@ -272,8 +276,6 @@ public function valid_ip(?string $ip = null, ?string $which = null): bool * * Warning: this rule will pass basic strings like * "banana"; use valid_url_strict for a stricter rule. - * - * @param string $str */ public function valid_url(?string $str = null): bool { @@ -317,18 +319,16 @@ public function valid_url_strict(?string $str = null, ?string $validSchemes = nu /** * Checks for a valid date and matches a given date format - * - * @param string $str - * @param string $format */ public function valid_date(?string $str = null, ?string $format = null): bool { if (empty($format)) { - return (bool) strtotime($str); + return strtotime($str) !== false; } - $date = DateTime::createFromFormat($format, $str); + $date = DateTime::createFromFormat($format, $str); + $errors = DateTime::getLastErrors(); - return (bool) $date && DateTime::getLastErrors()['warning_count'] === 0 && DateTime::getLastErrors()['error_count'] === 0; + return $date !== false && $errors !== false && $errors['warning_count'] === 0 && $errors['error_count'] === 0; } } diff --git a/system/Validation/Rules.php b/system/Validation/Rules.php index 20f558e52be2..367915ebae35 100644 --- a/system/Validation/Rules.php +++ b/system/Validation/Rules.php @@ -22,8 +22,7 @@ class Rules /** * The value does not match another field in $data. * - * @param string $str - * @param array $data Other field/value pairs + * @param array $data Other field/value pairs */ public function differs(?string $str, string $field, array $data): bool { @@ -36,8 +35,6 @@ public function differs(?string $str, string $field, array $data): bool /** * Equals the static value provided. - * - * @param string $str */ public function equals(?string $str, string $val): bool { @@ -47,15 +44,13 @@ public function equals(?string $str, string $val): bool /** * Returns true if $str is $val characters long. * $val = "5" (one) | "5,8,12" (multiple values) - * - * @param string $str */ public function exact_length(?string $str, string $val): bool { $val = explode(',', $val); foreach ($val as $tmp) { - if (is_numeric($tmp) && (int) $tmp === mb_strlen($str)) { + if (is_numeric($tmp) && (int) $tmp === mb_strlen($str ?? '')) { return true; } } @@ -65,8 +60,6 @@ public function exact_length(?string $str, string $val): bool /** * Greater than - * - * @param string $str */ public function greater_than(?string $str, string $min): bool { @@ -75,8 +68,6 @@ public function greater_than(?string $str, string $min): bool /** * Equal to or Greater than - * - * @param string $str */ public function greater_than_equal_to(?string $str, string $min): bool { @@ -91,8 +82,6 @@ public function greater_than_equal_to(?string $str, string $min): bool * Example: * is_not_unique[table.field,where_field,where_value] * is_not_unique[menu.id,active,1] - * - * @param string $str */ public function is_not_unique(?string $str, string $field, array $data): bool { @@ -102,9 +91,8 @@ public function is_not_unique(?string $str, string $field, array $data): bool // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); - $db = Database::connect($data['DBGroup'] ?? null); - - $row = $db->table($table) + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) ->select('1') ->where($field, $str) ->limit(1); @@ -118,8 +106,6 @@ public function is_not_unique(?string $str, string $field, array $data): bool /** * Value should be within an array of values - * - * @param string $value */ public function in_list(?string $value, string $list): bool { @@ -136,20 +122,15 @@ public function in_list(?string $value, string $list): bool * Example: * is_unique[table.field,ignore_field,ignore_value] * is_unique[users.email,id,5] - * - * @param string $str */ public function is_unique(?string $str, string $field, array $data): bool { - // Grab any data for exclusion of a single row. [$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null); - // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); - $db = Database::connect($data['DBGroup'] ?? null); - - $row = $db->table($table) + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) ->select('1') ->where($field, $str) ->limit(1); @@ -163,8 +144,6 @@ public function is_unique(?string $str, string $field, array $data): bool /** * Less than - * - * @param string $str */ public function less_than(?string $str, string $max): bool { @@ -173,8 +152,6 @@ public function less_than(?string $str, string $max): bool /** * Equal to or Less than - * - * @param string $str */ public function less_than_equal_to(?string $str, string $max): bool { @@ -184,8 +161,7 @@ public function less_than_equal_to(?string $str, string $max): bool /** * Matches the value of another field in $data. * - * @param string $str - * @param array $data Other field/value pairs + * @param array $data Other field/value pairs */ public function matches(?string $str, string $field, array $data): bool { @@ -198,22 +174,18 @@ public function matches(?string $str, string $field, array $data): bool /** * Returns true if $str is $val or fewer characters in length. - * - * @param string $str */ public function max_length(?string $str, string $val): bool { - return is_numeric($val) && $val >= mb_strlen($str); + return is_numeric($val) && $val >= mb_strlen($str ?? ''); } /** * Returns true if $str is at least $val length. - * - * @param string $str */ public function min_length(?string $str, string $val): bool { - return is_numeric($val) && $val <= mb_strlen($str); + return is_numeric($val) && $val <= mb_strlen($str ?? ''); } /** @@ -237,11 +209,7 @@ public function not_in_list(?string $value, string $list): bool } /** - * Required - * - * @param mixed $str Value - * - * @return bool True if valid, false if not + * @param mixed $str */ public function required($str = null): bool { @@ -270,11 +238,10 @@ public function required_with($str = null, ?string $fields = null, array $data = throw new InvalidArgumentException('You must supply the parameters: fields, data.'); } - $fields = explode(',', $fields); - // If the field is present we can safely assume that // the field is here, no matter whether the corresponding // search field is present or not. + $fields = explode(',', $fields); $present = $this->required($str ?? ''); if ($present) { @@ -311,11 +278,10 @@ public function required_without($str = null, ?string $fields = null, array $dat throw new InvalidArgumentException('You must supply the parameters: fields, data.'); } - $fields = explode(',', $fields); - // If the field is present we can safely assume that // the field is here, no matter whether the corresponding // search field is present or not. + $fields = explode(',', $fields); $present = $this->required($str ?? ''); if ($present) { diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index 8bd14817e79d..876ab3caffa0 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -215,7 +215,7 @@ protected function processRules(string $field, ?string $label, $value, $rules = } if (in_array('permit_empty', $rules, true)) { - if (! in_array('required', $rules, true) && (is_array($value) ? empty($value) : (trim($value) === ''))) { + if (! in_array('required', $rules, true) && (is_array($value) ? $value === [] : trim($value ?? '') === '')) { $passed = true; foreach ($rules as $rule) { @@ -570,13 +570,13 @@ protected function fillPlaceholders(array $rules, array $data): array continue; } - $row = strtr($row, $replacements); + $row = strtr($row ?? '', $replacements); } continue; } - $rule = strtr($rule, $replacements); + $rule = strtr($rule ?? '', $replacements); } } @@ -594,10 +594,6 @@ public function hasError(string $field): bool /** * Returns the error(s) for a specified $field (or empty string if not * set). - * - * @param string $field Field. - * - * @return string Error(s). */ public function getError(?string $field = null): string { @@ -617,9 +613,7 @@ public function getError(?string $field = null): string * 'field2' => 'error message', * ] * - * @return array - * - * Excluded from code coverage because that it always run as cli + * @return array * * @codeCoverageIgnore */ @@ -648,12 +642,10 @@ public function setError(string $field, string $error): ValidationInterface /** * Attempts to find the appropriate error message * - * @param string $param - * @param string $value The value that caused the validation to fail. + * @param string|null $value The value that caused the validation to fail. */ protected function getErrorMessage(string $rule, string $field, ?string $label = null, ?string $param = null, ?string $value = null): string { - // Check if custom message has been defined by user if (isset($this->customErrors[$field][$rule])) { $message = lang($this->customErrors[$field][$rule]); } else { @@ -666,7 +658,7 @@ protected function getErrorMessage(string $rule, string $field, ?string $label = $message = str_replace('{field}', empty($label) ? $field : lang($label), $message); $message = str_replace('{param}', empty($this->rules[$param]['label']) ? $param : lang($this->rules[$param]['label']), $message); - return str_replace('{value}', $value, $message); + return str_replace('{value}', $value ?? '', $message); } /** diff --git a/tests/system/I18n/TimeTest.php b/tests/system/I18n/TimeTest.php index 205a98098724..75f4416676fc 100644 --- a/tests/system/I18n/TimeTest.php +++ b/tests/system/I18n/TimeTest.php @@ -42,8 +42,7 @@ public function testNewTimeNow() 'yyyy-MM-dd HH:mm:ss' ); - $time = new Time(null, 'America/Chicago'); - + $time = new Time('', 'America/Chicago'); $this->assertSame($formatter->format($time), (string) $time); } From d4d3316909476cab57474d77c4cebc753f328cc2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 10:16:37 +0900 Subject: [PATCH 170/407] docs: fix by proofreading Co-authored-by: MGatner --- user_guide_src/source/general/modules.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/modules.rst b/user_guide_src/source/general/modules.rst index 85a1d4ae82f8..581b2617aabb 100644 --- a/user_guide_src/source/general/modules.rst +++ b/user_guide_src/source/general/modules.rst @@ -196,7 +196,7 @@ Config files are automatically discovered whenever using the **config()** functi .. note:: **config()** finds the file in **app/Config/** when there is a class with the same shortname, even if you specify a fully qualified class name like ``config(\Acme\Blog\Config\Blog::class)``. - This is because ``Factories``'s the default configuration. See :ref:`factories-options` for more information. + This is because ``config()`` is a wrapper for the ``Factories`` class which uses ``preferApp`` by default. See :ref:`factories-options` for more information. Migrations ========== From 09147bb716ea7599cbf0e8bc67a52aa07b89ea7b Mon Sep 17 00:00:00 2001 From: vlakoff Date: Sun, 26 Sep 2021 09:49:18 +0200 Subject: [PATCH 171/407] Determine if binds are simple or named by looking at the $binds array --- system/Database/Query.php | 34 +++++++++++++------------ tests/system/Database/BaseQueryTest.php | 26 ++++++++++++++++++- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index a4bb1b2b9de5..aaf6b6cb9671 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -275,14 +275,7 @@ protected function compileBinds() { $sql = $this->finalQueryString; - $hasBinds = strpos($sql, $this->bindMarker) !== false; - $hasNamedBinds = ! $hasBinds - && preg_match('/:(?!=).+:/', $sql) === 1; - - if (empty($this->binds) - || empty($this->bindMarker) - || (! $hasNamedBinds && ! $hasBinds) - ) { + if (empty($this->binds)) { return; } @@ -294,16 +287,25 @@ protected function compileBinds() $bindCount = count($binds); } - // Reverse the binds so that duplicate named binds - // will be processed prior to the original binds. - if (! is_numeric(key(array_slice($binds, 0, 1)))) { - $binds = array_reverse($binds); - } + if (is_numeric(key(array_slice($binds, 0, 1)))) { + if (empty($this->bindMarker) || strpos($sql, $this->bindMarker) === false) { + return; + } - $ml = strlen($this->bindMarker); - $sql = $hasNamedBinds ? $this->matchNamedBinds($sql, $binds) : $this->matchSimpleBinds($sql, $binds, $bindCount, $ml); + $ml = strlen($this->bindMarker); - $this->finalQueryString = $sql; + $this->finalQueryString = $this->matchSimpleBinds($sql, $binds, $bindCount, $ml); + } else { + if (! preg_match('/:(?!=).+:/', $sql)) { + return; + } + + // Reverse the binds so that duplicate named binds + // will be processed prior to the original binds. + $binds = array_reverse($binds); + + $this->finalQueryString = $this->matchNamedBinds($sql, $binds); + } } /** diff --git a/tests/system/Database/BaseQueryTest.php b/tests/system/Database/BaseQueryTest.php index fe942ffeb187..cebbe47163ec 100644 --- a/tests/system/Database/BaseQueryTest.php +++ b/tests/system/Database/BaseQueryTest.php @@ -269,7 +269,7 @@ public function testNamedBinds() /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/3566 */ - public function testNamedBindsWithColonElseWhere() + public function testNamedBindsWithColonElsewhere() { $query = new Query($this->db); $query->setQuery('SELECT `email`, @total:=(total+1) FROM `users` WHERE `id` = :id:', ['id' => 10]); @@ -278,6 +278,30 @@ public function testNamedBindsWithColonElseWhere() $this->assertSame($sql, $query->getQuery()); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/pull/5138 + */ + public function testNamedBindsWithBindMarkerElsewhere() + { + $query = new Query($this->db); + $query->setQuery('SELECT * FROM posts WHERE id = :id: AND title = \'The default bind marker is "?"\'', ['id' => 10]); + + $sql = 'SELECT * FROM posts WHERE id = 10 AND title = \'The default bind marker is "?"\''; + $this->assertSame($sql, $query->getQuery()); + } + + /** + * @see https://github.com/codeigniter4/CodeIgniter4/pull/5138 + */ + public function testSimpleBindsWithNamedBindPlaceholderElsewhere() + { + $query = new Query($this->db); + $query->setQuery('SELECT * FROM posts WHERE id = ? AND title = \'A named bind placeholder looks like ":foobar:"\'', 10); + + $sql = 'SELECT * FROM posts WHERE id = 10 AND title = \'A named bind placeholder looks like ":foobar:"\''; + $this->assertSame($sql, $query->getQuery()); + } + /** * @group single * From a8e549b355fb6e17dac11de6b5e5cc1911fb7974 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Sun, 26 Sep 2021 10:16:41 +0200 Subject: [PATCH 172/407] Remove tests that are now superfluous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Simple binds: matchSimpleBinds() also handles the bind marker, and more elaborately: handles enclosing quotes, checks the number of markers… * Named binds: there just won't be replacements for matchNamedBinds() to make. --- system/Database/Query.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index aaf6b6cb9671..1892781e44c0 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -288,7 +288,7 @@ protected function compileBinds() } if (is_numeric(key(array_slice($binds, 0, 1)))) { - if (empty($this->bindMarker) || strpos($sql, $this->bindMarker) === false) { + if (empty($this->bindMarker)) { return; } @@ -296,10 +296,6 @@ protected function compileBinds() $this->finalQueryString = $this->matchSimpleBinds($sql, $binds, $bindCount, $ml); } else { - if (! preg_match('/:(?!=).+:/', $sql)) { - return; - } - // Reverse the binds so that duplicate named binds // will be processed prior to the original binds. $binds = array_reverse($binds); From d1a973869bcc9cfd1b386201c1940ed03a5cfcc0 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Fri, 1 Oct 2021 22:23:49 +0200 Subject: [PATCH 173/407] Remove another superfluous test It's very unlikely that the bindMarker property would be empty. --- system/Database/Query.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index 1892781e44c0..64264bf70635 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -288,10 +288,6 @@ protected function compileBinds() } if (is_numeric(key(array_slice($binds, 0, 1)))) { - if (empty($this->bindMarker)) { - return; - } - $ml = strlen($this->bindMarker); $this->finalQueryString = $this->matchSimpleBinds($sql, $binds, $bindCount, $ml); From 211f713f7ac9bc91ebbf734ffe21e923ad272073 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Fri, 1 Oct 2021 22:24:59 +0200 Subject: [PATCH 174/407] Some refinement / optimization Considering that $binds is usually an array, and that only matchSimpleBinds() needs the count. --- system/Database/Query.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index 64264bf70635..021a360d85c9 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -279,16 +279,11 @@ protected function compileBinds() return; } - if (! is_array($this->binds)) { - $binds = [$this->binds]; - $bindCount = 1; - } else { - $binds = $this->binds; - $bindCount = count($binds); - } + $binds = (array) $this->binds; if (is_numeric(key(array_slice($binds, 0, 1)))) { - $ml = strlen($this->bindMarker); + $bindCount = count($binds); + $ml = strlen($this->bindMarker); $this->finalQueryString = $this->matchSimpleBinds($sql, $binds, $bindCount, $ml); } else { From 2a08bc7a0dc5a7b688fa40a86b43fa745ed7d995 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Tue, 16 Nov 2021 15:25:49 +0100 Subject: [PATCH 175/407] Make the test "array is a list" a bit more robust We are looking for an integer, excluding other numeric values (decimals, etc). As a reminder: for array keys, PHP automatically casts strings representing integers to regular integers. --- system/Database/Query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index 021a360d85c9..a2f65f629f8a 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -281,7 +281,7 @@ protected function compileBinds() $binds = (array) $this->binds; - if (is_numeric(key(array_slice($binds, 0, 1)))) { + if (is_int(key(array_slice($binds, 0, 1)))) { $bindCount = count($binds); $ml = strlen($this->bindMarker); From 9d92d56d6401f12bfe2780a6f56886155076bd71 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Tue, 23 Nov 2021 03:04:12 +0100 Subject: [PATCH 176/407] Use array_key_first() Same results, but simpler and faster code. Note array_key_first() is available on PHP 7.3+, which is thankfully the minimum PHP version required by CodeIgniter. --- system/Database/Query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index a2f65f629f8a..f1ec562034c7 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -281,7 +281,7 @@ protected function compileBinds() $binds = (array) $this->binds; - if (is_int(key(array_slice($binds, 0, 1)))) { + if (is_int(array_key_first($binds))) { $bindCount = count($binds); $ml = strlen($this->bindMarker); From 147fc9d8f6cc449c2fd56eb3c9022c43c3dd19e3 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sun, 21 Nov 2021 18:36:02 +0800 Subject: [PATCH 177/407] Fix precision loss deprecation on float to int conversion --- system/Images/Handlers/GDHandler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/Images/Handlers/GDHandler.php b/system/Images/Handlers/GDHandler.php index 02d61c40a007..ab8e0b7e3dd3 100644 --- a/system/Images/Handlers/GDHandler.php +++ b/system/Images/Handlers/GDHandler.php @@ -188,7 +188,7 @@ protected function process(string $action) imagesavealpha($dest, true); } - $copy($dest, $src, 0, 0, $this->xAxis, $this->yAxis, $this->width, $this->height, $origWidth, $origHeight); + $copy($dest, $src, 0, 0, (int) $this->xAxis, (int) $this->yAxis, $this->width, $this->height, $origWidth, $origHeight); imagedestroy($src); $this->resource = $dest; @@ -472,9 +472,9 @@ protected function textOverlay(string $text, array $options = [], bool $isShadow // Add the shadow to the source image if (! empty($options['fontPath'])) { // We have to add fontheight because imagettftext locates the bottom left corner, not top-left corner. - imagettftext($src, $options['fontSize'], 0, $xAxis, $yAxis + $options['fontheight'], $color, $options['fontPath'], $text); + imagettftext($src, $options['fontSize'], 0, (int) $xAxis, (int) ($yAxis + $options['fontheight']), $color, $options['fontPath'], $text); } else { - imagestring($src, $options['fontSize'], $xAxis, $yAxis, $text, $color); + imagestring($src, (int) $options['fontSize'], (int) $xAxis, (int) $yAxis, $text, $color); } $this->resource = $src; From abab12128ecf8fe1f8920550048d6f064dc862fe Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 14:31:34 +0900 Subject: [PATCH 178/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/incoming/filters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 334edf188fee..ef2b1991004c 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -193,6 +193,6 @@ In this example, the array ``['dual', 'noreturn']`` will be passed in ``$argumen Provided Filters **************** -These filters are bundled with CodeIgniter4: ``Honeypot``, ``CSRF``, ``DebugToolbar`` and ``InvalidChars``. +The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``DebugToolbar``, and ``InvalidChars``. .. note:: The filters are executed in the declared order that is defined in the config file, but there is one exception to this and it concerns the ``DebugToolbar``, which is always executed last. This is because ``DebugToolbar`` should be able to register everything that happens in other filters. From fe3ab5eb9551fa4445e3bc8c54e8e1dab6fe4bee Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 14:32:54 +0900 Subject: [PATCH 179/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/incoming/filters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index ef2b1991004c..60e2ea90cc76 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -195,4 +195,4 @@ Provided Filters The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``DebugToolbar``, and ``InvalidChars``. -.. note:: The filters are executed in the declared order that is defined in the config file, but there is one exception to this and it concerns the ``DebugToolbar``, which is always executed last. This is because ``DebugToolbar`` should be able to register everything that happens in other filters. +.. note:: The filters are executed in the order defined in the config file. However, if enabled, ``DebugToolbar`` is always executed last because it should be able to capture everything that happens in the other filters. From e7e492fe6d7cf2a9253d0a918360b415b9447533 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 14:33:36 +0900 Subject: [PATCH 180/407] test: add param type Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- tests/system/Filters/InvalidCharsTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php index 95725de07323..5bfe9268795c 100644 --- a/tests/system/Filters/InvalidCharsTest.php +++ b/tests/system/Filters/InvalidCharsTest.php @@ -144,10 +144,8 @@ public function stringWithLineBreakAndTabProvider() /** * @dataProvider stringWithControlCharsProvider - * - * @param string $input */ - public function testCheckControlStringWithControlCharsCausesException($input) + public function testCheckControlStringWithControlCharsCausesException(string $input) { $this->expectException(SecurityException::class); $this->expectExceptionMessage('Invalid Control characters in get:'); From 70424d61d5b4d00e0b475b49d36a04a29aa2034c Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 14:33:58 +0900 Subject: [PATCH 181/407] test: add param type Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- tests/system/Filters/InvalidCharsTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php index 5bfe9268795c..fb487c7939dc 100644 --- a/tests/system/Filters/InvalidCharsTest.php +++ b/tests/system/Filters/InvalidCharsTest.php @@ -121,10 +121,8 @@ public function testBeforeInvalidControlCharCausesException() * @doesNotPerformAssertions * * @dataProvider stringWithLineBreakAndTabProvider - * - * @param string $input */ - public function testCheckControlStringWithLineBreakAndTabReturnsTheString($input) + public function testCheckControlStringWithLineBreakAndTabReturnsTheString(string $input) { $_GET['val'] = $input; From 72aa844b5c9ba2adb9d2c326e7a2380d85d9285d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 14:40:36 +0900 Subject: [PATCH 182/407] test: replace return with yield from Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- tests/system/Filters/InvalidCharsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php index fb487c7939dc..90e106eec97d 100644 --- a/tests/system/Filters/InvalidCharsTest.php +++ b/tests/system/Filters/InvalidCharsTest.php @@ -131,7 +131,7 @@ public function testCheckControlStringWithLineBreakAndTabReturnsTheString(string public function stringWithLineBreakAndTabProvider() { - return [ + yield from [ ["String contains \n line break."], ["String contains \r line break."], ["String contains \r\n line break."], From 9d7e0389a981f0c8e4650fc4c61d8414bd88aa1a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 14:40:43 +0900 Subject: [PATCH 183/407] test: replace return with yield from Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- tests/system/Filters/InvalidCharsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/Filters/InvalidCharsTest.php b/tests/system/Filters/InvalidCharsTest.php index 90e106eec97d..8724413120b5 100644 --- a/tests/system/Filters/InvalidCharsTest.php +++ b/tests/system/Filters/InvalidCharsTest.php @@ -155,7 +155,7 @@ public function testCheckControlStringWithControlCharsCausesException(string $in public function stringWithControlCharsProvider() { - return [ + yield from [ ["String contains null char.\0"], ["String contains null char and line break.\0\n"], ]; From b8fe16d2ff708971693a5e3325b74447ffb93fdd Mon Sep 17 00:00:00 2001 From: Katherine Date: Tue, 23 Nov 2021 11:49:00 +0000 Subject: [PATCH 184/407] fix: BaseModel::insert() may not pass all the values from Entity (#4980) * Update of BaseModel.php to fix INSERT issue Applied the fix that enables the INSERT to work correctly when inserting a row that already contains data. * Update BaseModel.php * Added tests for fix. User.php is an Entity UserObjModel.php returns an entity not StdObj * Updated to simplify usings. * Updated to cleanup test code. * Update tests/system/Models/InsertModelTest.php Co-authored-by: kenjis * Update tests/_support/Entity/User.php Co-authored-by: kenjis Co-authored-by: Katherine Co-authored-by: kenjis --- system/BaseModel.php | 2 +- tests/_support/Entity/User.php | 21 +++++++++++++++++++ tests/_support/Models/UserObjModel.php | 28 +++++++++++++++++++++++++ tests/system/Models/InsertModelTest.php | 22 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tests/_support/Entity/User.php create mode 100644 tests/_support/Models/UserObjModel.php diff --git a/system/BaseModel.php b/system/BaseModel.php index 6b9ef3687817..971303664a8e 100644 --- a/system/BaseModel.php +++ b/system/BaseModel.php @@ -1578,7 +1578,7 @@ protected function transformDataToArray($data, string $type): array // properties representing the collection elements, we need to grab // them as an array. if (is_object($data) && ! $data instanceof stdClass) { - $data = $this->objectToArray($data, true, true); + $data = $this->objectToArray($data, ($type === 'update'), true); } // If it's still a stdClass, go ahead and convert to diff --git a/tests/_support/Entity/User.php b/tests/_support/Entity/User.php new file mode 100644 index 000000000000..dc8a3954341d --- /dev/null +++ b/tests/_support/Entity/User.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Support\Entity; + +use CodeIgniter\Entity\Entity; + +class User extends Entity +{ + protected $attributes = [ + 'country' => 'India', + ]; +} diff --git a/tests/_support/Models/UserObjModel.php b/tests/_support/Models/UserObjModel.php new file mode 100644 index 000000000000..ea461ec64fb3 --- /dev/null +++ b/tests/_support/Models/UserObjModel.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Support\Models; + +use CodeIgniter\Model; + +class UserObjModel extends Model +{ + protected $table = 'user'; + protected $allowedFields = [ + 'name', + 'email', + 'country', + 'deleted_at', + ]; + protected $returnType = \Tests\Support\Entity\User::class; + protected $useSoftDeletes = true; + protected $dateFormat = 'datetime'; +} diff --git a/tests/system/Models/InsertModelTest.php b/tests/system/Models/InsertModelTest.php index d08db6f87ac8..2bcc912e3d80 100644 --- a/tests/system/Models/InsertModelTest.php +++ b/tests/system/Models/InsertModelTest.php @@ -15,8 +15,10 @@ use CodeIgniter\Entity\Entity; use CodeIgniter\I18n\Time; use stdClass; +use Tests\Support\Entity\User; use Tests\Support\Models\JobModel; use Tests\Support\Models\UserModel; +use Tests\Support\Models\UserObjModel; use Tests\Support\Models\WithoutAutoIncrementModel; /** @@ -286,4 +288,24 @@ public function testInsertWithSetAndEscape(): void $this->assertCloseEnough(time(), strtotime($result->created_at)); } + + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/4247 + */ + public function testInsertWithDefaultValue(): void + { + $this->createModel(UserObjModel::class); + + $entity = new User(); + $entity->name = 'Mark'; + $entity->email = 'mark@example.com'; + $entity->country = 'India'; // same as the default + $entity->deleted = 0; + $entity->created_at = new Time('now'); + + $this->model->insert($entity); + + $id = $this->model->getInsertID(); + $this->assertSame($entity->country, $this->model->find($id)->country); + } } From 3497170a595f99238ce50bd8381cb94258591535 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 09:53:25 +0900 Subject: [PATCH 185/407] fix: make sure $this->tableName is string --- system/Database/BaseBuilder.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index b0ea12416683..0d7ca807a036 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -158,6 +158,9 @@ class BaseBuilder * Tracked separately because $QBFrom gets escaped * and prefixed. * + * When $tableName to the constructor has multiple tables, + * the value is empty string. + * * @var string */ protected $tableName; @@ -276,7 +279,13 @@ public function __construct($tableName, ConnectionInterface &$db, ?array $option */ $this->db = $db; - $this->tableName = $tableName; + // If it contains `,`, it has multiple tables + if (is_string($tableName) && strpos($tableName, ',') === false) { + $this->tableName = $tableName; // @TODO remove alias if exists + } else { + $this->tableName = ''; + } + $this->from($tableName); if (! empty($options)) { From 82e27ba2eb20892b0133645a44f9d349f5cc5430 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 09:55:47 +0900 Subject: [PATCH 186/407] docs: make comment more detailed --- system/Database/BaseBuilder.php | 4 +++- system/Database/BaseConnection.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 0d7ca807a036..fecf3e10718f 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -264,7 +264,9 @@ class BaseBuilder /** * Constructor * - * @param array|string $tableName + * @param array|string $tableName tablename or tablenames with or without aliases + * + * Examples of $tableName: `mytable`, `jobs j`, `jobs j, users u`, `['jobs j','users u']` * * @throws DatabaseException */ diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index b7168259e631..f2ceb5a0f907 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -835,7 +835,7 @@ abstract protected function _transCommit(): bool; abstract protected function _transRollback(): bool; /** - * Returns an instance of the query builder for this connection. + * Returns a non-shared new instance of the query builder for this connection. * * @param array|string $tableName * From d22c6f14ece4f603184942c73ff5e26780d6458c Mon Sep 17 00:00:00 2001 From: vlakoff Date: Wed, 24 Nov 2021 04:48:32 +0100 Subject: [PATCH 187/407] Remove unneeded cast to array As discussed on GitHub PR #5138, $this->binds is not expected to be something else than an array. --- system/Database/Query.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index f1ec562034c7..91b98c77d2ef 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -273,14 +273,13 @@ public function getOriginalQuery(): string */ protected function compileBinds() { - $sql = $this->finalQueryString; + $sql = $this->finalQueryString; + $binds = $this->binds; - if (empty($this->binds)) { + if (empty($binds)) { return; } - $binds = (array) $this->binds; - if (is_int(array_key_first($binds))) { $bindCount = count($binds); $ml = strlen($this->bindMarker); From 0f3ce86e425847ba3518425000cbe3258cf919c1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 13:22:15 +0900 Subject: [PATCH 188/407] docs: fix incorrect explanation on getCompiledInsert() It has only one parameter in CI4. --- user_guide_src/source/database/query_builder.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index a05fb25f8159..7aa8cf69dcdb 100755 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -886,15 +886,15 @@ Example:: 'date' => 'My date', ]; - $sql = $builder->set($data)->getCompiledInsert('mytable'); + $sql = $builder->set($data)->getCompiledInsert(); echo $sql; // Produces string: INSERT INTO mytable (`title`, `name`, `date`) VALUES ('My title', 'My name', 'My date') -The second parameter enables you to set whether or not the query builder query +The first parameter enables you to set whether or not the query builder query will be reset (by default it will be--just like ``$builder->insert()``):: - echo $builder->set('title', 'My Title')->getCompiledInsert('mytable', false); + echo $builder->set('title', 'My Title')->getCompiledInsert(false); // Produces string: INSERT INTO mytable (`title`) VALUES ('My Title') @@ -902,9 +902,7 @@ will be reset (by default it will be--just like ``$builder->insert()``):: // Produces string: INSERT INTO mytable (`title`, `content`) VALUES ('My Title', 'My Content') -The key thing to notice in the above example is that the second query did not -utilize ``$builder->from()`` nor did it pass a table name into the first -parameter. The reason this worked is that the query has not been executed +The reason the second query worked is that the query has not been executed using ``$builder->insert()`` which resets values or reset directly using ``$builder->resetQuery()``. From 81859f2920148fa7e95a0cceadfaf06fa09ee98f Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 14:30:14 +0900 Subject: [PATCH 189/407] docs: change from important to warning It is security thing. --- user_guide_src/source/general/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/configuration.rst b/user_guide_src/source/general/configuration.rst index ac31e6f3241a..7543802f39ad 100644 --- a/user_guide_src/source/general/configuration.rst +++ b/user_guide_src/source/general/configuration.rst @@ -115,7 +115,7 @@ overwritten. The loaded Environment variables are accessed using any of the foll $s3_bucket = $_ENV['S3_BUCKET']; $s3_bucket = $_SERVER['S3_BUCKET']; -.. important:: Note that your settings from the **.env** file are added to Environment Variables. As a side effect, this means that if your CodeIgniter application is (for example) generating a ``var_dump($_ENV)`` or ``phpinfo()`` (for debugging or other valid reasons) **your secure credentials are publicly exposed**. +.. warning:: Note that your settings from the **.env** file are added to Environment Variables. As a side effect, this means that if your CodeIgniter application is (for example) generating a ``var_dump($_ENV)`` or ``phpinfo()`` (for debugging or other valid reasons) **your secure credentials are publicly exposed**. Nesting Variables ================= From 954cc0d8c85e8545b0402156f50bbd632f6db787 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 14:37:04 +0900 Subject: [PATCH 190/407] docs: add ::class sample --- user_guide_src/source/general/configuration.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/general/configuration.rst b/user_guide_src/source/general/configuration.rst index 7543802f39ad..b1016b939c9b 100644 --- a/user_guide_src/source/general/configuration.rst +++ b/user_guide_src/source/general/configuration.rst @@ -31,7 +31,8 @@ You can access configuration files for your classes in several different ways. $config = config('Pager'); // Access config class with namespace - $config = config( 'Config\\Pager' ); + $config = config('Config\\Pager'); + $config = config(\Config\Pager::class); // Creating a new object with config function $config = config('Pager', false); From e452d510ad374cbb4040018c21af53f80db36f18 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 14:37:37 +0900 Subject: [PATCH 191/407] docs: fix RST format --- user_guide_src/source/general/configuration.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/user_guide_src/source/general/configuration.rst b/user_guide_src/source/general/configuration.rst index b1016b939c9b..813f523c7fa2 100644 --- a/user_guide_src/source/general/configuration.rst +++ b/user_guide_src/source/general/configuration.rst @@ -122,8 +122,7 @@ Nesting Variables ================= To save on typing, you can reuse variables that you've already specified in the file by wrapping the -variable name within ``${...}`` -:: +variable name within ``${...}``:: BASE_DIR="/var/webroot/project-root" CACHE_DIR="${BASE_DIR}/cache" From f990c7f9be275f054a73426e1cc7993756a1e965 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 14:52:22 +0900 Subject: [PATCH 192/407] docs: add reference from Module Routes to Route processing queue --- user_guide_src/source/general/modules.rst | 3 +++ user_guide_src/source/incoming/routing.rst | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/general/modules.rst b/user_guide_src/source/general/modules.rst index 91ec5554c955..19797b099416 100644 --- a/user_guide_src/source/general/modules.rst +++ b/user_guide_src/source/general/modules.rst @@ -153,6 +153,9 @@ the **Modules** config file, described above. .. note:: Since the files are being included into the current scope, the ``$routes`` instance is already defined for you. It will cause errors if you attempt to redefine that class. +When working with modules, it can be a problem if the routes in the application contain wildcards. +In that case, see :ref:`routing-priority`. + Filters ======= diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 5f18fb4960d8..be571d34b736 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -456,7 +456,7 @@ be used when the first parameter is a language string:: // Creates: $routes['users/(:num)'] = 'users/show/$2'; -.. _priority: +.. _routing-priority: Route processing queue ---------------------- @@ -590,7 +590,7 @@ Route processing by priority Enables or disables processing of the routes queue by priority. Lowering the priority is defined in the route option. Disabled by default. This functionality affects all routes. -For an example of use lowering the priority see :ref:`priority`:: +For an example of use lowering the priority see :ref:`routing-priority`:: // to enable $routes->setPrioritize(); From dfa5229145de49c9e31556129959e87901c2d262 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 15:25:52 +0900 Subject: [PATCH 193/407] docs: replace PSR* with PSR-* --- user_guide_src/source/concepts/autoloader.rst | 4 ++-- user_guide_src/source/general/logging.rst | 4 ++-- user_guide_src/source/general/modules.rst | 6 +++--- user_guide_src/source/installation/upgrade_4xx.rst | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/user_guide_src/source/concepts/autoloader.rst b/user_guide_src/source/concepts/autoloader.rst index 543d70323bc6..beb8da256f0b 100644 --- a/user_guide_src/source/concepts/autoloader.rst +++ b/user_guide_src/source/concepts/autoloader.rst @@ -11,7 +11,7 @@ headache and very error-prone. That's where autoloaders come in. CodeIgniter provides a very flexible autoloader that can be used with very little configuration. It can locate individual non-namespaced classes, namespaced classes that adhere to -`PSR4 `_ autoloading +`PSR-4 `_ autoloading directory structures, and will even attempt to locate classes in common directories (like Controllers, Models, etc). @@ -30,7 +30,7 @@ Configuration ============= Initial configuration is done in **/app/Config/Autoload.php**. This file contains two primary -arrays: one for the classmap, and one for PSR4-compatible namespaces. +arrays: one for the classmap, and one for PSR-4 compatible namespaces. Namespaces ========== diff --git a/user_guide_src/source/general/logging.rst b/user_guide_src/source/general/logging.rst index 7fa706ce6a86..761500ac722a 100644 --- a/user_guide_src/source/general/logging.rst +++ b/user_guide_src/source/general/logging.rst @@ -136,8 +136,8 @@ Using Third-Party Loggers ========================= You can use any other logger that you might like as long as it extends from either -``Psr\Log\LoggerInterface`` and is `PSR3 `_ compatible. This means -that you can easily drop in use for any PSR3-compatible logger, or create your own. +``Psr\Log\LoggerInterface`` and is `PSR-3 `_ compatible. This means +that you can easily drop in use for any PSR-3 compatible logger, or create your own. You must ensure that the third-party logger can be found by the system, by adding it to either the **app/Config/Autoload.php** configuration file, or through another autoloader, diff --git a/user_guide_src/source/general/modules.rst b/user_guide_src/source/general/modules.rst index 91ec5554c955..7aea12358fdb 100644 --- a/user_guide_src/source/general/modules.rst +++ b/user_guide_src/source/general/modules.rst @@ -15,8 +15,8 @@ language files, etc. Modules may contain as few, or as many, of these as you lik Namespaces ========== -The core element of the modules functionality comes from the :doc:`PSR4-compatible autoloading ` -that CodeIgniter uses. While any code can use the PSR4 autoloader and namespaces, the primary way to take full advantage of +The core element of the modules functionality comes from the :doc:`PSR-4 compatible autoloading ` +that CodeIgniter uses. While any code can use the PSR-4 autoloader and namespaces, the primary way to take full advantage of modules is to namespace your code and add it to **app/Config/Autoload.php**, in the ``psr4`` section. For example, let's say we want to keep a simple blog module that we can re-use between applications. We might create @@ -129,7 +129,7 @@ Discovery and Composer ====================== Packages that were installed via Composer will also be discovered by default. This only requires that the namespace -that Composer knows about is a PSR4 namespace. PSR0 namespaces will not be detected. +that Composer knows about is a PSR-4 namespace. PSR-0 namespaces will not be detected. If you do not want all of Composer's known directories to be scanned when locating files, you can turn this off by editing the ``$discoverInComposer`` variable in ``Config\Modules.php``:: diff --git a/user_guide_src/source/installation/upgrade_4xx.rst b/user_guide_src/source/installation/upgrade_4xx.rst index 76fdba16c8e0..ae6bd0188608 100644 --- a/user_guide_src/source/installation/upgrade_4xx.rst +++ b/user_guide_src/source/installation/upgrade_4xx.rst @@ -77,7 +77,7 @@ General Adjustments references magically injected as properties of your controller. - Classes are instantiated where needed, and components are managed by ``Services``. -- The class loader automatically handles PSR4 style class locating, +- The class loader automatically handles PSR-4 style class locating, within the ``App`` (application) and ``CodeIgniter`` (i.e., system) top level namespaces; with composer autoloading support, and even using educated guessing to find your models and libraries if they are in the right From 0ba441a1518d9d80d00cac076f28eb27d670bd38 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 15:38:59 +0900 Subject: [PATCH 194/407] docs: change lang file sample filename to uppercase first --- user_guide_src/source/outgoing/localization.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/outgoing/localization.rst b/user_guide_src/source/outgoing/localization.rst index 97d3fbdf6d5e..996224fc2c72 100644 --- a/user_guide_src/source/outgoing/localization.rst +++ b/user_guide_src/source/outgoing/localization.rst @@ -20,9 +20,9 @@ supported language:: /app /Language /en - app.php + App.php /fr - app.php + App.php .. important:: Locale detection only works for web-based requests that use the IncomingRequest class. Command-line requests will not have these features. From 025d27a76daeab7e7c0bef2688db8eb7ec103aed Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 15:40:42 +0900 Subject: [PATCH 195/407] docs: change lang key to camelCase --- user_guide_src/source/outgoing/localization.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/outgoing/localization.rst b/user_guide_src/source/outgoing/localization.rst index 996224fc2c72..f9e0693abfcb 100644 --- a/user_guide_src/source/outgoing/localization.rst +++ b/user_guide_src/source/outgoing/localization.rst @@ -119,11 +119,11 @@ You might name it simply: **Errors.php**. Within the file, you would return an array, where each element in the array has a language key and can have string to return:: - 'language_key' => 'The actual message to be shown.' + 'languageKey' => 'The actual message to be shown.' It also support nested definition:: - 'language_key' => [ + 'languageKey' => [ 'nested' => [ 'key' => 'The actual message to be shown.', ], From a7fc1bed9e4d740cc440e591296c9ef169968e90 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 15:41:09 +0900 Subject: [PATCH 196/407] docs: remove out-of-dated note It seems about CI3. --- user_guide_src/source/outgoing/localization.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/user_guide_src/source/outgoing/localization.rst b/user_guide_src/source/outgoing/localization.rst index f9e0693abfcb..4c78ed39ee44 100644 --- a/user_guide_src/source/outgoing/localization.rst +++ b/user_guide_src/source/outgoing/localization.rst @@ -129,10 +129,6 @@ It also support nested definition:: ], ], -.. note:: It's good practice to use a common prefix for all messages in a given file to avoid collisions with - similarly named items in other files. For example, if you are creating error messages you might prefix them - with error\_ - :: return [ From 96381ea4a8cbeff2be980785074ea1b8b0ace478 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 15:41:56 +0900 Subject: [PATCH 197/407] docs: replace " with ' in sample code No reason to use `"`. --- user_guide_src/source/outgoing/localization.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/outgoing/localization.rst b/user_guide_src/source/outgoing/localization.rst index 4c78ed39ee44..58b24c48524f 100644 --- a/user_guide_src/source/outgoing/localization.rst +++ b/user_guide_src/source/outgoing/localization.rst @@ -170,9 +170,9 @@ You can pass an array of values to replace placeholders in the language string a // The language file, Tests.php: return [ - "apples" => "I have {0, number} apples.", - "men" => "The top {1, number} men out-performed the remaining {0, number}", - "namedApples" => "I have {number_apples, number, integer} apples.", + 'apples' => 'I have {0, number} apples.', + 'men' => 'The top {1, number} men out-performed the remaining {0, number}', + 'namedApples' => 'I have {number_apples, number, integer} apples.', ]; // Displays "I have 3 apples." @@ -186,7 +186,7 @@ The first item in the placeholder corresponds to the index of the item in the ar You can also use named keys to make it easier to keep things straight, if you'd like:: // Displays "I have 3 apples." - echo lang("Tests.namedApples", ['number_apples' => 3]); + echo lang('Tests.namedApples', ['number_apples' => 3]); Obviously, you can do more than just number replacement. According to the `official ICU docs `_ for the underlying From 95a0ed59f17e3d5495bc4ac187b43d9829ae5df1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Nov 2021 18:38:48 +0900 Subject: [PATCH 198/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/incoming/routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index be571d34b736..0e9f3bb4e6be 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -590,7 +590,7 @@ Route processing by priority Enables or disables processing of the routes queue by priority. Lowering the priority is defined in the route option. Disabled by default. This functionality affects all routes. -For an example of use lowering the priority see :ref:`routing-priority`:: +For an example use of lowering the priority see :ref:`routing-priority`:: // to enable $routes->setPrioritize(); From 9edc247dbafae08f5e55c2b0e41ad18175e14afe Mon Sep 17 00:00:00 2001 From: Toto Prayogo Date: Wed, 24 Nov 2021 20:57:38 +0700 Subject: [PATCH 199/407] update line numbers about Paths.php --- user_guide_src/source/general/managing_apps.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index c1781e032fa0..21fcebdf9407 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -14,14 +14,14 @@ Renaming or Relocating the Application Directory If you would like to rename your application directory or even move it to a different location on your server, other than your project root, open your main **app/Config/Paths.php** and set a *full server path* in the -``$appDirectory`` variable (at about line 45):: +``$appDirectory`` variable (at about line 44):: public $appDirectory = '/path/to/your/application'; You will need to modify two additional files in your project root, so that they can find the ``Paths`` configuration file: -- ``/spark`` runs command line apps; the path is specified on or about line 36:: +- ``/spark`` runs command line apps; the path is specified on or about line 35:: $pathsConfig = 'app/Config/Paths.php'; // ^^^ Change this line if you move your application folder From bead7d01437aaef5f22f6e7bc9b8ff078859ae00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Nov 2021 15:03:44 +0000 Subject: [PATCH 200/407] chore(deps-dev): update rector/rector requirement from 0.12.4 to 0.12.5 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/0.12.4...0.12.5) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4e3ebda66819..064f7b392e05 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.12.4" + "rector/rector": "0.12.5" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" From 9def2430108d867615145e612419f64f7dc8f194 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 13:23:58 +0900 Subject: [PATCH 201/407] chore: add PHPUnitSetList::PHPUNIT_80 and remove skip of AssertFalseStrposToContainsRector --- rector.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rector.php b/rector.php index 829ec303e0f4..92636b0bfdd5 100644 --- a/rector.php +++ b/rector.php @@ -42,7 +42,6 @@ use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; -use Rector\PHPUnit\Rector\MethodCall\AssertFalseStrposToContainsRector; use Rector\PHPUnit\Rector\MethodCall\AssertIssetToSpecificMethodRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\LevelSetList; @@ -57,6 +56,7 @@ $containerConfigurator->import(SetList::DEAD_CODE); $containerConfigurator->import(LevelSetList::UP_TO_PHP_73); $containerConfigurator->import(PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD); + $containerConfigurator->import(PHPUnitSetList::PHPUNIT_80); $parameters = $containerConfigurator->parameters(); @@ -122,9 +122,6 @@ __DIR__ . '/tests/system/Entity/EntityTest.php', __DIR__ . '/tests/system/Session/SessionTest.php', ], - - // assertContains() to string can't be used in PHPUnit 9.1 - AssertFalseStrposToContainsRector::class, ]); // auto import fully qualified class names From 3cf95b599a59a1569378aa20fe944e096bc6ca4a Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 15 Nov 2021 13:25:13 +0900 Subject: [PATCH 202/407] test: refactor: vendor/bin/rector process tests/system/ --- tests/system/HTTP/ResponseTest.php | 4 ++-- tests/system/View/ViewTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/system/HTTP/ResponseTest.php b/tests/system/HTTP/ResponseTest.php index 64eab48dc0fa..b4eba4c547c9 100644 --- a/tests/system/HTTP/ResponseTest.php +++ b/tests/system/HTTP/ResponseTest.php @@ -327,7 +327,7 @@ public function testJSONWithArray() $response->setJSON($body); $this->assertSame($expected, $response->getJSON()); - $this->assertNotFalse(strpos($response->getHeaderLine('content-type'), 'application/json')); + $this->assertStringContainsString('application/json', $response->getHeaderLine('content-type')); } public function testJSONGetFromNormalBody() @@ -364,7 +364,7 @@ public function testXMLWithArray() $response->setXML($body); $this->assertSame($expected, $response->getXML()); - $this->assertNotFalse(strpos($response->getHeaderLine('content-type'), 'application/xml')); + $this->assertStringContainsString('application/xml', $response->getHeaderLine('content-type')); } public function testXMLGetFromNormalBody() diff --git a/tests/system/View/ViewTest.php b/tests/system/View/ViewTest.php index 435c4d8f9578..d740e17a4c34 100644 --- a/tests/system/View/ViewTest.php +++ b/tests/system/View/ViewTest.php @@ -316,8 +316,8 @@ public function testRenderLayoutWithInclude() $content = $view->render('extend_include'); - $this->assertNotFalse(strpos($content, '

Open

')); - $this->assertNotFalse(strpos($content, '

Hello World

')); + $this->assertStringContainsString('

Open

', $content); + $this->assertStringContainsString('

Hello World

', $content); $this->assertSame(2, substr_count($content, 'Hello World')); } From 6cd24700ac3be69e776e0d9db1c5df5447299505 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Thu, 25 Nov 2021 12:08:40 +0800 Subject: [PATCH 203/407] Additional fix for deprecated `null` usage --- system/HTTP/IncomingRequest.php | 2 +- system/Validation/FormatRules.php | 22 ++++++++++++++++------ system/Validation/Rules.php | 10 +++++++++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index 3ac25b6df5fd..76b0c1d1c40a 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -565,7 +565,7 @@ public function getJsonVar(string $index, bool $assoc = false, ?int $filter = nu */ public function getRawInput() { - parse_str($this->body, $output); + parse_str($this->body ?? '', $output); return $output; } diff --git a/system/Validation/FormatRules.php b/system/Validation/FormatRules.php index e28f6d6af13d..4d02f221365d 100644 --- a/system/Validation/FormatRules.php +++ b/system/Validation/FormatRules.php @@ -45,11 +45,16 @@ public function alpha_space(?string $value = null): bool /** * Alphanumeric with underscores and dashes + * + * @see https://regex101.com/r/XfVY3d/1 */ public function alpha_dash(?string $str = null): bool { - // @see https://regex101.com/r/XfVY3d/1 - return (bool) preg_match('/\A[a-z0-9_-]+\z/i', $str); + if ($str === null) { + return false; + } + + return preg_match('/\A[a-z0-9_-]+\z/i', $str) === 1; } /** @@ -59,14 +64,19 @@ public function alpha_dash(?string $str = null): bool * _ underscore, + plus, = equals, | vertical bar, : colon, . period * ~ ! # $ % & * - _ + = | : . * - * @param string $str + * @param string|null $str * * @return bool + * + * @see https://regex101.com/r/6N8dDY/1 */ public function alpha_numeric_punct($str) { - // @see https://regex101.com/r/6N8dDY/1 - return (bool) preg_match('/\A[A-Z0-9 ~!#$%\&\*\-_+=|:.]+\z/i', $str); + if ($str === null) { + return false; + } + + return preg_match('/\A[A-Z0-9 ~!#$%\&\*\-_+=|:.]+\z/i', $str) === 1; } /** @@ -307,7 +317,7 @@ public function valid_url_strict(?string $str = null, ?string $validSchemes = nu return false; } - $scheme = strtolower(parse_url($str, PHP_URL_SCHEME)); + $scheme = strtolower(parse_url($str, PHP_URL_SCHEME) ?? ''); // absent scheme gives null $validSchemes = explode( ',', strtolower($validSchemes ?? 'http,https') diff --git a/system/Validation/Rules.php b/system/Validation/Rules.php index 367915ebae35..aba9ff117df6 100644 --- a/system/Validation/Rules.php +++ b/system/Validation/Rules.php @@ -213,11 +213,19 @@ public function not_in_list(?string $value, string $list): bool */ public function required($str = null): bool { + if ($str === null) { + return false; + } + if (is_object($str)) { return true; } - return is_array($str) ? ! empty($str) : (trim($str) !== ''); + if (is_array($str)) { + return $str !== []; + } + + return trim((string) $str) !== ''; } /** From b2f49be433d3c195be5fc3cfd76eb417e1034ca7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 25 Nov 2021 13:28:11 +0900 Subject: [PATCH 204/407] docs: improve explanation --- user_guide_src/source/general/modules.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/general/modules.rst b/user_guide_src/source/general/modules.rst index 0c38a36bb14b..15a4040f020a 100644 --- a/user_guide_src/source/general/modules.rst +++ b/user_guide_src/source/general/modules.rst @@ -128,8 +128,8 @@ present, then no auto-discovery will happen for that item, but the others in the Discovery and Composer ====================== -Packages that were installed via Composer will also be discovered by default. This only requires that the namespace -that Composer knows about is a PSR-4 namespace. PSR-0 namespaces will not be detected. +Packages installed via Composer using PSR-4 namespaces will also be discovered by default. +PSR-0 namespaced packages will not be detected. If you do not want all of Composer's known directories to be scanned when locating files, you can turn this off by editing the ``$discoverInComposer`` variable in ``Config\Modules.php``:: From 0a5508202b1c08928c7bcb863837a8a119951b32 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" <51850998+paulbalandan@users.noreply.github.com> Date: Thu, 25 Nov 2021 22:24:19 +0800 Subject: [PATCH 205/407] Add support for PHP 8.1 (#4883) --- .github/workflows/test-phpunit.yml | 36 ++++++++++++++---------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index aa7d584991a6..4583244ed358 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -4,12 +4,7 @@ on: push: branches: - develop - - '4.*' paths: - - 'app/**' - - 'public/**' - - 'system/**' - - 'tests/**' - composer.json - spark - phpunit.xml.dist @@ -18,12 +13,7 @@ on: pull_request: branches: - develop - - '4.*' paths: - - 'app/**' - - 'public/**' - - 'system/**' - - 'tests/**' - composer.json - spark - phpunit.xml.dist @@ -31,22 +21,24 @@ on: - .github/workflows/test-phpunit.yml jobs: - tests: + name: PHP ${{ matrix.php-versions }} - ${{ matrix.db-platforms }} runs-on: ubuntu-20.04 if: "!contains(github.event.head_commit.message, '[ci skip]')" - name: PHP ${{ matrix.php-versions }} - ${{ matrix.db-platforms }} strategy: fail-fast: false matrix: - php-versions: ['7.3', '7.4', '8.0'] + php-versions: ['7.3', '7.4', '8.0', '8.1'] db-platforms: ['MySQLi', 'Postgre', 'SQLite3', 'SQLSRV'] mysql-versions: ['5.7'] include: - php-versions: '7.4' db-platforms: MySQLi mysql-versions: '8.0' + # @todo remove once 8.1 is stable enough + - php-versions: '8.1' + composer-flag: '--ignore-platform-req=php' services: mysql: @@ -57,6 +49,7 @@ jobs: ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + postgres: image: postgres env: @@ -66,6 +59,7 @@ jobs: ports: - 5432:5432 options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3 + mssql: image: mcr.microsoft.com/mssql/server:2019-CU10-ubuntu-20.04 env: @@ -75,11 +69,13 @@ jobs: ports: - 1433:1433 options: --health-cmd="/opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q 'SELECT @@VERSION'" --health-interval=10s --health-timeout=5s --health-retries=3 + redis: image: redis ports: - 6379:6379 options: --health-cmd "redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + memcached: image: memcached:1.6-alpine ports: @@ -105,6 +101,7 @@ jobs: - name: Install latest ImageMagick run: | + sudo apt-get update sudo apt-get install --reinstall libgs9-common fonts-noto-mono libgs9:amd64 libijs-0.35:amd64 fonts-urw-base35 ghostscript poppler-data libjbig2dec0:amd64 gsfonts libopenjp2-7:amd64 fonts-droid-fallback ttf-dejavu-core sudo apt-get install -y imagemagick sudo apt-get install --fix-broken @@ -122,13 +119,13 @@ jobs: - name: Install dependencies run: | - composer update --ansi --no-interaction - composer remove --ansi --dev --unused -W rector/rector phpstan/phpstan friendsofphp/php-cs-fixer nexusphp/cs-config codeigniter/coding-standard + composer update --ansi --no-interaction ${{ matrix.composer-flag }} + composer remove --ansi --dev --unused -W ${{ matrix.composer-flag }} -- rector/rector phpstan/phpstan friendsofphp/php-cs-fixer nexusphp/cs-config codeigniter/coding-standard env: COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }} - - name: Profile slow tests in PHP 7.4 MySQLi for now - if: matrix.php-versions == '7.4' && matrix.db-platforms == 'MySQLi' + - name: Profile slow tests in PHP 8.0 + if: matrix.php-versions == '8.0' run: echo "TACHYCARDIA_MONITOR_GA=enabled" >> $GITHUB_ENV - name: Test with PHPUnit @@ -137,8 +134,8 @@ jobs: DB: ${{ matrix.db-platforms }} TERM: xterm-256color - - if: github.repository_owner == 'codeigniter4' && matrix.php-versions == '7.4' - name: Run Coveralls + - name: Run Coveralls + if: github.repository_owner == 'codeigniter4' && matrix.php-versions == '8.0' run: | composer global require --ansi php-coveralls/php-coveralls:^2.4 php-coveralls --coverage_clover=build/logs/clover.xml -v @@ -151,6 +148,7 @@ jobs: if: github.repository_owner == 'codeigniter4' needs: [tests] runs-on: ubuntu-20.04 + steps: - name: Coveralls Finished uses: coverallsapp/github-action@master From 567f0c6507941ffbac0cfeb55e2cc19f84ab6944 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 08:53:44 +0900 Subject: [PATCH 206/407] fix: IncomingRequest::getJsonVar() may cause TypeError See #5391 [TypeError] dot_array_search(): Argument #2 ($array) must be of type array, null given, called in .../system/HTTP/IncomingRequest.php on line 540 at SYSTEMPATH/Helpers/array_helper.php:21 --- system/HTTP/IncomingRequest.php | 6 +++++- tests/system/HTTP/IncomingRequestTest.php | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index 76b0c1d1c40a..ea5b968a6f79 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -537,7 +537,11 @@ public function getJsonVar(string $index, bool $assoc = false, ?int $filter = nu { helper('array'); - $data = dot_array_search($index, $this->getJSON(true)); + $json = $this->getJSON(true); + if (! is_array($json)) { + return null; + } + $data = dot_array_search($index, $json); if ($data === null) { return null; diff --git a/tests/system/HTTP/IncomingRequestTest.php b/tests/system/HTTP/IncomingRequestTest.php index 3b14c6a03357..4229d5d264ec 100644 --- a/tests/system/HTTP/IncomingRequestTest.php +++ b/tests/system/HTTP/IncomingRequestTest.php @@ -394,6 +394,29 @@ public function testGetVarWorksWithJsonAndGetParams() $this->assertSame('buzz', $all['fizz']); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5391 + */ + public function testGetJsonVarReturnsNullFromNullBody() + { + $config = new App(); + $config->baseURL = 'http://example.com/'; + $json = null; + $request = new IncomingRequest($config, new URI(), $json, new UserAgent()); + + $this->assertNull($request->getJsonVar('myKey')); + } + + public function testgetJSONReturnsNullFromNullBody() + { + $config = new App(); + $config->baseURL = 'http://example.com/'; + $json = null; + $request = new IncomingRequest($config, new URI(), $json, new UserAgent()); + + $this->assertNull($request->getJSON()); + } + public function testCanGrabGetRawInput() { $rawstring = 'username=admin001&role=administrator&usepass=0'; From 9c9c4d2e15805ecfa0163469021ac49c13ff14f8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 09:24:11 +0900 Subject: [PATCH 207/407] fix: passing null to parameter of type string ErrorException: json_decode(): Passing null to parameter #1 ($json) of type string is deprecated --- system/HTTP/IncomingRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index ea5b968a6f79..071b18e97d00 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -520,7 +520,7 @@ public function getVar($index = null, $filter = null, $flags = null) */ public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0) { - return json_decode($this->body, $assoc, $depth, $options); + return json_decode($this->body ?? '', $assoc, $depth, $options); } /** From ed0207d29a86c00c2e1b95ad22b142c0f440c9d1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 14:43:00 +0900 Subject: [PATCH 208/407] docs: add space after `//` in sample code --- user_guide_src/source/incoming/incomingrequest.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/user_guide_src/source/incoming/incomingrequest.rst b/user_guide_src/source/incoming/incomingrequest.rst index d08bf8470f70..63a4aa5266df 100644 --- a/user_guide_src/source/incoming/incomingrequest.rst +++ b/user_guide_src/source/incoming/incomingrequest.rst @@ -149,7 +149,7 @@ data that you want or you can use "dot" notation to dig into the JSON to get dat :: - //With a request body of: + // With a request body of: { "foo": "bar", "fizz": { @@ -157,10 +157,10 @@ data that you want or you can use "dot" notation to dig into the JSON to get dat } } $data = $request->getVar('foo'); - //$data = "bar" + // $data = "bar" $data = $request->getVar('fizz.buzz'); - //$data = "baz" + // $data = "baz" If you want the result to be an associative array instead of an object, you can use ``getJsonVar()`` instead and pass @@ -169,12 +169,12 @@ correct ``CONTENT_TYPE`` header. :: - //With the same request as above + // With the same request as above $data = $request->getJsonVar('fizz'); - //$data->buzz = "baz" + // $data->buzz = "baz" $data = $request->getJsonVar('fizz', true); - //$data = ["buzz" => "baz"] + // $data = ["buzz" => "baz"] .. note:: See the documentation for ``dot_array_search()`` in the ``Array`` helper for more information on "dot" notation. From 59d1b74effaa4db8a3faaa8526186d373adce8fb Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 17:13:29 +0900 Subject: [PATCH 209/407] docs: fix about class loading Update application folder name. Remove about Legacy Support which was removed in 4.1.0. --- user_guide_src/source/installation/upgrade_4xx.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_4xx.rst b/user_guide_src/source/installation/upgrade_4xx.rst index ae6bd0188608..6b693b3101cb 100644 --- a/user_guide_src/source/installation/upgrade_4xx.rst +++ b/user_guide_src/source/installation/upgrade_4xx.rst @@ -78,10 +78,8 @@ General Adjustments - Classes are instantiated where needed, and components are managed by ``Services``. - The class loader automatically handles PSR-4 style class locating, - within the ``App`` (application) and ``CodeIgniter`` (i.e., system) top level - namespaces; with composer autoloading support, and even using educated - guessing to find your models and libraries if they are in the right - folder even though not namespaced. + within the ``App`` (**app**) and ``CodeIgniter`` (i.e., **system**) top level + namespaces; with Composer autoloading support. - You can configure the class loading to support whatever application structure you are most comfortable with, including the "HMVC" style. From c28b5d10fc3c2049daaf34f8b703a418e7b89772 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 17:19:31 +0900 Subject: [PATCH 210/407] docs: decorate file paths with ** --- .../source/installation/upgrade_4xx.rst | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_4xx.rst b/user_guide_src/source/installation/upgrade_4xx.rst index 6b693b3101cb..d4f219d4d7a3 100644 --- a/user_guide_src/source/installation/upgrade_4xx.rst +++ b/user_guide_src/source/installation/upgrade_4xx.rst @@ -39,26 +39,26 @@ General Adjustments **Application Structure** -- The ``application`` folder is renamed as ``app`` and the framework still has ``system`` folders, +- The **application** folder is renamed as **app** and the framework still has **system** folders, with the same interpretation as before. -- The framework now provides for a ``public`` folder, intended as the document root for your app. -- There is also a ``writable`` folder, to hold cache data, logs, and session data. -- The ``app`` folder looks very similar to ``application`` for CI3, with some - name changes, and some subfolders moved to the ``writable`` folder. -- There is no longer a nested ``application/core`` folder, as we have +- The framework now provides for a **public** folder, intended as the document root for your app. +- There is also a **writable** folder, to hold cache data, logs, and session data. +- The **app** folder looks very similar to **application** for CI3, with some + name changes, and some subfolders moved to the **writable** folder. +- There is no longer a nested **application/core** folder, as we have a different mechanism for extending framework components (see below). **Model, View and Controller** - CodeIgniter is based on the MVC concept. Thus, the changes on the Model, View and Controller are one of the most important things you have to handle. -- In CodeIgniter 4, models are now located in ``app/Models`` and you have to add the lines +- In CodeIgniter 4, models are now located in **app/Models** and you have to add the lines ``namespace App\Models;`` along with ``use CodeIgniter\Model;`` right after the opening php tag. The last step is to replace ``extends CI_Model`` with ``extends Model``. -- The views of CodeIgniter 4 have been moved ``to app/Views``. Furthermore, you have to change +- The views of CodeIgniter 4 have been moved to **app/Views**. Furthermore, you have to change the syntax of loading views from ``$this->load->view('directory_name/file_name')`` to ``echo view('directory_name/file_name');``. -- Controllers of CodeIgniter 4 have to be moved to ``app/Controllers;``. After that, +- Controllers of CodeIgniter 4 have to be moved to **app/Controllers**. After that, add ``namespace App\Controllers;`` after the opening php tag. Lastly, replace ``extends CI_Controller`` with ``extends BaseController``. - For more information we recommend you the following upgrade guides, which will give @@ -85,7 +85,7 @@ General Adjustments **Libraries** -- Your app classes can still go inside ``app/Libraries``, but they don't have to. +- Your app classes can still go inside **app/Libraries**, but they don't have to. - Instead of CI3's ``$this->load->library(x);`` you can now use ``$this->x = new X();``, following namespaced conventions for your component. @@ -105,18 +105,18 @@ General Adjustments **Extending the framework** -- You don't need a ``core`` folder to hold ``MY_...`` framework +- You don't need a **core** folder to hold ``MY_...`` framework component extensions or replacements. - You don't need ``MY_x`` classes inside your libraries folder to extend or replace CI4 pieces. - Make any such classes where you like, and add appropriate - service methods in ``app/Config/Services.php`` to load + service methods in **app/Config/Services.php** to load your components instead of the default ones. Upgrading Libraries =================== -- Your app classes can still go inside ``app/Libraries``, but they don’t have to. +- Your app classes can still go inside **app/Libraries**, but they don’t have to. - Instead of CI3’s ``$this->load->library(x);`` you can now use ``$this->x = new X();``, following namespaced conventions for your component. - Some libraries from CodeIgniter 3 no longer exists in Version 4. For all these From a467f3a5ea73def182494dbb0a3cc46cfa9f739e Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 18:33:50 +0900 Subject: [PATCH 211/407] docs: add settings and devkit repositories --- .../source/installation/repositories.rst | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/user_guide_src/source/installation/repositories.rst b/user_guide_src/source/installation/repositories.rst index 9e4e0abc9db9..e35de088e99e 100644 --- a/user_guide_src/source/installation/repositories.rst +++ b/user_guide_src/source/installation/repositories.rst @@ -6,15 +6,21 @@ The CodeIgniter 4 open source project has its own There are several development repositories, of interest to potential contributors: -+---------------------------------------------------------------------+--------------+-----------------------------------------------------------------+ -| Repository | Audience | Description | -+=====================================================================+==============+=================================================================+ -| CodeIgniter4 | contributors | Project codebase, including tests & user guide sources | -+---------------------------------------------------------------------+--------------+-----------------------------------------------------------------+ -| translations | developers | System message translations | -+---------------------------------------------------------------------+--------------+-----------------------------------------------------------------+ -| `coding-standard `_ | contributors | Coding style conventions & rules | -+---------------------------------------------------------------------+--------------+-----------------------------------------------------------------+ ++------------------+--------------+-----------------------------------------------------------------+ +| Repository | Audience | Description | ++==================+==============+=================================================================+ +| CodeIgniter4 | contributors | Project codebase, including tests & user guide sources | ++------------------+--------------+-----------------------------------------------------------------+ +| translations | developers | System message translations | ++------------------+--------------+-----------------------------------------------------------------+ +| coding-standard_ | contributors | Coding style conventions & rules | ++------------------+--------------+-----------------------------------------------------------------+ +| settings | developers | Settings Library for CodeIgniter 4 | ++------------------+--------------+-----------------------------------------------------------------+ +| devkit | developers | Development toolkit for CodeIgniter libraries and projects | ++------------------+--------------+-----------------------------------------------------------------+ + +.. _coding-standard: https://github.com/CodeIgniter/coding-standard There are also several deployment repositories, referenced in the installation directions. The deployment repositories are built automatically when a new version is released, and they From b83d2646c4a4f1847d59b183cd2aa0cd0da4269f Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 18:34:35 +0900 Subject: [PATCH 212/407] docs: update codeigniter.com repository --- user_guide_src/source/installation/repositories.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/installation/repositories.rst b/user_guide_src/source/installation/repositories.rst index e35de088e99e..be7e0863136f 100644 --- a/user_guide_src/source/installation/repositories.rst +++ b/user_guide_src/source/installation/repositories.rst @@ -66,7 +66,7 @@ but which showcase it or make it easier to work with! +------------------+--------------+-----------------------------------------------------------------+ | Repository | Audience | Description | +==================+==============+=================================================================+ -| website2 | developers | The codeigniter.com website, written in CodeIgniter 4 | +| website | developers | The codeigniter.com website, written in CodeIgniter 4 | +------------------+--------------+-----------------------------------------------------------------+ | playground | developers | Basic code examples in project form. Still growing. | +------------------+--------------+-----------------------------------------------------------------+ From 8c638e05c8a7515d1e987ae0fbbac1169f50b751 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 27 Nov 2021 10:55:35 +0900 Subject: [PATCH 213/407] docs: add about BaseBuilder::$tableName in changelog --- user_guide_src/source/changelogs/v4.1.6.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 093ea6ca8aec..2bb0f77f9536 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -11,6 +11,7 @@ Release Date: Not released BREAKING ======== +- Multiple table names will no longer be stored in ``BaseBuilder::$tableName`` - an empty string will be used instead. Enhancements ============ From fa1ae6802d8d5fe0981d825563395bf72a6726d6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 27 Nov 2021 11:06:36 +0900 Subject: [PATCH 214/407] docs: remove deprecated CodeIgniter\Config\Config::get() usage --- user_guide_src/source/installation/upgrade_configuration.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_configuration.rst b/user_guide_src/source/installation/upgrade_configuration.rst index 21c309cb34f2..78793439e333 100644 --- a/user_guide_src/source/installation/upgrade_configuration.rst +++ b/user_guide_src/source/installation/upgrade_configuration.rst @@ -31,8 +31,7 @@ Upgrade Guide from the CI3 config into the new CI4 config class as public class properties. 4. Now, you have to change the config fetching syntax everywhere you fetch config values. The CI3 syntax is something like ``$this->config->item('item_name');``. - You have to change this into ``config('MyConfigFile')->item_name;``. Alternatively, - you can use the object-oriented approach: ``CodeIgniter\Config\Config::get('MyConfigFile')->item_name;`` + You have to change this into ``config('MyConfigFile')->item_name;``. Code Example ============ From 748b11a6ae8b35fdcb608ccb6c8c6c45ef65b70c Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 27 Nov 2021 11:09:13 +0900 Subject: [PATCH 215/407] docs: decorate file paths with ** --- .../source/installation/upgrade_configuration.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_configuration.rst b/user_guide_src/source/installation/upgrade_configuration.rst index 78793439e333..cad74dc1e713 100644 --- a/user_guide_src/source/installation/upgrade_configuration.rst +++ b/user_guide_src/source/installation/upgrade_configuration.rst @@ -25,7 +25,7 @@ Upgrade Guide 1. You have to change the values in the default CI4 config files according to the changes in the CI3 files. The config names are pretty much the same as in CI3. 2. If you are using custom config files in your CI3 project you have to create those - files as new PHP classes in your CI4 project in ``app/Config/``. These classes + files as new PHP classes in your CI4 project in **app/Config**. These classes should be in the ``Config`` namespace and should extend ``CodeIgniter\Config\BaseConfig``. 3. Once you have created all custom config classes, you have to copy the variables from the CI3 config into the new CI4 config class as public class properties. @@ -39,7 +39,7 @@ Code Example CodeIgniter Version 3.11 ------------------------ -Path: ``application/models``:: +Path: **application/config**:: Date: Sun, 28 Nov 2021 14:00:57 +0900 Subject: [PATCH 216/407] fix: remove dependency on VENDORPATH Fixes #5401 --- system/Debug/Toolbar/Collectors/Database.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/system/Debug/Toolbar/Collectors/Database.php b/system/Debug/Toolbar/Collectors/Database.php index db13e14e920e..520ddc7c5dc6 100644 --- a/system/Debug/Toolbar/Collectors/Database.php +++ b/system/Debug/Toolbar/Collectors/Database.php @@ -141,7 +141,10 @@ public function display(): array // Clean up the file paths $traceLine['file'] = str_ireplace(APPPATH, 'APPPATH/', $traceLine['file']); $traceLine['file'] = str_ireplace(SYSTEMPATH, 'SYSTEMPATH/', $traceLine['file']); - $traceLine['file'] = str_ireplace(VENDORPATH, 'VENDORPATH/', $traceLine['file']); + if (defined('VENDORPATH')) { + // VENDORPATH is not defined unless `vendor/autoload.php` exists + $traceLine['file'] = str_ireplace(VENDORPATH, 'VENDORPATH/', $traceLine['file']); + } $traceLine['file'] = str_ireplace(ROOTPATH, 'ROOTPATH/', $traceLine['file']); if (strpos($traceLine['file'], 'SYSTEMPATH') !== false) { From 77e3e6ad8c2770dddcc7d73fa7e6bcf79695897e Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 13:43:37 +0900 Subject: [PATCH 217/407] docs: add GitHub auto-generated release note for v4.1.4 --- CHANGELOG.md | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a77c0a4d13a..820ca4069478 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,10 +72,153 @@ ## [v4.1.4](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.4) (2021-09-06) +[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.1.3...v4.1.4) + This release focuses on code style. All changes (except those noted below) are cosmetic to bring the code in line with the new [CodeIgniter Coding Standard](https://github.com/CodeIgniter/coding-standard) (based on PSR-12). -*Note: Full changelog forthcoming.* +**What's Changed** + +* Use php-cs-fixer as coding style tool by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4770 +* Convert tabs to spaces by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4771 +* Initial rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4774 +* Fixes incorrect release versions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4777 +* [CS Migration]Enable `binary_operator_spaces` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4779 +* Update rector/rector requirement from 0.11.8 to 0.11.14 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4785 +* Remove unused local variables by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4783 +* Use static lambda if a binding to `$this` is not required. by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4784 +* [CS Migration]PSR12 rules starting with "b" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4780 +* Use/Fix `preg_quote()` delimiters by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4789 +* [CS Migration]Update indentation to spaces by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4778 +* Define yoda_style rule and initially apply no_yoda style by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4786 +* Don't override `$path` parameter by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4787 +* Don't override `$value` parameter by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4788 +* Add brackets to clarify intent and avoid unwanted side-effects by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4791 +* Use constants instead of functions by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4793 +* Replace alias functions with origins by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4794 +* Use null coalescing operator by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4796 +* Remove removed `safe_mode` ini Option by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4795 +* Enable `blank_line_before_statement` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4790 +* Enable `braces` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4792 +* Ensure single space between cast and variable by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4797 +* Update rector/rector requirement from 0.11.14 to 0.11.15 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4803 +* It will fix undefined index cid error when sending emails with embedded images by @mmfarhan in https://github.com/codeigniter4/CodeIgniter4/pull/4798 +* Update rector/rector requirement from 0.11.15 to 0.11.16 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4805 +* Phpdoc param return types by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4802 +* [Rector] Apply Rector: SimplifyRegexPatternRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4806 +* Shift binary alignment to `align_single_space_minimal` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4801 +* Enable rules fixing array notations by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4808 +* PSR12: Add visibility identifiers by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4809 +* Class, trait and interface elements must be separated with one line by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4810 +* Enable `ordered_imports` by @totoprayogo1916 in https://github.com/codeigniter4/CodeIgniter4/pull/4815 +* Enable `class_definition` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4811 +* Revert Model coalesce by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/4819 +* Define remaining "c" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4817 +* Heredocs-related rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4818 +* Update rector/rector requirement from 0.11.16 to 0.11.20 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4832 +* Initial Phpdoc-related rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4820 +* Phpdoc types by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4823 +* Modernize and standardize typecasting by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4824 +* Enforce ordering and trimming of phpdoc elements by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4822 +* Define switch-related rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4835 +* Define rules starting with "L" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4838 +* Define rules on unary operators by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4837 +* Define initial "m" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4839 +* Define rules for ternary operators by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4836 +* Define last "m" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4842 +* PSR12: Enable `method_argument_space` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4840 +* Enable `method_chaining_indentation` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4841 +* Native functions and type hints should be written in correct case by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4845 +* PSR12: All instances created with `new` keyword must be followed by braces. by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4846 +* Master language constructs shall be used instead of aliases. by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4847 +* [Commands] Remove unused $minPHPVersion property at Serve command by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4852 +* Update to latest PHPStan and Rector and Rector config compat by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4861 +* [Rector] Apply Rector: RemoveExtraParametersRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4862 +* [Rector] Apply Rector: RemoveUnusedVariableAssignRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4864 +* Update rector/rector requirement from 0.11.21 to 0.11.23 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4869 +* Test classes should be marked as final and internal by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4870 +* Normalize tests to use dedicated PHPUnit assertions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4868 +* Other PHPUnit-related fixers by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4871 +* Configure rules in "d" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4872 +* Defining the trailing "p" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4873 +* Update to latest laminas-escaper ^2.8 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4878 +* Enable `echo_tag_syntax` until `error_suppression` fixers by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4879 +* Strive for stricter assertions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4874 +* Convert to explicit those implicit string variables by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4882 +* Enable `explicit_indirect_variable` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4881 +* Update rector/rector requirement from 0.11.23 to 0.11.28 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4889 +* Update to rector 0.11.29 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4893 +* Update rector/rector requirement from 0.11.29 to 0.11.32 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4895 +* Enable remaining rules in "f" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4888 +* Enable `escape_implicit_backslashes` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4880 +* Enable prohibitory rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4900 +* Enable `no_null_property_initialization` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4901 +* Update rector/rector requirement from 0.11.32 to 0.11.35 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4916 +* General phpdocs by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4917 +* Define "i" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4919 +* Define "o" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4921 +* Define "r" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4926 +* [Rector] Re-run InlineIfToExplicitIfRector on Latest Rector 0.11.36 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4930 +* Add `?` to nullable typehints by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4928 +* Define `single_**` rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4924 +* Define last "s" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4925 +* Define initial "s" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4923 +* Define remaining rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4934 +* Remove 'memory_usage' from 'displayPerformanceMetrics()' comment by @Mauricevb in https://github.com/codeigniter4/CodeIgniter4/pull/4939 +* Normalize var and return annotations by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4942 +* Fix tag casing and tag types by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4943 +* Change some phpdocs to simple comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4945 +* Remove useless code separator comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4946 +* Normalize and add file-level headers to `system/`, `tests/`, `utils/` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4949 +* [Rector] Update rector to 0.11.37, clean up config by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4954 +* Update to phpdocumentor v3.0 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4773 +* [PHPStan] Using PHPStan ^0.12.91 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4962 +* Add workflow for linting framework by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4958 +* Update pre-commit to lint code by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4960 +* Remove superfluous phpdoc tags by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4941 +* Update to phpdoc v3.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4961 +* [Rector] Apply FuncGetArgsToVariadicParamRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4963 +* Optimize Filters by @mostafakhudair in https://github.com/codeigniter4/CodeIgniter4/pull/4965 +* Update rector/rector requirement from 0.11.37 to 0.11.40 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4967 +* Fix properly the phpstan error in 0.12.93 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4970 +* [Rector] Apply MakeInheritedMethodVisibilitySameAsParentRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4966 +* Fix API repo preparation step by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4969 +* Manual cleanup of docblocks and comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4964 +* Delete `docs` directly, not `api/docs` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4976 +* [Rector] Apply Rector: RemoveDuplicatedArrayKeyRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4978 +* Update rector/rector requirement from 0.11.40 to 0.11.42 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4984 +* Update rector/rector requirement from 0.11.42 to 0.11.43 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4985 +* Remove override by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4991 +* Update rector/rector requirement from 0.11.43 to 0.11.46 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4995 +* Update rector/rector requirement from 0.11.46 to 0.11.47 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4997 +* Add SpaceAfterCommentStartFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4999 +* [Rector] Apply Rector: RemoveDoubleAssignRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5000 +* [Rector] Apply Rector dead code set list by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5007 +* Make Cookie compatible with ArrayAccess by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5004 +* Replace deprecated FILTER_SANITIZE_STRING by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5005 +* Make CookieStore compatible with IteratorAggregate::getIterator by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5010 +* Make the session handlers all compatible with SessionHandlerInterface by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5012 +* Make CITestStreamFilter compatible with php_user_filter by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5014 +* Update rector/rector requirement from 0.11.48 to 0.11.49 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5018 +* Make Time compatible with DateTime by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5022 +* Update dependabot config by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5027 +* Add `ReturnTypeWillChange` attribute to Entity by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5028 +* Replace unused Entity private method by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5029 +* Update rector/rector requirement from 0.11.49 to 0.11.52 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5033 +* Fix broken apt installation by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5037 +* Make File compatible with SplFileInfo by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5040 +* Update documentation code samples by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5039 +* PHP Copy-Paste Detector by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5031 +* Fix key casting in form_dropdown helper. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5035 +* [Rector] Apply Rector: FixClassCaseSensitivityNameRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5044 +* Bump to php-cs-fixer v3.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5045 +* Switch to official coding standard by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5038 +* 4.1.4 Ready code by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5058 + +**New Contributors** + +* @mmfarhan made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/4798 +* @Mauricevb made their first contribution in https://github.com/codeigniter4/CodeIgniter4/pull/4939 ## [v4.1.3](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.3) (2021-06-06) From 74d7159ef07cf9378b55b1953c6839da5a2de420 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 14:05:34 +0900 Subject: [PATCH 218/407] docs: remove PRs on coding style, rector, phpstan --- CHANGELOG.md | 79 ---------------------------------------------------- 1 file changed, 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 820ca4069478..7a62c588d97c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,17 +80,9 @@ This release focuses on code style. All changes (except those noted below) are c **What's Changed** * Use php-cs-fixer as coding style tool by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4770 -* Convert tabs to spaces by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4771 -* Initial rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4774 -* Fixes incorrect release versions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4777 -* [CS Migration]Enable `binary_operator_spaces` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4779 -* Update rector/rector requirement from 0.11.8 to 0.11.14 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4785 * Remove unused local variables by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4783 * Use static lambda if a binding to `$this` is not required. by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4784 -* [CS Migration]PSR12 rules starting with "b" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4780 * Use/Fix `preg_quote()` delimiters by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4789 -* [CS Migration]Update indentation to spaces by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4778 -* Define yoda_style rule and initially apply no_yoda style by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4786 * Don't override `$path` parameter by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4787 * Don't override `$value` parameter by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4788 * Add brackets to clarify intent and avoid unwanted side-effects by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4791 @@ -98,122 +90,51 @@ This release focuses on code style. All changes (except those noted below) are c * Replace alias functions with origins by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4794 * Use null coalescing operator by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4796 * Remove removed `safe_mode` ini Option by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4795 -* Enable `blank_line_before_statement` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4790 -* Enable `braces` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4792 * Ensure single space between cast and variable by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4797 -* Update rector/rector requirement from 0.11.14 to 0.11.15 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4803 * It will fix undefined index cid error when sending emails with embedded images by @mmfarhan in https://github.com/codeigniter4/CodeIgniter4/pull/4798 -* Update rector/rector requirement from 0.11.15 to 0.11.16 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4805 -* Phpdoc param return types by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4802 -* [Rector] Apply Rector: SimplifyRegexPatternRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4806 -* Shift binary alignment to `align_single_space_minimal` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4801 -* Enable rules fixing array notations by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4808 -* PSR12: Add visibility identifiers by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4809 * Class, trait and interface elements must be separated with one line by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4810 -* Enable `ordered_imports` by @totoprayogo1916 in https://github.com/codeigniter4/CodeIgniter4/pull/4815 -* Enable `class_definition` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4811 * Revert Model coalesce by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/4819 -* Define remaining "c" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4817 -* Heredocs-related rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4818 -* Update rector/rector requirement from 0.11.16 to 0.11.20 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4832 -* Initial Phpdoc-related rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4820 -* Phpdoc types by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4823 * Modernize and standardize typecasting by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4824 * Enforce ordering and trimming of phpdoc elements by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4822 -* Define switch-related rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4835 -* Define rules starting with "L" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4838 -* Define rules on unary operators by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4837 -* Define initial "m" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4839 -* Define rules for ternary operators by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4836 -* Define last "m" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4842 -* PSR12: Enable `method_argument_space` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4840 -* Enable `method_chaining_indentation` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4841 * Native functions and type hints should be written in correct case by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4845 -* PSR12: All instances created with `new` keyword must be followed by braces. by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4846 * Master language constructs shall be used instead of aliases. by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4847 * [Commands] Remove unused $minPHPVersion property at Serve command by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4852 -* Update to latest PHPStan and Rector and Rector config compat by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4861 -* [Rector] Apply Rector: RemoveExtraParametersRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4862 -* [Rector] Apply Rector: RemoveUnusedVariableAssignRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4864 -* Update rector/rector requirement from 0.11.21 to 0.11.23 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4869 * Test classes should be marked as final and internal by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4870 * Normalize tests to use dedicated PHPUnit assertions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4868 -* Other PHPUnit-related fixers by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4871 -* Configure rules in "d" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4872 -* Defining the trailing "p" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4873 * Update to latest laminas-escaper ^2.8 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4878 -* Enable `echo_tag_syntax` until `error_suppression` fixers by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4879 * Strive for stricter assertions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4874 * Convert to explicit those implicit string variables by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4882 -* Enable `explicit_indirect_variable` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4881 -* Update rector/rector requirement from 0.11.23 to 0.11.28 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4889 -* Update to rector 0.11.29 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4893 -* Update rector/rector requirement from 0.11.29 to 0.11.32 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4895 -* Enable remaining rules in "f" by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4888 -* Enable `escape_implicit_backslashes` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4880 -* Enable prohibitory rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4900 -* Enable `no_null_property_initialization` fixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4901 -* Update rector/rector requirement from 0.11.32 to 0.11.35 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4916 * General phpdocs by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4917 -* Define "i" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4919 -* Define "o" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4921 -* Define "r" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4926 -* [Rector] Re-run InlineIfToExplicitIfRector on Latest Rector 0.11.36 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4930 * Add `?` to nullable typehints by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4928 -* Define `single_**` rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4924 -* Define last "s" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4925 -* Define initial "s" rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4923 -* Define remaining rules by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4934 * Remove 'memory_usage' from 'displayPerformanceMetrics()' comment by @Mauricevb in https://github.com/codeigniter4/CodeIgniter4/pull/4939 * Normalize var and return annotations by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4942 * Fix tag casing and tag types by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4943 * Change some phpdocs to simple comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4945 * Remove useless code separator comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4946 * Normalize and add file-level headers to `system/`, `tests/`, `utils/` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4949 -* [Rector] Update rector to 0.11.37, clean up config by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4954 * Update to phpdocumentor v3.0 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4773 -* [PHPStan] Using PHPStan ^0.12.91 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4962 * Add workflow for linting framework by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4958 * Update pre-commit to lint code by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4960 * Remove superfluous phpdoc tags by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4941 -* Update to phpdoc v3.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4961 -* [Rector] Apply FuncGetArgsToVariadicParamRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4963 * Optimize Filters by @mostafakhudair in https://github.com/codeigniter4/CodeIgniter4/pull/4965 -* Update rector/rector requirement from 0.11.37 to 0.11.40 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4967 * Fix properly the phpstan error in 0.12.93 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4970 -* [Rector] Apply MakeInheritedMethodVisibilitySameAsParentRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4966 * Fix API repo preparation step by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4969 * Manual cleanup of docblocks and comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4964 * Delete `docs` directly, not `api/docs` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4976 -* [Rector] Apply Rector: RemoveDuplicatedArrayKeyRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4978 -* Update rector/rector requirement from 0.11.40 to 0.11.42 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4984 -* Update rector/rector requirement from 0.11.42 to 0.11.43 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4985 -* Remove override by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4991 -* Update rector/rector requirement from 0.11.43 to 0.11.46 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4995 -* Update rector/rector requirement from 0.11.46 to 0.11.47 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/4997 -* Add SpaceAfterCommentStartFixer by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4999 -* [Rector] Apply Rector: RemoveDoubleAssignRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5000 -* [Rector] Apply Rector dead code set list by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5007 * Make Cookie compatible with ArrayAccess by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5004 * Replace deprecated FILTER_SANITIZE_STRING by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5005 * Make CookieStore compatible with IteratorAggregate::getIterator by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5010 * Make the session handlers all compatible with SessionHandlerInterface by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5012 * Make CITestStreamFilter compatible with php_user_filter by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5014 -* Update rector/rector requirement from 0.11.48 to 0.11.49 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5018 * Make Time compatible with DateTime by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5022 -* Update dependabot config by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5027 * Add `ReturnTypeWillChange` attribute to Entity by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5028 * Replace unused Entity private method by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5029 -* Update rector/rector requirement from 0.11.49 to 0.11.52 by @dependabot in https://github.com/codeigniter4/CodeIgniter4/pull/5033 * Fix broken apt installation by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5037 * Make File compatible with SplFileInfo by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5040 * Update documentation code samples by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5039 * PHP Copy-Paste Detector by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5031 * Fix key casting in form_dropdown helper. by @sfadschm in https://github.com/codeigniter4/CodeIgniter4/pull/5035 -* [Rector] Apply Rector: FixClassCaseSensitivityNameRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/5044 -* Bump to php-cs-fixer v3.1 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5045 * Switch to official coding standard by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5038 -* 4.1.4 Ready code by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5058 **New Contributors** From b89cf02a558c54de202f215ffda1f8fa848f990a Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 14:19:12 +0900 Subject: [PATCH 219/407] docs: remove PRs on coding style, github/workflow --- CHANGELOG.md | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a62c588d97c..9d2a65357cab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,41 +86,17 @@ This release focuses on code style. All changes (except those noted below) are c * Don't override `$path` parameter by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4787 * Don't override `$value` parameter by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4788 * Add brackets to clarify intent and avoid unwanted side-effects by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4791 -* Use constants instead of functions by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4793 -* Replace alias functions with origins by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4794 -* Use null coalescing operator by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4796 * Remove removed `safe_mode` ini Option by @jeromegamez in https://github.com/codeigniter4/CodeIgniter4/pull/4795 -* Ensure single space between cast and variable by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4797 * It will fix undefined index cid error when sending emails with embedded images by @mmfarhan in https://github.com/codeigniter4/CodeIgniter4/pull/4798 -* Class, trait and interface elements must be separated with one line by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4810 * Revert Model coalesce by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/4819 -* Modernize and standardize typecasting by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4824 -* Enforce ordering and trimming of phpdoc elements by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4822 -* Native functions and type hints should be written in correct case by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4845 * Master language constructs shall be used instead of aliases. by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4847 * [Commands] Remove unused $minPHPVersion property at Serve command by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4852 -* Test classes should be marked as final and internal by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4870 -* Normalize tests to use dedicated PHPUnit assertions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4868 * Update to latest laminas-escaper ^2.8 by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/4878 -* Strive for stricter assertions by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4874 -* Convert to explicit those implicit string variables by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4882 -* General phpdocs by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4917 -* Add `?` to nullable typehints by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4928 * Remove 'memory_usage' from 'displayPerformanceMetrics()' comment by @Mauricevb in https://github.com/codeigniter4/CodeIgniter4/pull/4939 -* Normalize var and return annotations by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4942 -* Fix tag casing and tag types by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4943 -* Change some phpdocs to simple comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4945 * Remove useless code separator comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4946 -* Normalize and add file-level headers to `system/`, `tests/`, `utils/` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4949 -* Update to phpdocumentor v3.0 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4773 -* Add workflow for linting framework by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4958 -* Update pre-commit to lint code by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4960 -* Remove superfluous phpdoc tags by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4941 * Optimize Filters by @mostafakhudair in https://github.com/codeigniter4/CodeIgniter4/pull/4965 * Fix properly the phpstan error in 0.12.93 by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4970 -* Fix API repo preparation step by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4969 * Manual cleanup of docblocks and comments by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4964 -* Delete `docs` directly, not `api/docs` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/4976 * Make Cookie compatible with ArrayAccess by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5004 * Replace deprecated FILTER_SANITIZE_STRING by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5005 * Make CookieStore compatible with IteratorAggregate::getIterator by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5010 @@ -129,7 +105,6 @@ This release focuses on code style. All changes (except those noted below) are c * Make Time compatible with DateTime by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5022 * Add `ReturnTypeWillChange` attribute to Entity by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5028 * Replace unused Entity private method by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5029 -* Fix broken apt installation by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5037 * Make File compatible with SplFileInfo by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5040 * Update documentation code samples by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/5039 * PHP Copy-Paste Detector by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/5031 From 854fefbacfe930734d6c6ebe02fff927121f9546 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 09:21:06 +0900 Subject: [PATCH 220/407] docs: fix 404 link --- user_guide_src/source/installation/upgrade_emails.rst | 2 +- user_guide_src/source/libraries/email.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/installation/upgrade_emails.rst b/user_guide_src/source/installation/upgrade_emails.rst index 41778027dc30..d64a6bb2afea 100644 --- a/user_guide_src/source/installation/upgrade_emails.rst +++ b/user_guide_src/source/installation/upgrade_emails.rst @@ -22,7 +22,7 @@ Upgrade Guide 1. Within your class change the ``$this->load->library('email');`` to ``$email = service('email');``. 2. From that on you have to replace every line starting with ``$this->email`` to ``$email``. 3. The methods in the Email class are named slightly different. All methods, except for ``send()``, ``attach()``, ``printDebugger()`` and ``clear()`` have a ``set`` as prefix followed by the previous method name. ``bcc()`` is now ``setBcc()`` and so on. -4. The config attributes in ``app/Config/Email.php`` have changed. You should have a look at the `Email Class Documentation `__ to have a list of the new attributes. +4. The config attributes in **app/Config/Email.php** have changed. You should have a look at the :ref:`setting-email-preferences` to have a list of the new attributes. Code Example ============ diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index f57f3cf93d8d..a10b3d9bf6ca 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -44,6 +44,8 @@ Here is a basic example demonstrating how you might send email:: $email->send(); +.. _setting-email-preferences: + Setting Email Preferences ========================= From 66c588335a594346fb822e167b5e7b1f3ef1a20c Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 09:44:44 +0900 Subject: [PATCH 221/407] docs: decorate keywords in source code with '``' --- user_guide_src/source/incoming/restful.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/user_guide_src/source/incoming/restful.rst b/user_guide_src/source/incoming/restful.rst index bb2f9d8ad1bb..2ed7ed4607fe 100644 --- a/user_guide_src/source/incoming/restful.rst +++ b/user_guide_src/source/incoming/restful.rst @@ -47,7 +47,7 @@ name:: .. important:: The routes are matched in the order they are specified, so if you have a resource photos above a get 'photos/poll' the show action's route for the resource line will be matched before the get line. To fix this, move the get line above the resource line so that it is matched first. The second parameter accepts an array of options that can be used to modify the routes that are generated. While these -routes are geared toward API-usage, where more methods are allowed, you can pass in the 'websafe' option to have it +routes are geared toward API-usage, where more methods are allowed, you can pass in the ``websafe`` option to have it generate update and delete methods that work with HTML forms:: $routes->resource('photos', ['websafe' => 1]); @@ -90,15 +90,15 @@ Otherwise you can remove unused routes with the ``except`` option. This option r $routes->resource('photos', ['except' => 'new,edit']); -Valid methods are: index, show, create, update, new, edit and delete. +Valid methods are: ``index``, ``show``, ``create``, ``update``, ``new``, ``edit`` and ``delete``. ResourceController ============================================================ -The `ResourceController` provides a convenient starting point for your RESTful API, +The ``ResourceController`` provides a convenient starting point for your RESTful API, with methods that correspond to the resource routes above. -Extend it, over-riding the `modelName` and `format` properties, and then +Extend it, over-riding the ``modelName`` and ``format`` properties, and then implement those methods that you want handled.:: presenter('photos', ['except' => 'new,edit']); -Valid methods are: index, show, new, create, edit, update, remove and delete. +Valid methods are: ``index``, ``show``, ``new``, ``create``, ``edit``, ``update``, ``remove`` and ``delete``. ResourcePresenter ============================================================ -The `ResourcePresenter` provides a convenient starting point for presenting views +The ``ResourcePresenter`` provides a convenient starting point for presenting views of your resource, and processing data from forms in those views, with methods that align to the resource routes above. -Extend it, over-riding the `modelName` property, and then +Extend it, over-riding the ``modelName`` property, and then implement those methods that you want handled.:: Date: Tue, 30 Nov 2021 09:45:42 +0900 Subject: [PATCH 222/407] docs: replace segment with (:segment) Make it more precise. --- user_guide_src/source/incoming/restful.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/incoming/restful.rst b/user_guide_src/source/incoming/restful.rst index 2ed7ed4607fe..9ac3ed1292c4 100644 --- a/user_guide_src/source/incoming/restful.rst +++ b/user_guide_src/source/incoming/restful.rst @@ -70,7 +70,7 @@ the controller that should be used:: Change the Placeholder Used --------------------------- -By default, the ``segment`` placeholder is used when a resource ID is needed. You can change this by passing +By default, the ``(:segment)`` placeholder is used when a resource ID is needed. You can change this by passing in the ``placeholder`` option with the new string to use:: $routes->resource('photos', ['placeholder' => '(:num)']); @@ -175,7 +175,7 @@ the controller that should be used:: Change the Placeholder Used --------------------------- -By default, the ``segment`` placeholder is used when a resource ID is needed. You can change this by passing +By default, the ``(:segment)`` placeholder is used when a resource ID is needed. You can change this by passing in the ``placeholder`` option with the new string to use:: $routes->presenter('photos', ['placeholder' => '(:num)']); From 36ae946804044bf4b46f4a55a9fac9c3890af452 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 09:47:50 +0900 Subject: [PATCH 223/407] docs: improve explanation for except option --- user_guide_src/source/incoming/restful.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/incoming/restful.rst b/user_guide_src/source/incoming/restful.rst index 9ac3ed1292c4..8992221590a0 100644 --- a/user_guide_src/source/incoming/restful.rst +++ b/user_guide_src/source/incoming/restful.rst @@ -81,12 +81,12 @@ in the ``placeholder`` option with the new string to use:: Limit the Routes Made --------------------- -You can restrict the routes generated with the ``only`` option. This should be an array or comma separated list of method names that should +You can restrict the routes generated with the ``only`` option. This should be **an array** or **comma separated list** of method names that should be created. Only routes that match one of these methods will be created. The rest will be ignored:: $routes->resource('photos', ['only' => ['index', 'show']]); -Otherwise you can remove unused routes with the ``except`` option. This option run after ``only``:: +Otherwise you can remove unused routes with the ``except`` option. This should also be **an array** or **comma separated list** of method names. This option run after ``only``:: $routes->resource('photos', ['except' => 'new,edit']); @@ -186,12 +186,12 @@ in the ``placeholder`` option with the new string to use:: Limit the Routes Made --------------------- -You can restrict the routes generated with the ``only`` option. This should be an array or comma separated list of method names that should +You can restrict the routes generated with the ``only`` option. This should be **an array** or **comma separated list** of method names that should be created. Only routes that match one of these methods will be created. The rest will be ignored:: $routes->presenter('photos', ['only' => ['index', 'show']]); -Otherwise you can remove unused routes with the ``except`` option. This option run after ``only``:: +Otherwise you can remove unused routes with the ``except`` option. This should also be **an array** or **comma separated list** of method names. This option run after ``only``:: $routes->presenter('photos', ['except' => 'new,edit']); From c15b930b9d167a6ea1166b1cfe9081b047f680c7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:23:49 +0900 Subject: [PATCH 224/407] docs: fix sample code It seems 3.x and 4.x sample code are not the same. --- user_guide_src/source/installation/upgrade_routing.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_routing.rst b/user_guide_src/source/installation/upgrade_routing.rst index bd840b06a82c..8743cc7816f1 100644 --- a/user_guide_src/source/installation/upgrade_routing.rst +++ b/user_guide_src/source/installation/upgrade_routing.rst @@ -64,12 +64,12 @@ Path: ``app/Config/Routes.php``:: ... - $routes->add('posts', 'Posts::index'); + $routes->add('posts/index', 'Posts::index'); $routes->add('teams/create', 'Teams::create'); - $routes->add('teams/edit/(:any)', 'Teams::edit/$1'); + $routes->add('teams/update', 'Teams::update'); $routes->add('posts/create', 'Posts::create'); - $routes->add('posts/edit/(:any)', 'Posts::edit/$1'); + $routes->add('posts/update', 'Posts::update'); $routes->add('drivers/create', 'Drivers::create'); - $routes->add('drivers/edit/(:any)', 'Drivers::edit/$1'); + $routes->add('drivers/update', 'Drivers::update'); $routes->add('posts/(:any)', 'Posts::view/$1'); From 59660589ee1ede69770c4ab6eec31f00cd4f3b49 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:24:54 +0900 Subject: [PATCH 225/407] docs: decorate file paths with ** --- user_guide_src/source/installation/upgrade_routing.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_routing.rst b/user_guide_src/source/installation/upgrade_routing.rst index 8743cc7816f1..b99dd676bf5a 100644 --- a/user_guide_src/source/installation/upgrade_routing.rst +++ b/user_guide_src/source/installation/upgrade_routing.rst @@ -19,7 +19,7 @@ What has been changed Upgrade Guide ============= -1. You have to change the syntax of each routing line and append it in ``app/Config/Routes.php``. For example: +1. You have to change the syntax of each routing line and append it in **app/Config/Routes.php**. For example: - ``$route['journals'] = 'blogs';`` to ``$routes->add('journals', 'App\Blogs');`` this would map to the ``index()`` method in the "Blogs" class. - ``$route['product/(:any)'] = 'catalog/product_lookup';`` to ``$routes->add('product/(:any)', 'Catalog::productLookup');`` @@ -30,7 +30,7 @@ Code Example CodeIgniter Version 3.11 ------------------------ -Path: ``application/config/routes.php``:: +Path: **application/config/routes.php**:: Date: Tue, 30 Nov 2021 10:25:34 +0900 Subject: [PATCH 226/407] docs: fix indentation of the list and the explanation --- user_guide_src/source/installation/upgrade_routing.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_routing.rst b/user_guide_src/source/installation/upgrade_routing.rst index b99dd676bf5a..5ea14f16e74d 100644 --- a/user_guide_src/source/installation/upgrade_routing.rst +++ b/user_guide_src/source/installation/upgrade_routing.rst @@ -21,9 +21,9 @@ Upgrade Guide ============= 1. You have to change the syntax of each routing line and append it in **app/Config/Routes.php**. For example: -- ``$route['journals'] = 'blogs';`` to ``$routes->add('journals', 'App\Blogs');`` this would map to the ``index()`` method in the "Blogs" class. -- ``$route['product/(:any)'] = 'catalog/product_lookup';`` to ``$routes->add('product/(:any)', 'Catalog::productLookup');`` -- ``$route['login/(.+)'] = 'auth/login/$1';`` to ``$routes->add('login/(.+)', 'Auth::login/$1');`` + - ``$route['journals'] = 'blogs';`` to ``$routes->add('journals', 'Blogs::index');``. This would map to the ``index()`` method in the ``Blogs`` controller. + - ``$route['product/(:any)'] = 'catalog/product_lookup';`` to ``$routes->add('product/(:any)', 'Catalog::productLookup');`` + - ``$route['login/(.+)'] = 'auth/login/$1';`` to ``$routes->add('login/(.+)', 'Auth::login/$1');`` Code Example ============ From c9c8748770a062f59d6b54ff68b960400b0d4ced Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:46:19 +0900 Subject: [PATCH 227/407] docs: fix coding style of sample code --- user_guide_src/source/libraries/uploaded_files.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index 094eacc1eafa..c0284f221d79 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -110,7 +110,7 @@ In controller:: foreach($imagefile['images'] as $img) { if ($img->isValid() && ! $img->hasMoved()) { $newName = $img->getRandomName(); - $img->move(WRITEPATH.'uploads', $newName); + $img->move(WRITEPATH . 'uploads', $newName); } } } @@ -153,7 +153,7 @@ Verify A File You can check that a file was actually uploaded via HTTP with no errors by calling the ``isValid()`` method:: if (! $file->isValid()) { - throw new \RuntimeException($file->getErrorString().'('.$file->getError().')'); + throw new \RuntimeException($file->getErrorString() . '(' . $file->getError() . ')'); } As seen in this example, if a file had an upload error, you can retrieve the error code (an integer) and the error @@ -216,12 +216,12 @@ Moving Files Each file can be moved to its new location with the aptly named ``move()`` method. This takes the directory to move the file to as the first parameter:: - $file->move(WRITEPATH.'uploads'); + $file->move(WRITEPATH . 'uploads'); By default, the original filename was used. You can specify a new filename by passing it as the second parameter:: $newName = $file->getRandomName(); - $file->move(WRITEPATH.'uploads', $newName); + $file->move(WRITEPATH . 'uploads', $newName); Once the file has been removed the temporary file is deleted. You can check if a file has been moved already with the ``hasMoved()`` method, which returns a boolean:: From 7422d99f97507a01af43a010baa0cbf2863d2de5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:46:49 +0900 Subject: [PATCH 228/407] docs: fix typo --- user_guide_src/source/libraries/uploaded_files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index c0284f221d79..b15185506e81 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -117,7 +117,7 @@ In controller:: where the **images** is a loop from the form field name -If there are multiple files with the same name you can use ``getFile()`` ro retrieve every file individually:: +If there are multiple files with the same name you can use ``getFile()`` to retrieve every file individually:: In controller:: $file1 = $this->request->getFile('images.0'); From 34340569a9866f3d52cb1338eff0b6afd01f4f1b Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:47:24 +0900 Subject: [PATCH 229/407] docs: decorate words in code with '``' --- user_guide_src/source/libraries/uploaded_files.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index b15185506e81..c0e4b27baf9a 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -160,7 +160,7 @@ As seen in this example, if a file had an upload error, you can retrieve the err message with the ``getError()`` and ``getErrorString()`` methods. The following errors can be discovered through this method: -* The file exceeds your upload_max_filesize ini directive. +* The file exceeds your ``upload_max_filesize`` ini directive. * The file exceeds the upload limit defined in your form. * The file was only partially uploaded. * No file was uploaded. @@ -255,7 +255,7 @@ passing it as the second parameter:: $path = $this->request->getFile('userfile')->store('head_img/', 'user_name.jpg'); -Moving an uploaded file can fail, with an HTTPException, under several circumstances: +Moving an uploaded file can fail, with an ``HTTPException``, under several circumstances: - the file has already been moved - the file did not upload successfully From a177ea33d1d8c70869053168d85afdc88ad2ac6e Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:48:41 +0900 Subject: [PATCH 230/407] docs: make it a single sentence --- user_guide_src/source/libraries/uploaded_files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index c0e4b27baf9a..d48bc02a9dcb 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -138,7 +138,7 @@ In controller:: $file1 = $this->request->getFile('my-form.details.avatars.0'); $file2 = $this->request->getFile('my-form.details.avatars.1'); -.. note:: using ``getFiles()`` is more appropriate +.. note:: Using ``getFiles()`` is more appropriate. ===================== Working With the File From 80689ddc4cb3b72179f9cee57ef12ec619b3e13d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:49:22 +0900 Subject: [PATCH 231/407] docs: decroate file paths with ** --- user_guide_src/source/libraries/uploaded_files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index d48bc02a9dcb..e1734165c6e5 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -245,7 +245,7 @@ With the simplest usage, a single file might be submitted like:: -By default, upload files are saved in writable/uploads directory. The YYYYMMDD folder +By default, upload files are saved in **writable/uploads** directory. The **YYYYMMDD** folder and random file name will be created. Returns a file path:: $path = $this->request->getFile('userfile')->store(); From 49a07f0ccb46e313e08b8cb6c53de00e0df537e3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 10:49:48 +0900 Subject: [PATCH 232/407] docs: make warning for security matter --- user_guide_src/source/libraries/uploaded_files.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index e1734165c6e5..d4ecc9d34867 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -196,11 +196,12 @@ Other File Info **getClientExtension()** -Returns the original file extension, based on the file name that was uploaded. This is NOT a trusted source. For a -trusted version, use ``guessExtension()`` instead:: +Returns the original file extension, based on the file name that was uploaded:: $ext = $file->getClientExtension(); +.. warning:: This is NOT a trusted source. For a trusted version, use ``guessExtension()`` instead. + **getClientMimeType()** Returns the mime type (mime type) of the file as provided by the client. This is NOT a trusted value. For a trusted From 352a67166ad6e592c70c17c64626e41e075ccad0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 12:13:47 +0900 Subject: [PATCH 233/407] docs: add file upload sample code like CI3 --- .../source/libraries/uploaded_files.rst | 176 ++++++++++++++++-- 1 file changed, 163 insertions(+), 13 deletions(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index d4ecc9d34867..1f60167f9189 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -1,6 +1,6 @@ -*************************** +########################### Working with Uploaded Files -*************************** +########################### CodeIgniter makes working with files uploaded through a form much simpler and more secure than using PHP's ``$_FILES`` array directly. This extends the :doc:`File class ` and thus gains all of the features of that class. @@ -12,12 +12,162 @@ array directly. This extends the :doc:`File class ` and thus g :local: :depth: 2 -=============== +*********** +The Process +*********** + +Uploading a file involves the following general process: + +- An upload form is displayed, allowing a user to select a file and + upload it. +- When the form is submitted, the file is uploaded to the destination + you specify. +- Along the way, the file is validated to make sure it is allowed to be + uploaded based on the preferences you set. +- Once uploaded, the user will be shown a success message. + +To demonstrate this process here is brief tutorial. Afterward you'll +find reference information. + +Creating the Upload Form +======================== + +Using a text editor, create a form called upload_form.php. In it, place +this code and save it to your **app/Views/** directory:: + + + + + Upload Form + + + + +
  • + + + + + + +

    + + + + + + + + +You'll notice we are using a form helper to create the opening form tag. +File uploads require a multipart form, so the helper creates the proper +syntax for you. You'll also notice we have an ``$errors`` variable. This is +so we can show error messages in the event the user does something +wrong. + +The Success Page +================ + +Using a text editor, create a form called upload_success.php. In it, +place this code and save it to your **app/Views/** directory:: + + + + + Upload Form + + + +

    Your file was successfully uploaded!

    + +
      +
    • name: getBasename() ?>
    • +
    • size: getSizeByUnit('kb') ?> KB
    • +
    • extension: guessExtension() ?>
    • +
    + +

    + + + + +The Controller +============== + +Using a text editor, create a controller called Upload.php. In it, place +this code and save it to your **app/Controllers/** directory:: + + []]); + } + + public function upload() + { + $validationRule = [ + 'userfile' => [ + 'label' => 'Image File', + 'rules' => 'uploaded[userfile]' + . '|is_image[userfile]' + . '|mime_in[userfile,image/jpg,image/jpeg,image/gif,image/png,image/webp]' + . '|max_size[userfile,100]' + . '|max_dims[userfile,1024,768]', + ], + ]; + if (! $this->validate($validationRule)) { + $data = ['errors' => $this->validator->getErrors()]; + + return view('upload_form', $data); + } + + $img = $this->request->getFile('userfile'); + + if (! $img->hasMoved()) { + $filepath = WRITEPATH . 'uploads/' . $img->store(); + + $data = ['uploaded_flleinfo' => new File($filepath)]; + + return view('upload_success', $data); + } else { + $data = ['errors' => 'The file has already been moved.']; + + return view('upload_form', $data); + } + } + } + +The Upload Directory +==================== + +The uploaded files are stored in the **writable/uploads/** directory. + +Try it! +======= + +To try your form, visit your site using a URL similar to this one:: + + example.com/index.php/upload/ + +You should see an upload form. Try uploading an image file (either a +**jpg**, **gif**, **png**, or **webp**). If the path in your controller is correct it should +work. + +*************** Accessing Files -=============== +*************** All Files ----------- +========= When you upload files they can be accessed natively in PHP through the ``$_FILES`` superglobal. This array has some major shortcomings when working with multiple files uploaded at once, and has potential security flaws many developers @@ -72,7 +222,7 @@ In this case, the returned array of files would be more like:: ] Single File ------------ +=========== If you just need to access a single file, you can use ``getFile()`` to retrieve the file instance directly. This will return an instance of ``CodeIgniter\HTTP\Files\UploadedFile``: @@ -140,15 +290,15 @@ In controller:: .. note:: Using ``getFiles()`` is more appropriate. -===================== +********************* Working With the File -===================== +********************* Once you've retrieved the UploadedFile instance, you can retrieve information about the file in safe ways, as well as move the file to a new location. Verify A File -------------- +============= You can check that a file was actually uploaded via HTTP with no errors by calling the ``isValid()`` method:: @@ -169,7 +319,7 @@ this method: * File upload was stopped by a PHP extension. File Names ----------- +========== **getName()** @@ -192,7 +342,7 @@ To get the full path of the temp file that was created during the upload, you ca $tempfile = $file->getTempName(); Other File Info ---------------- +=============== **getClientExtension()** @@ -212,7 +362,7 @@ version, use ``getMimeType()`` instead:: echo $type; // image/png Moving Files ------------- +============ Each file can be moved to its new location with the aptly named ``move()`` method. This takes the directory to move the file to as the first parameter:: @@ -238,7 +388,7 @@ Moving an uploaded file can fail, with an HTTPException, under several circumsta - the file move operation fails (e.g., improper permissions) Store Files ------------- +=========== Each file can be moved to its new location with the aptly named ``store()`` method. From f646b9c3ee2c3ce6d34ed99a7b9a703c1c9ebbd5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 13:03:40 +0900 Subject: [PATCH 234/407] docs: update sample code coding style --- user_guide_src/source/libraries/files.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index 76b2e8a6acd8..cf46d8ceb9b5 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -96,17 +96,17 @@ Moving Files Each file can be moved to its new location with the aptly named ``move()`` method. This takes the directory to move the file to as the first parameter:: - $file->move(WRITEPATH.'uploads'); + $file->move(WRITEPATH . 'uploads'); By default, the original filename was used. You can specify a new filename by passing it as the second parameter:: $newName = $file->getRandomName(); - $file->move(WRITEPATH.'uploads', $newName); + $file->move(WRITEPATH . 'uploads', $newName); The move() method returns a new File instance that for the relocated file, so you must capture the result if the resulting location is needed:: - $file = $file->move(WRITEPATH.'uploads'); + $file = $file->move(WRITEPATH . 'uploads'); **************** File Collections @@ -136,8 +136,7 @@ When your collection is complete, you can use ``get()`` to retrieve the final li echo 'My files: ' . implode(PHP_EOL, $files->get()); echo 'I have ' . count($files) . ' files!'; - foreach ($files as $file) - { + foreach ($files as $file) { echo 'Moving ' . $file->getBasename() . ', ' . $file->getSizeByUnit('mb'); $file->move(WRITABLE . $file->getRandomName()); } From afdc97646f6d3e6073d288aca73cdee2ea3ab730 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 13:06:09 +0900 Subject: [PATCH 235/407] docs: decorate method/variable with '``' --- user_guide_src/source/libraries/files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index cf46d8ceb9b5..04bd317356e2 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -149,7 +149,7 @@ Starting a Collection **__construct(string[] $files = [])** The constructor accepts an optional array of file paths to use as the initial collection. These are passed to -**add()** so any files supplied by child classes in the **$files** will remain. +``add()`` so any files supplied by child classes in the ``$files`` will remain. **define()** From 78cf411974a2b074faf5d91cec2a29fa16868ca1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 13:06:54 +0900 Subject: [PATCH 236/407] docs: add / to separate methods --- user_guide_src/source/libraries/files.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index 04bd317356e2..6734e98d5fda 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -180,17 +180,17 @@ Inputting Files Adds all files indicated by the path or array of paths. If the path resolves to a directory then ``$recursive`` will include sub-directories. -**addFile(string $file)** +**addFile(string $file)** / **addFiles(array $files)** Adds the file or files to the current list of input files. Files are absolute paths to actual files. -**removeFile(string $file)** +**removeFile(string $file)** / **removeFiles(array $files)** Removes the file or files from the current list of input files. -**addDirectory(string $directory, bool $recursive = false)** +**addDirectory(string $directory, bool $recursive = false)** / **addDirectories(array $directories, bool $recursive = false)** Adds all files from the directory or directories, optionally recursing into sub-directories. Directories are @@ -199,7 +199,7 @@ absolute paths to actual directories. Filtering Files =============== -**removePattern(string $pattern, string $scope = null)** +**removePattern(string $pattern, string $scope = null)** / **retainPattern(string $pattern, string $scope = null)** Filters the current file list through the pattern (and optional scope), removing or retaining matched From fbabefa946ae4899e90e9c0b0a92eca49861fb9f Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 13:51:27 +0900 Subject: [PATCH 237/407] docs: add esc() to views --- user_guide_src/source/libraries/uploaded_files.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index 1f60167f9189..961823036e60 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -43,7 +43,7 @@ this code and save it to your **app/Views/** directory:: -
  • +
  • @@ -81,9 +81,9 @@ place this code and save it to your **app/Views/** directory::

    Your file was successfully uploaded!

      -
    • name: getBasename() ?>
    • -
    • size: getSizeByUnit('kb') ?> KB
    • -
    • extension: guessExtension() ?>
    • +
    • name: getBasename()) ?>
    • +
    • size: getSizeByUnit('kb')) ?> KB
    • +
    • extension: guessExtension()) ?>

    From 4d8266dfb9d7ccb3611b09d305dc8054aeab07b7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 14:57:25 +0900 Subject: [PATCH 238/407] docs: add esc() to views It is not good practice to show variables without escaping --- user_guide_src/source/outgoing/views.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/user_guide_src/source/outgoing/views.rst b/user_guide_src/source/outgoing/views.rst index 533e3c9bead5..8b8f21efccaf 100644 --- a/user_guide_src/source/outgoing/views.rst +++ b/user_guide_src/source/outgoing/views.rst @@ -163,10 +163,10 @@ Now open your view file and change the text to variables that correspond to the - <?= $title ?> + <?= esc($title) ?> -

    +

    @@ -220,17 +220,17 @@ Now open your view file and create a loop:: - <?= $title ?> + <?= esc($title) ?> -

    +

    My Todo List

      -
    • +
    From 2fb74d0ab70215811a8bbac3deb4eacaf8545066 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 14:58:27 +0900 Subject: [PATCH 239/407] docs: fix coding style --- user_guide_src/source/outgoing/views.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/outgoing/views.rst b/user_guide_src/source/outgoing/views.rst index 8b8f21efccaf..5cc77d05a3a4 100644 --- a/user_guide_src/source/outgoing/views.rst +++ b/user_guide_src/source/outgoing/views.rst @@ -228,11 +228,11 @@ Now open your view file and create a loop::

    My Todo List

      - +
    • - +
    From 69a6563d52229ddfa8fd2e2a0f833bd2d945d734 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 15:03:24 +0900 Subject: [PATCH 240/407] docs: fix coding style remove unneeded ; remove space before : --- user_guide_src/source/installation/upgrade_views.rst | 2 +- user_guide_src/source/libraries/pagination.rst | 4 ++-- user_guide_src/source/libraries/validation.rst | 2 +- user_guide_src/source/outgoing/alternative_php.rst | 8 ++++---- user_guide_src/source/tutorial/news_section.rst | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_views.rst b/user_guide_src/source/installation/upgrade_views.rst index 554a0a83ffc3..829b84a47e5f 100644 --- a/user_guide_src/source/installation/upgrade_views.rst +++ b/user_guide_src/source/installation/upgrade_views.rst @@ -70,7 +70,7 @@ Path: ``app/Views``::
    • - +
    diff --git a/user_guide_src/source/libraries/pagination.rst b/user_guide_src/source/libraries/pagination.rst index 8b47ac046d1f..b665300749e2 100644 --- a/user_guide_src/source/libraries/pagination.rst +++ b/user_guide_src/source/libraries/pagination.rst @@ -250,7 +250,7 @@ usefulness. It is easiest to demonstrate creating a new view by showing you the - links() as $link) : ?> + links() as $link): ?>
  • > @@ -328,7 +328,7 @@ See following an example with these changes::
  • - links() as $link) : ?> + links() as $link): ?>
  • > diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index 27691f084a55..468f05e5a41f 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -607,7 +607,7 @@ a new view at **/app/Views/_errors_list.php**::

    View article

    - + From 6ca2cfe78cfdf6beb83119ec68d41fa96a9745e6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 15:05:21 +0900 Subject: [PATCH 241/407] docs: fix coding style Align = position --- user_guide_src/source/installation/upgrade_migrations.rst | 8 ++++---- user_guide_src/source/installation/upgrade_models.rst | 6 +++--- user_guide_src/source/installation/upgrade_pagination.rst | 8 ++++---- .../source/installation/upgrade_view_parser.rst | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_migrations.rst b/user_guide_src/source/installation/upgrade_migrations.rst index 10a75bf23f2d..fc65ea2aa8d3 100644 --- a/user_guide_src/source/installation/upgrade_migrations.rst +++ b/user_guide_src/source/installation/upgrade_migrations.rst @@ -63,13 +63,13 @@ Path: ``application/migrations``:: { $this->dbforge->add_field(array( 'blog_id' => array( - 'type' => 'INT', - 'constraint' => 5, - 'unsigned' => true, + 'type' => 'INT', + 'constraint' => 5, + 'unsigned' => true, 'auto_increment' => true, ), 'blog_title' => array( - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => '100', ), 'blog_description' => array( diff --git a/user_guide_src/source/installation/upgrade_models.rst b/user_guide_src/source/installation/upgrade_models.rst index 7100f6ca9202..ba508424cdf2 100644 --- a/user_guide_src/source/installation/upgrade_models.rst +++ b/user_guide_src/source/installation/upgrade_models.rst @@ -50,9 +50,9 @@ Path: ``application/models``:: public function insert($name, $address, $email) { $this->db->insert('user_contacts', array( - "name" => $name, - "address" => $address, - "email" => $email, + 'name' => $name, + 'address' => $address, + 'email' => $email, )); } } diff --git a/user_guide_src/source/installation/upgrade_pagination.rst b/user_guide_src/source/installation/upgrade_pagination.rst index 4743bb985cf2..23c8564d1390 100644 --- a/user_guide_src/source/installation/upgrade_pagination.rst +++ b/user_guide_src/source/installation/upgrade_pagination.rst @@ -39,11 +39,11 @@ CodeIgniter Version 3.11 :: $this->load->library('pagination'); - $config['base_url'] = base_url().'users/index/'; - $config['total_rows'] = $this->db->count_all('users'); - $config['per_page'] = 10; + $config['base_url'] = base_url().'users/index/'; + $config['total_rows'] = $this->db->count_all('users'); + $config['per_page'] = 10; $config['uri_segment'] = 3; - $config['attributes'] = array('class' => 'pagination-link'); + $config['attributes'] = array('class' => 'pagination-link'); $this->pagination->initialize($config); $data['users'] = $this->user_model->get_users(FALSE, $config['per_page'], $offset); diff --git a/user_guide_src/source/installation/upgrade_view_parser.rst b/user_guide_src/source/installation/upgrade_view_parser.rst index 94bd5ac67f19..96f821b81922 100644 --- a/user_guide_src/source/installation/upgrade_view_parser.rst +++ b/user_guide_src/source/installation/upgrade_view_parser.rst @@ -33,7 +33,7 @@ CodeIgniter Version 3.11 $this->load->library('parser'); $data = array( - 'blog_title' => 'My Blog Title', + 'blog_title' => 'My Blog Title', 'blog_heading' => 'My Blog Heading' ); From 3839795e6cd65c5440a5bc197fc20f69198f3099 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 19:03:12 +0900 Subject: [PATCH 242/407] docs: decorate variable with '``' --- user_guide_src/source/libraries/validation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index 27691f084a55..3550bec9ff9d 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -896,7 +896,7 @@ Rules for File Uploads ====================== These validation rules enable you to do the basic checks you might need to verify that uploaded files meet your business needs. -Since the value of a file upload HTML field doesn't exist, and is stored in the $_FILES global, the name of the input field will +Since the value of a file upload HTML field doesn't exist, and is stored in the ``$_FILES`` global, the name of the input field will need to be used twice. Once to specify the field name as you would for any other rule, but again as the first parameter of all file upload related rules:: From 0daf8c90166f35230216bb878343f8931444ad7a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 19:03:50 +0900 Subject: [PATCH 243/407] docs: add note about Validation rules --- user_guide_src/source/libraries/uploaded_files.rst | 4 ++++ user_guide_src/source/libraries/validation.rst | 2 ++ 2 files changed, 6 insertions(+) diff --git a/user_guide_src/source/libraries/uploaded_files.rst b/user_guide_src/source/libraries/uploaded_files.rst index 961823036e60..615716ea0273 100644 --- a/user_guide_src/source/libraries/uploaded_files.rst +++ b/user_guide_src/source/libraries/uploaded_files.rst @@ -146,6 +146,10 @@ this code and save it to your **app/Controllers/** directory:: } } +.. note:: Since the value of a file upload HTML field doesn't exist, and is stored in the ``$_FILES`` global, + only :ref:`rules-for-file-uploads` can be used to validate upload file with :doc:`validation`. + The rule ``required`` also can't be used, so use ``uploaded`` instead. + The Upload Directory ==================== diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index 3550bec9ff9d..aed337d1b062 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -892,6 +892,8 @@ valid_cc_number Yes Verifies that the credit card number matches HSBC Canada Card (hsbc) ======================= ========== ============================================= =================================================== +.. _rules-for-file-uploads: + Rules for File Uploads ====================== From 47a4af22e8cef349171c510de319178037cc4368 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 1 Dec 2021 16:29:58 +0900 Subject: [PATCH 244/407] docs: add TOC to general pages --- user_guide_src/source/general/ajax.rst | 4 ++++ user_guide_src/source/general/caching.rst | 4 ++++ user_guide_src/source/general/environments.rst | 4 ++++ user_guide_src/source/general/managing_apps.rst | 4 ++++ user_guide_src/source/general/urls.rst | 4 ++++ 5 files changed, 20 insertions(+) diff --git a/user_guide_src/source/general/ajax.rst b/user_guide_src/source/general/ajax.rst index 710406b41272..d3fd5945f1ff 100644 --- a/user_guide_src/source/general/ajax.rst +++ b/user_guide_src/source/general/ajax.rst @@ -8,6 +8,10 @@ To get around this problem, the most efficient solution (so far) is to manually Here's how to force the ``X-Requested-With`` header to be sent in the Fetch API and other JavaScript libraries. +.. contents:: + :local: + :depth: 2 + Fetch API ========= diff --git a/user_guide_src/source/general/caching.rst b/user_guide_src/source/general/caching.rst index f241cb02c15d..b3d5e152b879 100644 --- a/user_guide_src/source/general/caching.rst +++ b/user_guide_src/source/general/caching.rst @@ -12,6 +12,10 @@ page load speeds. By caching your pages, since they are saved in their fully rendered state, you can achieve performance much closer to that of static web pages. +.. contents:: + :local: + :depth: 2 + How Does Caching Work? ====================== diff --git a/user_guide_src/source/general/environments.rst b/user_guide_src/source/general/environments.rst index ac860d4634cf..057dd8e57dea 100644 --- a/user_guide_src/source/general/environments.rst +++ b/user_guide_src/source/general/environments.rst @@ -9,6 +9,10 @@ while developing an application, but it may also pose a security issue when "live". In development environments, you might want additional tools loaded that you don't in production environments, etc. +.. contents:: + :local: + :depth: 2 + The ENVIRONMENT Constant ======================== diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index 21fcebdf9407..5e4711958c24 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -8,6 +8,10 @@ directory. It is possible, however, to have multiple sets of applications that share a single CodeIgniter installation, or even to rename or relocate your application directory. +.. contents:: + :local: + :depth: 2 + Renaming or Relocating the Application Directory ================================================ diff --git a/user_guide_src/source/general/urls.rst b/user_guide_src/source/general/urls.rst index 5eab9ee7a1e1..da056cc96cbc 100644 --- a/user_guide_src/source/general/urls.rst +++ b/user_guide_src/source/general/urls.rst @@ -2,6 +2,10 @@ CodeIgniter URLs ################ +.. contents:: + :local: + :depth: 2 + By default, URLs in CodeIgniter are designed to be search-engine and human-friendly. Rather than using the standard "query-string" approach to URLs that is synonymous with dynamic systems, CodeIgniter uses a **segment-based** approach:: From d3d514b4892c7c140cb210bf22d2d33f2c9b1e16 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 10:32:39 +0900 Subject: [PATCH 245/407] docs: fix application folder name --- user_guide_src/source/general/managing_apps.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index 21fcebdf9407..92c152c5dd63 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -3,7 +3,7 @@ Managing your Applications ########################## By default, it is assumed that you only intend to use CodeIgniter to -manage one application, which you will build in your **application** +manage one application, which you will build in your **app** directory. It is possible, however, to have multiple sets of applications that share a single CodeIgniter installation, or even to rename or relocate your application directory. @@ -16,7 +16,7 @@ it to a different location on your server, other than your project root, open your main **app/Config/Paths.php** and set a *full server path* in the ``$appDirectory`` variable (at about line 44):: - public $appDirectory = '/path/to/your/application'; + public $appDirectory = '/path/to/your/app'; You will need to modify two additional files in your project root, so that they can find the ``Paths`` configuration file: From c96224688927a3c64303fa1a817e490cfdf0a5f1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 10:33:42 +0900 Subject: [PATCH 246/407] docs: decorate file paths with ** --- .../source/general/managing_apps.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index 92c152c5dd63..6e156cd783d5 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -19,15 +19,15 @@ your main **app/Config/Paths.php** and set a *full server path* in the public $appDirectory = '/path/to/your/app'; You will need to modify two additional files in your project root, so that -they can find the ``Paths`` configuration file: +they can find the **Paths** configuration file: -- ``/spark`` runs command line apps; the path is specified on or about line 35:: +- **/spark** runs command line apps; the path is specified on or about line 35:: $pathsConfig = 'app/Config/Paths.php'; // ^^^ Change this line if you move your application folder -- ``/public/index.php`` is the front controller for your webapp; the config +- **/public/index.php** is the front controller for your webapp; the config path is specified on or about line 20:: $pathsConfig = FCPATH . '../app/Config/Paths.php'; @@ -41,8 +41,8 @@ If you would like to share a common CodeIgniter framework installation, to manag several different applications, simply put all of the directories located inside your application directory into their own (sub)-directory. -For example, let's say you want to create two applications, named "foo" -and "bar". You could structure your application project directories like this: +For example, let's say you want to create two applications, named **foo** +and **bar**. You could structure your application project directories like this: .. code-block:: text @@ -60,12 +60,12 @@ and "bar". You could structure your application project directories like this: /system /docs -This would have two apps, "foo" and "bar", both having standard application directories -and a ``public`` folder, and sharing a common codeigniter framework. +This would have two apps, **foo** and **bar**, both having standard application directories +and a **public** folder, and sharing a common **codeigniter** framework. -The ``index.php`` inside each application would refer to its own configuration, +The **index.php** inside each application would refer to its own configuration, ``../app/Config/Paths.php``, and the ``$systemDirectory`` variable inside each -of those would be set to refer to the shared common "system" folder. +of those would be set to refer to the shared common **system** folder. If either of the applications had a command-line component, then you would also -modify ``spark`` inside each application's project folder, as directed above. +modify **spark** inside each application's project folder, as directed above. From 95581fd3bb9f91a2e2fbd5e785f0738050bf3d31 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 10:53:25 +0900 Subject: [PATCH 247/407] docs: there is no `docs` folder now --- user_guide_src/source/general/managing_apps.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index 6e156cd783d5..d9a3e8e05d77 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -58,7 +58,6 @@ and **bar**. You could structure your application project directories like this: /writable /codeigniter /system - /docs This would have two apps, **foo** and **bar**, both having standard application directories and a **public** folder, and sharing a common **codeigniter** framework. From a2aed177b40949eeac58f4dde61a108916823be5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 10:56:49 +0900 Subject: [PATCH 248/407] docs: add `spark` file --- user_guide_src/source/general/managing_apps.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index d9a3e8e05d77..6e2279ede97c 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -51,11 +51,13 @@ and **bar**. You could structure your application project directories like this: /public /tests /writable + spark /bar /app /public /tests /writable + spark /codeigniter /system From a838edcb61ccb49998979411f12ecd6e2c877760 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 11:04:00 +0900 Subject: [PATCH 249/407] chore: temporary fix for PhpCoveralls error https://github.com/php-coveralls/php-coveralls/issues/327 --- .github/workflows/test-phpunit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index 4583244ed358..61133437d3e8 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -137,7 +137,7 @@ jobs: - name: Run Coveralls if: github.repository_owner == 'codeigniter4' && matrix.php-versions == '8.0' run: | - composer global require --ansi php-coveralls/php-coveralls:^2.4 + composer global require --ansi php-coveralls/php-coveralls:^2.4 symfony/console:^5 php-coveralls --coverage_clover=build/logs/clover.xml -v env: COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 8cd4cd33bf357247b0b6fc40b099d6d54ceda113 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 15:49:25 +0900 Subject: [PATCH 250/407] refactor: Time::getDst() --- system/I18n/Time.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/system/I18n/Time.php b/system/I18n/Time.php index ca8ffc3dc72e..c182bee32e7e 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -479,21 +479,7 @@ public function getQuarter(): string */ public function getDst(): bool { - // grab the transactions that would affect today - $start = strtotime('-1 year', $this->getTimestamp()); - $end = strtotime('+2 year', $start); - $transitions = $this->timezone->getTransitions($start, $end); - - $daylightSaving = false; - - foreach ($transitions as $transition) { - if ($transition['time'] > $this->format('U')) { - $daylightSaving = (bool) ($transition['isdst'] ?? $daylightSaving); - break; - } - } - - return $daylightSaving; + return (bool) $this->format('I'); } /** From 027381d6fbbf18a284d4e75061f8e36919774c93 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 1 Dec 2021 20:34:00 +0900 Subject: [PATCH 251/407] chore: fix example test code for starter and module --- .../tests/database/ExampleDatabaseTest.php | 12 ++++++------ .../module/tests/session/ExampleSessionTest.php | 17 +++++++---------- .../tests/database/ExampleDatabaseTest.php | 3 +++ .../tests/session/ExampleSessionTest.php | 7 +++++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/admin/module/tests/database/ExampleDatabaseTest.php b/admin/module/tests/database/ExampleDatabaseTest.php index 203b1261c7e0..f9edc4d235d8 100644 --- a/admin/module/tests/database/ExampleDatabaseTest.php +++ b/admin/module/tests/database/ExampleDatabaseTest.php @@ -1,18 +1,18 @@ session->set('logged_in', 123); - - $value = $this->session->get('logged_in'); + $session = Services::session(); - $this->assertSame(123, $value); + $session->set('logged_in', 123); + $this->assertSame(123, $session->get('logged_in')); } } diff --git a/admin/starter/tests/database/ExampleDatabaseTest.php b/admin/starter/tests/database/ExampleDatabaseTest.php index 5d13836f9dc6..f9edc4d235d8 100644 --- a/admin/starter/tests/database/ExampleDatabaseTest.php +++ b/admin/starter/tests/database/ExampleDatabaseTest.php @@ -2,6 +2,7 @@ use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; +use Tests\Support\Database\Seeds\ExampleSeeder; use Tests\Support\Models\ExampleModel; /** @@ -11,6 +12,8 @@ final class ExampleDatabaseTest extends CIUnitTestCase { use DatabaseTestTrait; + protected $seed = ExampleSeeder::class; + public function testModelFindAll() { $model = new ExampleModel(); diff --git a/admin/starter/tests/session/ExampleSessionTest.php b/admin/starter/tests/session/ExampleSessionTest.php index 151036412146..98fe7afa0d77 100644 --- a/admin/starter/tests/session/ExampleSessionTest.php +++ b/admin/starter/tests/session/ExampleSessionTest.php @@ -1,6 +1,7 @@ session->set('logged_in', 123); - $this->assertSame(123, $this->session->get('logged_in')); + $session = Services::session(); + + $session->set('logged_in', 123); + $this->assertSame(123, $session->get('logged_in')); } } From dfeb02f744f95ac879a2fc3550eea8b72c459916 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 08:31:56 +0900 Subject: [PATCH 252/407] docs: fix sample code that uses non-existent methods --- user_guide_src/source/libraries/time.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/libraries/time.rst b/user_guide_src/source/libraries/time.rst index 12f3a9f38e7e..cd8dc0a9ddcf 100644 --- a/user_guide_src/source/libraries/time.rst +++ b/user_guide_src/source/libraries/time.rst @@ -334,9 +334,9 @@ thrown. :: $time = $time->setYear(2017); - $time = $time->setMonthNumber(4); // April - $time = $time->setMonthLongName('April'); - $time = $time->setMonthShortName('Feb'); // February + $time = $time->setMonth(4); // April + $time = $time->setMonth('April'); + $time = $time->setMonth('Feb'); // February $time = $time->setDay(25); $time = $time->setHour(14); // 2:00 pm $time = $time->setMinute(30); From 4ea0156e387b0684477e6d313332213eec76045d Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 08:35:28 +0900 Subject: [PATCH 253/407] docs: decorate class,method,variable with '``' --- user_guide_src/source/libraries/time.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/user_guide_src/source/libraries/time.rst b/user_guide_src/source/libraries/time.rst index cd8dc0a9ddcf..11093a3b5a60 100644 --- a/user_guide_src/source/libraries/time.rst +++ b/user_guide_src/source/libraries/time.rst @@ -4,7 +4,7 @@ Times and Dates CodeIgniter provides a fully-localized, immutable, date/time class that is built on PHP's DateTime object, but uses the Intl extension's features to convert times across timezones and display the output correctly for different locales. This class -is the **Time** class and lives in the **CodeIgniter\\I18n** namespace. +is the ``Time`` class and lives in the ``CodeIgniter\I18n`` namespace. .. note:: Since the Time class extends DateTime, if there are features that you need that this class doesn't provide, you can likely find them within the DateTime class itself. @@ -38,7 +38,7 @@ provided, the application defaults will be used. now() ----- -The Time class has several helper methods to instantiate the class. The first of these is the **now()** method +The Time class has several helper methods to instantiate the class. The first of these is the ``now()`` method that returns a new instance set to the current time. You can pass in strings representing the timezone and the locale in the second and parameters, respectively. If no locale or timezone is provided, the application defaults will be used. @@ -92,7 +92,7 @@ fourth and fifth parameters:: createFromTime() ---------------- -Like **createFromDate** except it is only concerned with the **hours**, **minutes**, and **seconds**. Uses the +Like ``createFromDate()`` except it is only concerned with the **hours**, **minutes**, and **seconds**. Uses the current day for the date portion of the Time instance. Accepts strings for the timezone and locale in the fourth and fifth parameters:: @@ -113,7 +113,7 @@ createFromFormat() ------------------ This is a replacement for DateTime's method of the same name. This allows the timezone to be set at the same time, -and returns a **Time** instance, instead of DateTime:: +and returns a ``Time`` instance, instead of DateTime:: $time = Time::createFromFormat('j-M-Y', '15-Feb-2009', 'America/Chicago'); @@ -154,7 +154,7 @@ to display localized versions of the value, though. toLocalizedString() ------------------- -This is the localized version of DateTime's format() method. Instead of using the values you might be familiar with, though, +This is the localized version of DateTime's ``format()`` method. Instead of using the values you might be familiar with, though, you must use values acceptable to the `IntlDateFormatter `__ class. A full listing of values can be found `here `__. :: @@ -224,8 +224,8 @@ The Time object provides a number of methods to allow to get and set individual of an existing instance. All of the values retrieved through the following methods will be fully localized and respect the locale that the Time instance was created with. -All of the following `getX` and `setX` methods can also be used as if they were a class property. So, any calls to methods -like `getYear` can also be accessed through `$time->year`, and so on. +All of the following ``getX()`` and ``setX()`` methods can also be used as if they were a class property. So, any calls to methods +like ``getYear()`` can also be accessed through ``$time->year``, and so on. Getters ------- @@ -416,7 +416,7 @@ a timezone string in as the second parameter. If no timezone is given, the syste sameAs() -------- -This is identical to the **equals** method, except that it only returns true when the date, time, AND timezone are +This is identical to the ``equals()`` method, except that it only returns true when the date, time, AND timezone are all identical:: $time1 = Time::parse('January 10, 2017 21:50:00', 'America/Chicago'); @@ -446,7 +446,7 @@ a timezone string in as the second parameter. If no timezone is given, the syste isAfter() --------- -Works exactly the same as **isBefore()** except checks if the time is after the time passed in:: +Works exactly the same as ``isBefore()`` except checks if the time is after the time passed in:: $time1 = Time::parse('January 10, 2017 21:50:00', 'America/Chicago'); $time2 = Time::parse('January 11, 2017 03:50:00', 'America/Chicago'); @@ -457,7 +457,7 @@ Works exactly the same as **isBefore()** except checks if the time is after the Viewing Differences =================== -To compare two Times directly, you would use the **difference()** method, which returns a **CodeIgniter\\I18n\\TimeDifference** +To compare two Times directly, you would use the ``difference()`` method, which returns a ``CodeIgniter\\I18n\\TimeDifference`` instance. The first parameter is either a Time instance, a DateTime instance, or a string with the date/time. If a string is passed in the first parameter, the second parameter can be a timezone string:: @@ -484,7 +484,7 @@ the original time:: echo $diff->getMinutes(); // -3682080 echo $diff->getSeconds(); // -220924800 -You can use either **getX()** methods, or access the calculate values as if they were properties:: +You can use either ``getX()`` methods, or access the calculate values as if they were properties:: echo $diff->years; // -7 echo $diff->months; // -84 @@ -497,7 +497,7 @@ You can use either **getX()** methods, or access the calculate values as if they humanize() ---------- -Much like Time's humanize() method, this returns a string that displays the difference between the times in a +Much like Time's ``humanize()`` method, this returns a string that displays the difference between the times in a human readable format that is geared towards being easily understood. It can create strings like '3 hours ago', 'in 1 month', etc. The biggest differences are in how very recent dates are handled:: From c30e02622109571d1a49710978034584c8599408 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 08:37:47 +0900 Subject: [PATCH 254/407] docs: decrate filename with ** --- user_guide_src/source/libraries/time.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/libraries/time.rst b/user_guide_src/source/libraries/time.rst index 11093a3b5a60..6b2c2c32efd0 100644 --- a/user_guide_src/source/libraries/time.rst +++ b/user_guide_src/source/libraries/time.rst @@ -214,7 +214,7 @@ $time > now && < 1 hour in 35 minutes / 35 minutes ago $time == now Now =============================== ================================= -The exact language used is controlled through the language file, Time.php. +The exact language used is controlled through the language file, **Time.php**. ============================== Working with Individual Values @@ -522,4 +522,4 @@ $time > 1 minute && < 1 hour in 35 minutes / 35 minutes ago $time < 1 minute Now =============================== ================================= -The exact language used is controlled through the language file, Time.php. +The exact language used is controlled through the language file, **Time.php**. From 4cbbd7ecd6b520ef46b3fb537e14e823bcfa7b7d Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 08:38:29 +0900 Subject: [PATCH 255/407] docs: align comments --- user_guide_src/source/libraries/time.rst | 82 ++++++++++++------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/user_guide_src/source/libraries/time.rst b/user_guide_src/source/libraries/time.rst index 6b2c2c32efd0..494a934b4fea 100644 --- a/user_guide_src/source/libraries/time.rst +++ b/user_guide_src/source/libraries/time.rst @@ -85,7 +85,7 @@ Given separate inputs for **year**, **month**, and **day**, will return a new in are not provided, it will use the current value to fill it in. Accepts strings for the timezone and locale in the fourth and fifth parameters:: - $today = Time::createFromDate(); // Uses current year, month, and day + $today = Time::createFromDate(); // Uses current year, month, and day $anniversary = Time::createFromDate(2018); // Uses current month and day $date = Time::createFromDate(2018, 3, 15, 'America/Chicago', 'en_US'); @@ -96,7 +96,7 @@ Like ``createFromDate()`` except it is only concerned with the **hours**, **minu current day for the date portion of the Time instance. Accepts strings for the timezone and locale in the fourth and fifth parameters:: - $lunch = Time::createFromTime(11, 30); // 11:30 am today + $lunch = Time::createFromTime(11, 30); // 11:30 am today $dinner = Time::createFromTime(18, 00, 00); // 6:00 pm today $time = Time::createFromTime($hour, $minutes, $seconds, $timezone, $locale); @@ -234,17 +234,17 @@ The following basic getters exist:: $time = Time::parse('August 12, 2016 4:15:23pm'); - echo $time->getYear(); // 2016 - echo $time->getMonth(); // 8 - echo $time->getDay(); // 12 - echo $time->getHour(); // 16 + echo $time->getYear(); // 2016 + echo $time->getMonth(); // 8 + echo $time->getDay(); // 12 + echo $time->getHour(); // 16 echo $time->getMinute(); // 15 echo $time->getSecond(); // 23 - echo $time->year; // 2016 - echo $time->month; // 8 - echo $time->day; // 12 - echo $time->hour; // 16 + echo $time->year; // 2016 + echo $time->month; // 8 + echo $time->day; // 12 + echo $time->hour; // 16 echo $time->minute; // 15 echo $time->second; // 23 @@ -252,19 +252,19 @@ In addition to these, a number of methods exist to provide additional informatio $time = Time::parse('August 12, 2016 4:15:23pm'); - echo $time->getDayOfWeek(); // 6 - but may vary based on locale's starting day of the week - echo $time->getDayOfYear(); // 225 + echo $time->getDayOfWeek(); // 6 - but may vary based on locale's starting day of the week + echo $time->getDayOfYear(); // 225 echo $time->getWeekOfMonth(); // 2 - echo $time->getWeekOfYear(); // 33 - echo $time->getTimestamp(); // 1471018523 - UNIX timestamp - echo $time->getQuarter(); // 3 + echo $time->getWeekOfYear(); // 33 + echo $time->getTimestamp(); // 1471018523 - UNIX timestamp + echo $time->getQuarter(); // 3 - echo $time->dayOfWeek; // 6 - echo $time->dayOfYear; // 225 + echo $time->dayOfWeek; // 6 + echo $time->dayOfYear; // 225 echo $time->weekOfMonth; // 2 - echo $time->weekOfYear; // 33 - echo $time->timestamp; // 1471018523 - echo $time->quarter; // 3 + echo $time->weekOfYear; // 33 + echo $time->timestamp; // 1471018523 + echo $time->quarter; // 3 getAge() -------- @@ -275,7 +275,7 @@ the age of someone based on their birthday:: $time = Time::parse('5 years ago'); echo $time->getAge(); // 5 - echo $time->age; // 5 + echo $time->age; // 5 getDST() -------- @@ -283,14 +283,14 @@ getDST() Returns boolean true/false based on whether the Time instance is currently observing Daylight Savings Time:: echo Time::createFromDate(2012, 1, 1)->getDst(); // false - echo Time::createFromDate(2012, 9, 1)->dst; // true + echo Time::createFromDate(2012, 9, 1)->dst; // true getLocal() ---------- Returns boolean true if the Time instance is in the same timezone as the application is currently running in:: - echo Time::now()->getLocal(); // true + echo Time::now()->getLocal(); // true echo Time::now('Europe/London'); // false getUtc() @@ -299,7 +299,7 @@ getUtc() Returns boolean true if the Time instance is in UTC time:: echo Time::now('America/Chicago')->getUtc(); // false - echo Time::now('UTC')->utc; // true + echo Time::now('UTC')->utc; // true getTimezone() ------------- @@ -319,7 +319,7 @@ getTimezoneName() Returns the full `timezone string `__ of the Time instance:: echo Time::now('America/Chicago')->getTimezoneName(); // America/Chicago - echo Time::now('Europe/London')->timezoneName; // Europe/London + echo Time::now('Europe/London')->timezoneName; // Europe/London Setters ======= @@ -334,11 +334,11 @@ thrown. :: $time = $time->setYear(2017); - $time = $time->setMonth(4); // April + $time = $time->setMonth(4); // April $time = $time->setMonth('April'); - $time = $time->setMonth('Feb'); // February + $time = $time->setMonth('Feb'); // February $time = $time->setDay(25); - $time = $time->setHour(14); // 2:00 pm + $time = $time->setHour(14); // 2:00 pm $time = $time->setMinute(30); $time = $time->setSecond(54); @@ -350,10 +350,10 @@ Converts the time from it's current timezone into the new one:: $time = Time::parse('13 May 2020 10:00', 'America/Chicago'); $time2 = $time->setTimezone('Europe/London'); // Returns new instance converted to new timezone - echo $time->getTimezoneName(); // American/Chicago + echo $time->getTimezoneName(); // American/Chicago echo $time2->getTimezoneName(); // Europe/London - echo $time->toDateTimeString(); // 2020-05-13 10:00:00 + echo $time->toDateTimeString(); // 2020-05-13 10:00:00 echo $time2->toDateTimeString(); // 2020-05-13 18:00:00 setTimestamp() @@ -364,7 +364,7 @@ Returns a new instance with the date set to the new timestamp:: $time = Time::parse('May 10, 2017', 'America/Chicago'); $time2 = $time->setTimestamp(strtotime('April 1, 2017')); - echo $time->toDateTimeString(); // 2017-05-10 00:00:00 + echo $time->toDateTimeString(); // 2017-05-10 00:00:00 echo $time2->toDateTimeString(); // 2017-04-01 00:00:00 Modifying the Value @@ -422,7 +422,7 @@ all identical:: $time1 = Time::parse('January 10, 2017 21:50:00', 'America/Chicago'); $time2 = Time::parse('January 11, 2017 03:50:00', 'Europe/London'); - $time1->sameAs($time2); // false + $time1->sameAs($time2); // false $time2->sameAs('January 10, 2017 21:50:00', 'America/Chicago'); // true isBefore() @@ -476,21 +476,21 @@ the original time:: $diff = $current->difference($test); - echo $diff->getYears(); // -7 - echo $diff->getMonths(); // -84 - echo $diff->getWeeks(); // -365 - echo $diff->getDays(); // -2557 - echo $diff->getHours(); // -61368 + echo $diff->getYears(); // -7 + echo $diff->getMonths(); // -84 + echo $diff->getWeeks(); // -365 + echo $diff->getDays(); // -2557 + echo $diff->getHours(); // -61368 echo $diff->getMinutes(); // -3682080 echo $diff->getSeconds(); // -220924800 You can use either ``getX()`` methods, or access the calculate values as if they were properties:: echo $diff->years; // -7 - echo $diff->months; // -84 - echo $diff->weeks; // -365 - echo $diff->days; // -2557 - echo $diff->hours; // -61368 + echo $diff->months; // -84 + echo $diff->weeks; // -365 + echo $diff->days; // -2557 + echo $diff->hours; // -61368 echo $diff->minutes; // -3682080 echo $diff->seconds; // -220924800 From f55ddd28016fc258400fb905d2a19b5a3f495ecb Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 08:42:37 +0900 Subject: [PATCH 256/407] docs: remove duplicated '\' --- user_guide_src/source/libraries/time.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/time.rst b/user_guide_src/source/libraries/time.rst index 494a934b4fea..57ee4d4572d6 100644 --- a/user_guide_src/source/libraries/time.rst +++ b/user_guide_src/source/libraries/time.rst @@ -457,7 +457,7 @@ Works exactly the same as ``isBefore()`` except checks if the time is after the Viewing Differences =================== -To compare two Times directly, you would use the ``difference()`` method, which returns a ``CodeIgniter\\I18n\\TimeDifference`` +To compare two Times directly, you would use the ``difference()`` method, which returns a ``CodeIgniter\I18n\TimeDifference`` instance. The first parameter is either a Time instance, a DateTime instance, or a string with the date/time. If a string is passed in the first parameter, the second parameter can be a timezone string:: From 11007b454370097d5e763472c62a01b737c33256 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 08:51:07 +0900 Subject: [PATCH 257/407] docs: add command prompt '>' before `php spark` --- user_guide_src/source/cli/cli_generators.rst | 2 +- user_guide_src/source/dbmgmt/forge.rst | 4 ++-- user_guide_src/source/installation/running.rst | 8 ++++---- user_guide_src/source/installation/troubleshooting.rst | 2 +- user_guide_src/source/tutorial/index.rst | 2 +- user_guide_src/source/tutorial/static_pages.rst | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/user_guide_src/source/cli/cli_generators.rst b/user_guide_src/source/cli/cli_generators.rst index 210226b51edc..5cf4ed4279da 100644 --- a/user_guide_src/source/cli/cli_generators.rst +++ b/user_guide_src/source/cli/cli_generators.rst @@ -260,7 +260,7 @@ generator command are recognized by the scaffold command. Running this in your terminal:: - php spark make:scaffold user + > php spark make:scaffold user will create the following classes: diff --git a/user_guide_src/source/dbmgmt/forge.rst b/user_guide_src/source/dbmgmt/forge.rst index e1ed99e02c5c..720f77655d54 100644 --- a/user_guide_src/source/dbmgmt/forge.rst +++ b/user_guide_src/source/dbmgmt/forge.rst @@ -67,7 +67,7 @@ will complain that the database creation has failed. To start, just type the command and the name of the database (e.g., ``foo``):: - php spark db:create foo + > php spark db:create foo If everything went fine, you should expect the ``Database "foo" successfully created.`` message displayed. @@ -76,7 +76,7 @@ for the file where the database will be created using the ``--ext`` option. Vali ``sqlite`` and defaults to ``db``. Remember that these should not be preceded by a period. :: - php spark db:create foo --ext sqlite + > php spark db:create foo --ext sqlite // will create the db file in WRITEPATH/foo.sqlite .. note:: When using the special SQLite3 database name ``:memory:``, expect that the command will still diff --git a/user_guide_src/source/installation/running.rst b/user_guide_src/source/installation/running.rst index bb4b99aa468f..f16bb7636672 100644 --- a/user_guide_src/source/installation/running.rst +++ b/user_guide_src/source/installation/running.rst @@ -43,7 +43,7 @@ CodeIgniter 4 comes with a local development server, leveraging PHP's built-in w with CodeIgniter routing. You can use the ``serve`` script to launch it, with the following command line in the main directory:: - php spark serve + > php spark serve This will launch the server and you can now view your application in your browser at http://localhost:8080. @@ -58,17 +58,17 @@ The local development server can be customized with three command line options: - You can use the ``--host`` CLI option to specify a different host to run the application at:: - php spark serve --host example.dev + > php spark serve --host example.dev - By default, the server runs on port 8080 but you might have more than one site running, or already have another application using that port. You can use the ``--port`` CLI option to specify a different one:: - php spark serve --port 8081 + > php spark serve --port 8081 - You can also specify a specific version of PHP to use, with the ``--php`` CLI option, with its value set to the path of the PHP executable you want to use:: - php spark serve --php /usr/bin/php7.6.5.4 + > php spark serve --php /usr/bin/php7.6.5.4 Hosting with Apache =================== diff --git a/user_guide_src/source/installation/troubleshooting.rst b/user_guide_src/source/installation/troubleshooting.rst index ff30759efcad..0da650bdf07c 100644 --- a/user_guide_src/source/installation/troubleshooting.rst +++ b/user_guide_src/source/installation/troubleshooting.rst @@ -9,7 +9,7 @@ How do I know if my install is working? From the command line, at your project root:: - php spark serve + > php spark serve ``http://localhost:8080`` in your browser should then show the default welcome page: diff --git a/user_guide_src/source/tutorial/index.rst b/user_guide_src/source/tutorial/index.rst index 6be36535579b..71182a6f5bf4 100644 --- a/user_guide_src/source/tutorial/index.rst +++ b/user_guide_src/source/tutorial/index.rst @@ -82,7 +82,7 @@ comes with a simple command that takes advantage of PHP's built-in server to get you up and running fast on your development machines. Type the following on the command line from the root of your project:: - php spark serve + > php spark serve The Welcome Page diff --git a/user_guide_src/source/tutorial/static_pages.rst b/user_guide_src/source/tutorial/static_pages.rst index 1763d1fae624..ecf6e87e03c5 100644 --- a/user_guide_src/source/tutorial/static_pages.rst +++ b/user_guide_src/source/tutorial/static_pages.rst @@ -178,7 +178,7 @@ From the command line, at the root of your project: :: - php spark serve + > php spark serve will start a web server, accessible on port 8080. If you set the location field in your browser to ``localhost:8080``, you should see the CodeIgniter welcome page. From 458aa5b24fbbd7f3848eb226777289972be9485b Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 09:45:09 +0900 Subject: [PATCH 258/407] docs: add command prompt `>` before `composer` --- .../source/installation/installing_composer.rst | 14 +++++++------- user_guide_src/source/libraries/caching.rst | 2 +- user_guide_src/source/tutorial/index.rst | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index b63e34602425..41b288c02037 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -32,7 +32,7 @@ Installation & Set Up In the folder above your project root:: - composer create-project codeigniter4/appstarter project-root + > composer create-project codeigniter4/appstarter project-root The command above will create a "project-root" folder. @@ -46,7 +46,7 @@ trusted dependencies that we bundle, being composer-installed. A sample such installation command, using the default project-root "appstarter":: - composer create-project codeigniter4/appstarter --no-dev + > composer create-project codeigniter4/appstarter --no-dev After installation you should follow the steps in the "Upgrading" section. @@ -55,11 +55,11 @@ Upgrading Whenever there is a new release, then from the command line in your project root:: - composer update + > composer update If you want to compare the latest framework source structure for non-system directory (app, public, etc), you can update with ``--prefer-source``:: - composer update codeigniter4/framework --prefer-source + > composer update codeigniter4/framework --prefer-source If ``--prefer-source`` doesn't automatically update to pull latest framework source structure, you can remove first:: @@ -125,7 +125,7 @@ will be your document root. In your project root:: - composer require codeigniter4/framework --prefer-source + > composer require codeigniter4/framework --prefer-source As with the earlier two composer install methods, you can omit installing phpunit and its dependencies by adding the ``--no-dev`` argument to the ``composer require`` command. @@ -147,7 +147,7 @@ Upgrading Whenever there is a new release, then from the command line in your project root:: - composer update --prefer-source + > composer update --prefer-source Read the upgrade instructions, and check designated ``app/Config`` folders for affected changes. @@ -179,6 +179,6 @@ they can be added to your project in a similar fashion. From the command line inside your project root:: - composer require codeigniter4/translations + > composer require codeigniter4/translations These will be updated along with the framework whenever you do a ``composer update``. diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst index d9c79289c747..cc9049ee9a5d 100644 --- a/user_guide_src/source/libraries/caching.rst +++ b/user_guide_src/source/libraries/caching.rst @@ -315,7 +315,7 @@ Predis Caching Predis is a flexible and feature-complete PHP client library for the Redis key-value store. To use it, from the command line inside your project root:: - composer require predis/predis + > composer require predis/predis For more information on Redis, please see `https://github.com/nrk/predis `_. diff --git a/user_guide_src/source/tutorial/index.rst b/user_guide_src/source/tutorial/index.rst index 6be36535579b..f396e44283c8 100644 --- a/user_guide_src/source/tutorial/index.rst +++ b/user_guide_src/source/tutorial/index.rst @@ -59,7 +59,7 @@ From your command line type the following: :: - composer create-project codeigniter4/appstarter ci-news + > composer create-project codeigniter4/appstarter ci-news This creates a new folder, **ci-news**, which contains your application code, with CodeIgniter installed in the vendor folder. From 5ecf75138a2d5debe505d285f35031daffcf620c Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 09:55:41 +0900 Subject: [PATCH 259/407] docs: fix decoration for file path and code --- .../source/installation/upgrade_controllers.rst | 12 ++++++------ .../source/installation/upgrade_database.rst | 2 +- .../source/installation/upgrade_encryption.rst | 2 +- .../source/installation/upgrade_file_upload.rst | 2 +- .../source/installation/upgrade_localization.rst | 4 ++-- .../source/installation/upgrade_migrations.rst | 6 +++--- .../source/installation/upgrade_models.rst | 12 ++++++------ .../source/installation/upgrade_security.rst | 2 +- .../source/installation/upgrade_validations.rst | 8 ++++---- user_guide_src/source/installation/upgrade_views.rst | 6 +++--- 10 files changed, 28 insertions(+), 28 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_controllers.rst b/user_guide_src/source/installation/upgrade_controllers.rst index 2625bd29cbb0..003cad92a295 100644 --- a/user_guide_src/source/installation/upgrade_controllers.rst +++ b/user_guide_src/source/installation/upgrade_controllers.rst @@ -23,16 +23,16 @@ What has been changed Upgrade Guide ============= -1. First, move all controller files to the folder ``app/Controllers``. +1. First, move all controller files to the folder **app/Controllers**. 2. Add this line just after the opening php tag: ``namespace App\Controllers;`` 3. Replace ``extends CI_Controller`` with ``extends BaseController``. | If you use sub-directories in your controller structure, you have to change the namespace according to that. -| For example, you have a version 3 controller located in ``application/controllers/users/auth/Register.php``, +| For example, you have a version 3 controller located in **application/controllers/users/auth/Register.php**, the namespace has to be ``namespace App\Controllers\Users\Auth;`` and the controller path in the version 4 - should look like this: ``app/Controllers/Users/Auth/Register.php``. Make sure to have the first letters of + should look like this: **app/Controllers/Users/Auth/Register.php**. Make sure to have the first letters of the sub-directories as capitalized. -| After that you have to insert a "use" statement below the namespace definition in order to extend the "BaseController": +| After that you have to insert a ``use`` statement below the namespace definition in order to extend the ``BaseController``: ``use App\Controllers\BaseController;`` Code Example @@ -41,7 +41,7 @@ Code Example CodeIgniter Version 3.11 ------------------------ -Path: ``application/controllers``:: +Path: **application/controllers**:: load->database();`` with ``$db = db_connect();``. 3. If you use multiple databases use the following code to load additional databases ``$db = db_connect('group_name');``. 4. Now you have to change all database queries. The most important change here is to replace ``$this->db`` with just ``$db`` and adjust the method name and ``$db``. Here are some examples: diff --git a/user_guide_src/source/installation/upgrade_encryption.rst b/user_guide_src/source/installation/upgrade_encryption.rst index dca7fbcbc27b..003abc7ae218 100644 --- a/user_guide_src/source/installation/upgrade_encryption.rst +++ b/user_guide_src/source/installation/upgrade_encryption.rst @@ -19,7 +19,7 @@ What has been changed Upgrade Guide ============= -1. Within your configs the ``$config['encryption_key'] = 'abc123';`` moved from ``application/config/config.php`` to ``public $key = 'abc123';`` in ``app/Config/Encryption.php``. +1. Within your configs the ``$config['encryption_key'] = 'abc123';`` moved from **application/config/config.php** to ``public $key = 'abc123';`` in **app/Config/Encryption.php**. 2. Wherever you have used the encryption library you have to replace ``$this->load->library('encryption');`` with ``$encrypter = service('encrypter');`` and change the methods for encryption and decrypting like in the following code example. Code Example diff --git a/user_guide_src/source/installation/upgrade_file_upload.rst b/user_guide_src/source/installation/upgrade_file_upload.rst index 3369442e6392..6161e999f45e 100644 --- a/user_guide_src/source/installation/upgrade_file_upload.rst +++ b/user_guide_src/source/installation/upgrade_file_upload.rst @@ -18,7 +18,7 @@ What has been changed Upgrade Guide ============= In CI4 you access uploaded files with ``$file = $this->request->getFile('userfile')``. From there you can validate if the file got uploaded successfully with ``$file->isValid()``. -To store the file you could use ``$path = $this->request->getFile('userfile')->store('head_img/', 'user_name.jpg');`` This will store the file in ``writable/uploads/head_img/user_name.jpg``. +To store the file you could use ``$path = $this->request->getFile('userfile')->store('head_img/', 'user_name.jpg');``. This will store the file in **writable/uploads/head_img/user_name.jpg**. You have to change your file uploading code to match the new methods. diff --git a/user_guide_src/source/installation/upgrade_localization.rst b/user_guide_src/source/installation/upgrade_localization.rst index b974570f5939..ca919c7cdb1b 100644 --- a/user_guide_src/source/installation/upgrade_localization.rst +++ b/user_guide_src/source/installation/upgrade_localization.rst @@ -19,11 +19,11 @@ What has been changed Upgrade Guide ============= -1. Specify the default language in *Config/App.php*::: +1. Specify the default language in **Config/App.php**:: public $defaultLocale = 'en'; -2. Now move your language files to ``app/Language//``. +2. Now move your language files to **app/Language/**. 3. After that you have to change the syntax within the language files. Below in the Code Example you will see how the language array within the file should look like. 4. Remove from every file the language loader ``$this->lang->load($file, $lang);``. 5. Replace the method to load the language line ``$this->lang->line('error_email_missing')`` with ``echo lang('Errors.errorEmailMissing');``. diff --git a/user_guide_src/source/installation/upgrade_migrations.rst b/user_guide_src/source/installation/upgrade_migrations.rst index 10a75bf23f2d..9141cc82ae21 100644 --- a/user_guide_src/source/installation/upgrade_migrations.rst +++ b/user_guide_src/source/installation/upgrade_migrations.rst @@ -25,7 +25,7 @@ Upgrade Guide ============= 1. If your v3 project uses sequential migration names you have to change those to timestamp names. -2. You have to move all migration files to the new folder ``app/Database/Migrations``. +2. You have to move all migration files to the new folder **app/Database/Migrations**. 3. Remove the following line ``defined('BASEPATH') OR exit('No direct script access allowed');``. 4. Add this line just after the opening php tag: ``namespace App\Database\Migrations;``. 5. Below the ``namespace App\Database\Migrations;`` line add this line: ``use CodeIgniter\Database\Migration;`` @@ -51,7 +51,7 @@ Code Example CodeIgniter Version 3.11 ------------------------ -Path: ``application/migrations``:: +Path: **application/migrations**:: load->model(x);``, you would now use ``$this->x = new X();``, following namespaced conventions for your component. Alternatively, you can use the ``model`` function: ``$this->x = model('X');``. +5. Instead of CI3’s ``$this->load->model(x);``, you would now use ``$this->x = new X();``, following namespaced conventions for your component. Alternatively, you can use the ``model()`` function: ``$this->x = model('X');``. If you use sub-directories in your model structure you have to change the namespace according to that. -Example: You have a version 3 model located in ``application/models/users/user_contact.php`` the namespace has to be ``namespace App\Models\Users;`` and the model path in the version 4 should look like this: ``app/Models/Users/UserContact.php`` +Example: You have a version 3 model located in **application/models/users/user_contact.php** the namespace has to be ``namespace App\Models\Users;`` and the model path in the version 4 should look like this: **app/Models/Users/UserContact.php** The new Model in CI4 has a lot of built-in methods. For example, the ``find($id)`` method. With this you can find data where the primary key is equal to ``$id``. Inserting data is also easier than before. In CI4 there is an ``insert($data)`` method. You can optionally make use of all those built-in methods and migrate your code to the new methods. @@ -41,7 +41,7 @@ Code Example CodeIgniter Version 3.11 ------------------------ -Path: ``application/models``:: +Path: **application/models**:: insert()`` method because this method is built-in since CI 4. +To insert data you can just directly call the ``$model->insert()`` method because this method is built-in since CI4. diff --git a/user_guide_src/source/installation/upgrade_security.rst b/user_guide_src/source/installation/upgrade_security.rst index 4aeb34e513c9..12990ba63347 100644 --- a/user_guide_src/source/installation/upgrade_security.rst +++ b/user_guide_src/source/installation/upgrade_security.rst @@ -21,7 +21,7 @@ What has been changed Upgrade Guide ============= -1. To enable CSRF protection in CI4 you have to enable it in ``app/Config/Filters.php``:: +1. To enable CSRF protection in CI4 you have to enable it in **app/Config/Filters.php**:: public $globals = [ 'before' => [ diff --git a/user_guide_src/source/installation/upgrade_validations.rst b/user_guide_src/source/installation/upgrade_validations.rst index 5e2b1a2bf942..083479d210db 100644 --- a/user_guide_src/source/installation/upgrade_validations.rst +++ b/user_guide_src/source/installation/upgrade_validations.rst @@ -46,7 +46,7 @@ Code Example CodeIgniter Version 3.11 ------------------------ -Path: ``application/views``:: +Path: **application/views**:: @@ -77,7 +77,7 @@ Path: ``application/views``:: -Path: ``application/controllers/``:: +Path: **application/controllers**:: @@ -135,7 +135,7 @@ Path: ``app/Views``:: -Path: ``app/Controllers/``:: +Path: **app/Controllers**:: load->view('directory_name/file_name')`` to ``echo view('directory_name/file_name');`` 3. (optional) You can change the echo syntax in views from ```` to ```` @@ -33,7 +33,7 @@ Code Example CodeIgniter Version 3.11 ------------------------ -Path: ``application/views``:: +Path: **application/views**:: @@ -56,7 +56,7 @@ Path: ``application/views``:: CodeIgniter Version 4.x ----------------------- -Path: ``app/Views``:: +Path: **app/Views**:: From f3eea52e21dee98ae74fbe6e372ebe892bd7e0dc Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 5 Dec 2021 11:53:00 +0900 Subject: [PATCH 260/407] docs: add "License Agreement" and "Change Logs" in the TOC --- user_guide_src/source/installation/index.rst | 1 + user_guide_src/source/intro/index.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/user_guide_src/source/installation/index.rst b/user_guide_src/source/installation/index.rst index 37a4e61751a0..c29bcd33857e 100644 --- a/user_guide_src/source/installation/index.rst +++ b/user_guide_src/source/installation/index.rst @@ -19,6 +19,7 @@ Which is right for you? installing_manual running upgrading + ../changelogs/index troubleshooting repositories diff --git a/user_guide_src/source/intro/index.rst b/user_guide_src/source/intro/index.rst index 2a815c7d6d2b..4daafc228876 100644 --- a/user_guide_src/source/intro/index.rst +++ b/user_guide_src/source/intro/index.rst @@ -44,3 +44,4 @@ CodeIgniter is right for you if: requirements credits psr + License Agreement <../license> From 92820fa54301e4875107460619ce67932b4702e9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 10:44:58 +0900 Subject: [PATCH 261/407] test: add tests for current validation behaviors --- tests/system/Validation/FormatRulesTest.php | 67 +++++++++++++++ tests/system/Validation/ValidationTest.php | 95 +++++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/tests/system/Validation/FormatRulesTest.php b/tests/system/Validation/FormatRulesTest.php index 9a2e9bd46efc..1d7a0b33dc85 100644 --- a/tests/system/Validation/FormatRulesTest.php +++ b/tests/system/Validation/FormatRulesTest.php @@ -797,6 +797,73 @@ public function numericProvider(): Generator ]; } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5374 + * + * @dataProvider integerInvalidTypeDataProvider + * + * @param mixed $value + */ + public function testIntegerWithInvalidTypeData($value, bool $expected): void + { + $this->validation->setRules([ + 'foo' => 'integer', + ]); + + $data = [ + 'foo' => $value, + ]; + $this->assertsame($expected, $this->validation->run($data)); + } + + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5374 + * + * @dataProvider integerInvalidTypeDataProvider + * + * @param mixed $value + */ + public function testNumericWithInvalidTypeData($value, bool $expected): void + { + $this->validation->setRules([ + 'foo' => 'numeric', + ]); + + $data = [ + 'foo' => $value, + ]; + $this->assertsame($expected, $this->validation->run($data)); + } + + public function integerInvalidTypeDataProvider(): Generator + { + yield 'array with int' => [ + [555], + true, // incorrect + ]; + + // TypeError : CodeIgniter\Validation\FormatRules::integer(): Argument #1 ($str) must be of type ?string, array given + // yield 'empty array' => [ + // [], + // false, + // ]; + + yield 'bool true' => [ + true, + true, // incorrect + ]; + + yield 'bool false' => [ + false, + false, + ]; + + yield 'null' => [ + null, + false, + ]; + } + /** * @dataProvider integerProvider */ diff --git a/tests/system/Validation/ValidationTest.php b/tests/system/Validation/ValidationTest.php index cffde6abf3bd..f218117a70f8 100644 --- a/tests/system/Validation/ValidationTest.php +++ b/tests/system/Validation/ValidationTest.php @@ -100,6 +100,101 @@ public function testRunDoesTheBasics(): void $this->assertFalse($this->validation->run($data)); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5368 + * + * @dataProvider arrayDataProvider + * + * @param mixed $value + */ + public function testCanValidatetArrayData($value, bool $expected): void + { + $this->validation->setRules(['arr' => 'is_array']); + + $data['arr'] = $value; + $this->assertSame($expected, $this->validation->run($data)); + } + + public function arrayDataProvider(): Generator + { + yield 'list array' => [ + [1, 2, 3, 4, 5], + false, // incorrect + ]; + + yield 'associative array' => [ + [ + 'username' => 'admin001', + 'role' => 'administrator', + 'usepass' => 0, + ], + false, // incorrect + ]; + + yield 'int' => [ + 0, + false, + ]; + + yield 'string int' => [ + '0', + false, + ]; + + yield 'bool' => [ + false, + false, + ]; + + yield 'null' => [ + null, + false, + ]; + } + + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5374 + * + * @dataProvider isIntInvalidTypeDataProvider + * + * @param mixed $value + */ + public function testIsIntWithInvalidTypeData($value, bool $expected): void + { + $this->validation->setRules(['foo' => 'is_int']); + + $data = ['foo' => $value]; + $this->assertSame($expected, $this->validation->run($data)); + } + + public function isIntInvalidTypeDataProvider(): Generator + { + yield 'array with int' => [ + [555], + true, // incorrect + ]; + + yield 'empty array' => [ + [], + false, + ]; + + yield 'bool true' => [ + true, + false, + ]; + + yield 'bool false' => [ + false, + false, + ]; + + yield 'null' => [ + null, + false, + ]; + } + public function testRunReturnsLocalizedErrors(): void { $data = ['foo' => 'notanumber']; From 61e476a36249048106c603a1412abeefc02fd7b4 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 10:53:47 +0900 Subject: [PATCH 262/407] refactor: pass valid type value to method/function --- system/Validation/Validation.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index 876ab3caffa0..e28a704a31b9 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -295,7 +295,8 @@ protected function processRules(string $field, ?string $label, $value, $rules = $value = json_encode($value); } - $this->errors[$field] = $error ?? $this->getErrorMessage($rule, $field, $label, $param, $value); + $param = ($param === false) ? '' : $param; + $this->errors[$field] = $error ?? $this->getErrorMessage($rule, $field, $label, $param, (string) $value); return false; } @@ -646,6 +647,9 @@ public function setError(string $field, string $error): ValidationInterface */ protected function getErrorMessage(string $rule, string $field, ?string $label = null, ?string $param = null, ?string $value = null): string { + $param = $param ?? ''; + + // Check if custom message has been defined by user if (isset($this->customErrors[$field][$rule])) { $message = lang($this->customErrors[$field][$rule]); } else { From cfd27fbdb0ecaa6a9501c88a94c4215f39274e18 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 10:59:36 +0900 Subject: [PATCH 263/407] docs: fix typo in comment --- system/Validation/Validation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index e28a704a31b9..20f388fb59ff 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -261,7 +261,7 @@ protected function processRules(string $field, ?string $label, $value, $rules = // Placeholder for custom errors from the rules. $error = null; - // If it's a callable, call and and get out of here. + // If it's a callable, call and get out of here. if ($isCallable) { $passed = $param === false ? $rule($value) : $rule($value, $param, $data); } else { From 6b3121d0ffe199c4b71ffe6ba37bb87c3180e083 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 11:00:36 +0900 Subject: [PATCH 264/407] fix: cast $value to string, because it may be int/bool/null... --- system/Validation/Validation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index 20f388fb59ff..f2c467c95e13 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -215,7 +215,7 @@ protected function processRules(string $field, ?string $label, $value, $rules = } if (in_array('permit_empty', $rules, true)) { - if (! in_array('required', $rules, true) && (is_array($value) ? $value === [] : trim($value ?? '') === '')) { + if (! in_array('required', $rules, true) && (is_array($value) ? $value === [] : trim((string) $value) === '')) { $passed = true; foreach ($rules as $rule) { From 16b027f8514edf71a39cd47291af8f3c53b6a9c7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 11:09:43 +0900 Subject: [PATCH 265/407] fix: separate process of multiple field and single field --- system/Validation/Validation.php | 12 ++++++++---- tests/system/Validation/FormatRulesTest.php | 9 +++++---- tests/system/Validation/ValidationTest.php | 6 +++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index f2c467c95e13..c2a31790e2cc 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -139,16 +139,20 @@ public function run(?array $data = null, ?string $group = null, ?string $dbGroup } $values = dot_array_search($field, $data); - $values = is_array($values) ? $values : [$values]; if ($values === []) { // We'll process the values right away if an empty array $this->processRules($field, $setup['label'] ?? $field, $values, $rules, $data); } - foreach ($values as $value) { - // Otherwise, we'll let the loop do the job - $this->processRules($field, $setup['label'] ?? $field, $value, $rules, $data); + if (strpos($field, '*') !== false && is_array($values)) { + // Process multiple fields + foreach ($values as $value) { + $this->processRules($field, $setup['label'] ?? $field, $value, $rules, $data); + } + } else { + // Process single field + $this->processRules($field, $setup['label'] ?? $field, $values, $rules, $data); } } diff --git a/tests/system/Validation/FormatRulesTest.php b/tests/system/Validation/FormatRulesTest.php index 1d7a0b33dc85..411c173fcf8d 100644 --- a/tests/system/Validation/FormatRulesTest.php +++ b/tests/system/Validation/FormatRulesTest.php @@ -837,10 +837,11 @@ public function testNumericWithInvalidTypeData($value, bool $expected): void public function integerInvalidTypeDataProvider(): Generator { - yield 'array with int' => [ - [555], - true, // incorrect - ]; + // TypeError : CodeIgniter\Validation\FormatRules::integer(): Argument #1 ($str) must be of type ?string, array given + // yield 'array with int' => [ + // [555], + // false, + // ]; // TypeError : CodeIgniter\Validation\FormatRules::integer(): Argument #1 ($str) must be of type ?string, array given // yield 'empty array' => [ diff --git a/tests/system/Validation/ValidationTest.php b/tests/system/Validation/ValidationTest.php index f218117a70f8..d075b7b59151 100644 --- a/tests/system/Validation/ValidationTest.php +++ b/tests/system/Validation/ValidationTest.php @@ -119,7 +119,7 @@ public function arrayDataProvider(): Generator { yield 'list array' => [ [1, 2, 3, 4, 5], - false, // incorrect + true, ]; yield 'associative array' => [ @@ -128,7 +128,7 @@ public function arrayDataProvider(): Generator 'role' => 'administrator', 'usepass' => 0, ], - false, // incorrect + true, ]; yield 'int' => [ @@ -171,7 +171,7 @@ public function isIntInvalidTypeDataProvider(): Generator { yield 'array with int' => [ [555], - true, // incorrect + false, ]; yield 'empty array' => [ From aac0a51bce155190ba9239921fa5f49705feabcf Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 11:14:47 +0900 Subject: [PATCH 266/407] style: break long lines --- system/Validation/Validation.php | 36 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index c2a31790e2cc..e915e8c46528 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -198,11 +198,15 @@ protected function processRules(string $field, ?string $label, $value, $rules = // that can be used later $ifExistField = str_replace('\.\*', '\.(?:[^\.]+)', preg_quote($field, '/')); - $dataIsExisting = array_reduce(array_keys($flattenedData), static function ($carry, $item) use ($ifExistField) { - $pattern = sprintf('/%s/u', $ifExistField); - - return $carry || preg_match($pattern, $item) === 1; - }, false); + $dataIsExisting = array_reduce( + array_keys($flattenedData), + static function ($carry, $item) use ($ifExistField) { + $pattern = sprintf('/%s/u', $ifExistField); + + return $carry || preg_match($pattern, $item) === 1; + }, + false + ); } else { $dataIsExisting = array_key_exists($ifExistField, $flattenedData); } @@ -219,7 +223,10 @@ protected function processRules(string $field, ?string $label, $value, $rules = } if (in_array('permit_empty', $rules, true)) { - if (! in_array('required', $rules, true) && (is_array($value) ? $value === [] : trim((string) $value) === '')) { + if ( + ! in_array('required', $rules, true) + && (is_array($value) ? $value === [] : trim((string) $value) === '') + ) { $passed = true; foreach ($rules as $rule) { @@ -278,7 +285,8 @@ protected function processRules(string $field, ?string $label, $value, $rules = } $found = true; - $passed = $param === false ? $set->{$rule}($value, $error) : $set->{$rule}($value, $param, $data, $error); + $passed = $param === false ? $set->{$rule}($value, $error) + : $set->{$rule}($value, $param, $data, $error); break; } @@ -300,7 +308,13 @@ protected function processRules(string $field, ?string $label, $value, $rules = } $param = ($param === false) ? '' : $param; - $this->errors[$field] = $error ?? $this->getErrorMessage($rule, $field, $label, $param, (string) $value); + $this->errors[$field] = $error ?? $this->getErrorMessage( + $rule, + $field, + $label, + $param, + (string) $value + ); return false; } @@ -664,7 +678,11 @@ protected function getErrorMessage(string $rule, string $field, ?string $label = } $message = str_replace('{field}', empty($label) ? $field : lang($label), $message); - $message = str_replace('{param}', empty($this->rules[$param]['label']) ? $param : lang($this->rules[$param]['label']), $message); + $message = str_replace( + '{param}', + empty($this->rules[$param]['label']) ? $param : lang($this->rules[$param]['label']), + $message + ); return str_replace('{value}', $value ?? '', $message); } From a42a641bd946537bf280e9c8c53b4b46ab1665d2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 29 Nov 2021 11:42:25 +0900 Subject: [PATCH 267/407] docs: add about Validation result changes in Upgrading --- .../source/installation/upgrade_416.rst | 55 +++++++++++++++++++ .../source/installation/upgrading.rst | 1 + 2 files changed, 56 insertions(+) create mode 100644 user_guide_src/source/installation/upgrade_416.rst diff --git a/user_guide_src/source/installation/upgrade_416.rst b/user_guide_src/source/installation/upgrade_416.rst new file mode 100644 index 000000000000..2735e4b07aa4 --- /dev/null +++ b/user_guide_src/source/installation/upgrade_416.rst @@ -0,0 +1,55 @@ +############################# +Upgrading from 4.1.5 to 4.1.6 +############################# + +.. contents:: + :local: + :depth: 2 + +Breaking Changes +**************** + +Validation result changes +========================= + +The previous version of the Validation can't handle an array item. +Because of the bug fix, the validation results may be different, +or raise an TypeError. +But the previous version's results are probably incorrect. + +And the Validation separated the validation process of multiple field +like ``contacts.*.name`` and single field. +When a single field has an array data, the previous version validates each element of the array. +The validation rule gets an element of the array as the parameter. +On the other hand, the current version passes the array to the validation rule as a whole. + +Breaking Enhancements +********************* + +Project Files +************* + +Numerous files in the project space (root, app, public, writable) received updates. Due to +these files being outside of the system scope they will not be changed without your intervention. +There are some third-party CodeIgniter modules available to assist with merging changes to +the project space: `Explore on Packagist `_. + +.. note:: Except in very rare cases for bug fixes, no changes made to files for the project space + will break your application. All changes noted here are optional until the next major version, + and any mandatory changes will be covered in the sections above. + +Content Changes +=============== + +The following files received significant changes (including deprecations or visual adjustments) +and it is recommended that you merge the updated versions with your application: + +* + +All Changes +=========== + +This is a list of all files in the project space that received changes; +many will be simple comments or formatting that have no effect on the runtime: + +* diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index 0264b6eaa3bb..771392d8f81a 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -8,6 +8,7 @@ upgrading from. .. toctree:: :titlesonly: + Upgrading from 4.1.5 to 4.1.6 Upgrading from 4.1.4 to 4.1.5 Upgrading from 4.1.3 to 4.1.4 Upgrading from 4.1.2 to 4.1.3 From 0485bb79bace65e1f831e198efa75faeaa4994d1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 5 Dec 2021 11:23:55 +0900 Subject: [PATCH 268/407] docs: the longer explanation in the changelog, the upgrading section has actual tasks that need to be done when upgrading --- user_guide_src/source/changelogs/v4.1.6.rst | 16 +++++++++++++++- .../source/installation/upgrade_416.rst | 11 +---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 2bb0f77f9536..2e2c50b11869 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -7,12 +7,26 @@ Release Date: Not released .. contents:: :local: - :depth: 1 + :depth: 2 BREAKING ======== - Multiple table names will no longer be stored in ``BaseBuilder::$tableName`` - an empty string will be used instead. +.. _changelog-v416-validation-changes: + +Validation changes +------------------ +- The previous version of the Validation can't handle an array item. + Because of the bug fix, the validation results may be different, + or raise an TypeError. + But the previous version's results are probably incorrect. +- The Validation separated the validation process of multiple field + like ``contacts.*.name`` and single field. + When a single field has an array data, the previous version validates each element of the array. + The validation rule gets an element of the array as the parameter. + On the other hand, the current version passes the array to the validation rule as a whole. + Enhancements ============ - Database pane on debug toolbar now displays location where Query was called from. Also displays full backtrace. diff --git a/user_guide_src/source/installation/upgrade_416.rst b/user_guide_src/source/installation/upgrade_416.rst index 2735e4b07aa4..a0c1cbd02a1b 100644 --- a/user_guide_src/source/installation/upgrade_416.rst +++ b/user_guide_src/source/installation/upgrade_416.rst @@ -12,16 +12,7 @@ Breaking Changes Validation result changes ========================= -The previous version of the Validation can't handle an array item. -Because of the bug fix, the validation results may be different, -or raise an TypeError. -But the previous version's results are probably incorrect. - -And the Validation separated the validation process of multiple field -like ``contacts.*.name`` and single field. -When a single field has an array data, the previous version validates each element of the array. -The validation rule gets an element of the array as the parameter. -On the other hand, the current version passes the array to the validation rule as a whole. +Due to a bug fix, the Validation now might change the validation results when you validate an array item (see :ref:`Changelog `). So check the validation results for all the code that validates the array. Validating multiple fields like ``contacts.*.name`` is not affected. Breaking Enhancements ********************* From 622fc0486cf675f82533532cffbc9b6267a686ed Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 4 Dec 2021 11:39:30 +0900 Subject: [PATCH 269/407] docs: add space after `,` in sample code --- user_guide_src/source/dbmgmt/forge.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/user_guide_src/source/dbmgmt/forge.rst b/user_guide_src/source/dbmgmt/forge.rst index 720f77655d54..29f35e7a83f0 100644 --- a/user_guide_src/source/dbmgmt/forge.rst +++ b/user_guide_src/source/dbmgmt/forge.rst @@ -230,18 +230,18 @@ Adding Foreign Keys Foreign Keys help to enforce relationships and actions across your tables. For tables that support Foreign Keys, you may add them directly in forge:: - $forge->addForeignKey('users_id','users','id'); + $forge->addForeignKey('users_id', 'users', 'id'); // gives CONSTRAINT `TABLENAME_users_foreign` FOREIGN KEY(`users_id`) REFERENCES `users`(`id`) - $forge->addForeignKey(['users_id', 'users_name'],'users',['id', 'name']); + $forge->addForeignKey(['users_id', 'users_name'], 'users', ['id', 'name']); // gives CONSTRAINT `TABLENAME_users_foreign` FOREIGN KEY(`users_id`, `users_name`) REFERENCES `users`(`id`, `name`) You can specify the desired action for the "on delete" and "on update" properties of the constraint:: - $forge->addForeignKey('users_id','users','id','CASCADE','CASCADE'); + $forge->addForeignKey('users_id', 'users', 'id', 'CASCADE', 'CASCADE'); // gives CONSTRAINT `TABLENAME_users_foreign` FOREIGN KEY(`users_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE - $forge->addForeignKey(['users_id', 'users_name'],'users',['id', 'name'],'CASCADE','CASCADE'); + $forge->addForeignKey(['users_id', 'users_name'], 'users', ['id', 'name'], 'CASCADE', 'CASCADE'); // gives CONSTRAINT `TABLENAME_users_foreign` FOREIGN KEY(`users_id`, `users_name`) REFERENCES `users`(`id`, `name`) ON DELETE CASCADE ON UPDATE CASCADE Creating a table @@ -302,7 +302,7 @@ Execute a DROP FOREIGN KEY. :: // Produces: ALTER TABLE `tablename` DROP FOREIGN KEY `users_foreign` - $forge->dropForeignKey('tablename','users_foreign'); + $forge->dropForeignKey('tablename', 'users_foreign'); Dropping a Key @@ -313,7 +313,7 @@ Execute a DROP KEY. :: // Produces: DROP INDEX `users_index` ON `tablename` - $forge->dropKey('tablename','users_index'); + $forge->dropKey('tablename', 'users_index'); Renaming a table ================ From a0a55ed84447904cb64e176294daa1d46f04c340 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 6 Dec 2021 17:09:05 +0900 Subject: [PATCH 270/407] fix: when useAutoIncrement is disabled, countAllResults() is called --- system/Model.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/Model.php b/system/Model.php index c73e5c716778..bcc1d46a48c6 100644 --- a/system/Model.php +++ b/system/Model.php @@ -584,12 +584,12 @@ public function set($key, $value = '', ?bool $escape = null) */ protected function shouldUpdate($data): bool { - // When useAutoIncrement feature is disabled check + // When useAutoIncrement feature is disabled, check // in the database if given record already exists return parent::shouldUpdate($data) - && $this->useAutoIncrement + && ($this->useAutoIncrement ? true - : $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1; + : $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1); } /** From 35b612b075c6e7cc7930f05ff817f6f5f05fad03 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 6 Dec 2021 21:01:49 +0900 Subject: [PATCH 271/407] refactor: early return Complex conditions cause bugs. --- system/Model.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/system/Model.php b/system/Model.php index bcc1d46a48c6..767f7de08048 100644 --- a/system/Model.php +++ b/system/Model.php @@ -584,12 +584,15 @@ public function set($key, $value = '', ?bool $escape = null) */ protected function shouldUpdate($data): bool { + if (parent::shouldUpdate($data) === false) { + return false; + } + // When useAutoIncrement feature is disabled, check // in the database if given record already exists - return parent::shouldUpdate($data) - && ($this->useAutoIncrement + return $this->useAutoIncrement ? true - : $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1); + : $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1; } /** From 41f56cfb68fa18f6eed793e2eeef93b642884ced Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 6 Dec 2021 21:29:15 +0900 Subject: [PATCH 272/407] style: add line break Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- system/Validation/Validation.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index e915e8c46528..288fe8e02653 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -285,7 +285,8 @@ static function ($carry, $item) use ($ifExistField) { } $found = true; - $passed = $param === false ? $set->{$rule}($value, $error) + $passed = $param === false + ? $set->{$rule}($value, $error) : $set->{$rule}($value, $param, $data, $error); break; From dfdba23f490d5f07d2d1d28c1f810d18802b044e Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 6 Dec 2021 21:30:01 +0900 Subject: [PATCH 273/407] docs: fix by proofreading Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/changelogs/v4.1.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 2e2c50b11869..4cddcc21f953 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -19,7 +19,7 @@ Validation changes ------------------ - The previous version of the Validation can't handle an array item. Because of the bug fix, the validation results may be different, - or raise an TypeError. + or raise a ``TypeError``. But the previous version's results are probably incorrect. - The Validation separated the validation process of multiple field like ``contacts.*.name`` and single field. From 82573aad8ae410aa433544b805052677201d34b2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 6 Dec 2021 21:30:53 +0900 Subject: [PATCH 274/407] style: add new line --- system/Validation/Validation.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index 288fe8e02653..67cf1a16853d 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -308,7 +308,8 @@ static function ($carry, $item) use ($ifExistField) { $value = json_encode($value); } - $param = ($param === false) ? '' : $param; + $param = ($param === false) ? '' : $param; + $this->errors[$field] = $error ?? $this->getErrorMessage( $rule, $field, From d16b5ea53f3ddd2218325e9b220c4343fb40e0a3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 6 Dec 2021 22:03:11 +0900 Subject: [PATCH 275/407] fix: $this->processRules() may run twice --- system/Validation/Validation.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index 67cf1a16853d..39af6703f8df 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -143,6 +143,8 @@ public function run(?array $data = null, ?string $group = null, ?string $dbGroup if ($values === []) { // We'll process the values right away if an empty array $this->processRules($field, $setup['label'] ?? $field, $values, $rules, $data); + + continue; } if (strpos($field, '*') !== false && is_array($values)) { From 1533fa038a71216f8fbd0b8cc0977cdcffc3d766 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 7 Dec 2021 10:15:55 +0900 Subject: [PATCH 276/407] docs: add or improve links to other sections --- user_guide_src/source/changelogs/v4.1.5.rst | 4 ++-- user_guide_src/source/dbmgmt/forge.rst | 1 + user_guide_src/source/incoming/routing.rst | 4 +++- user_guide_src/source/installation/upgrade_415.rst | 4 +++- user_guide_src/source/libraries/security.rst | 2 ++ 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/changelogs/v4.1.5.rst b/user_guide_src/source/changelogs/v4.1.5.rst index 9cd543f181e2..67589933074f 100644 --- a/user_guide_src/source/changelogs/v4.1.5.rst +++ b/user_guide_src/source/changelogs/v4.1.5.rst @@ -21,12 +21,12 @@ Enhancements ============ - Added Cache config for reserved characters -- The ``addForeignKey`` function of the ``Forge`` class can now define composite foreign keys in an array +- The :ref:`addForeignKey()` function of the ``Forge`` class can now define composite foreign keys in an array - The ``dropKey`` function of the ``Forge`` class can remove key - Now ``_`` can be used as separators in environment variable - Added Multiple filters for a route and Classname filter - Reduced memory usage of ``insertBatch()`` and ``updateBatch()`` -- Added Session based CSRF Protection +- Added :ref:`Session based CSRF Protection ` - Added ``valid_url_strict`` rule for ``Validation`` - Debug Toolbar - Added formatted query string to timeline diff --git a/user_guide_src/source/dbmgmt/forge.rst b/user_guide_src/source/dbmgmt/forge.rst index 29f35e7a83f0..bbaa01490b0e 100644 --- a/user_guide_src/source/dbmgmt/forge.rst +++ b/user_guide_src/source/dbmgmt/forge.rst @@ -223,6 +223,7 @@ and unique keys with specific methods:: $forge->addUniqueKey(['blog_id', 'uri']); // gives UNIQUE KEY `blog_id_uri` (`blog_id`, `uri`) +.. _adding-foreign-keys: Adding Foreign Keys =================== diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 0e9f3bb4e6be..97c2b1aa1fdd 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -354,6 +354,8 @@ can modify the generated routes, or further restrict them. The ``$options`` arra $routes->map($array, $options); $routes->group('name', $options, function ()); +.. _applying-filters: + Applying Filters ---------------- @@ -390,7 +392,7 @@ You specify a filter classname for the filter value:: **Multiple filters** -.. important:: *Multiple filters* is disabled by default. Because it breaks backward compatibility. If you want to use it, you need to configure. See *Multiple filters for a route* in :doc:`/installation/upgrade_415` for the details. +.. important:: *Multiple filters* is disabled by default. Because it breaks backward compatibility. If you want to use it, you need to configure. See :ref:`upgrade-415-multiple-filters-for-a-route` for the details. You specify an array for the filter value:: diff --git a/user_guide_src/source/installation/upgrade_415.rst b/user_guide_src/source/installation/upgrade_415.rst index c7b885efa40a..a029724b3bfb 100644 --- a/user_guide_src/source/installation/upgrade_415.rst +++ b/user_guide_src/source/installation/upgrade_415.rst @@ -72,6 +72,8 @@ For optimization and a bug fix, the following behaviors, mostly used in testing, Breaking Enhancements ===================== +.. _upgrade-415-multiple-filters-for-a-route: + Multiple filters for a route ---------------------------- @@ -99,7 +101,7 @@ The following methods and a property have been deprecated: - ``CodeIgniter\Router\RouteCollection::getFilterForRoute()`` - ``CodeIgniter\Router\RouteCollection``'s property ``$filterInfo`` -See *Applying Filters* in :doc:`Routing ` for the functionality. +See :ref:`applying-filters` for the functionality. Project Files ============= diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index 9b317a75ea91..b0a11af06b6d 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -29,6 +29,8 @@ Cross-site request forgery (CSRF) Config for CSRF =============== +.. _csrf-protection-methods: + CSRF Protection Methods ----------------------- From 4ed62286f861347fd045c748ddcd7b5be8cd0609 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 7 Dec 2021 11:17:36 +0900 Subject: [PATCH 277/407] docs: remove out-of-dated
    It seems not used now. --- contributing/documentation.rst | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/contributing/documentation.rst b/contributing/documentation.rst index 03164f183e6e..d8756cc1623c 100644 --- a/contributing/documentation.rst +++ b/contributing/documentation.rst @@ -16,21 +16,9 @@ It is created automatically by inserting the following: .. contents:: :local: - .. raw:: html - -
    - .. contents:: :local: -.. raw:: html - -
    - -The
    that is inserted as raw HTML is a event for the documentation's -JavaScript to dynamically add links to any function and method definitions -contained in the current page. - ************** Tools Required ************** From a5d5d7eba3c15e5c1570e671dde24129cf388f17 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 7 Dec 2021 11:18:18 +0900 Subject: [PATCH 278/407] docs: add depth to sample code --- contributing/documentation.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/contributing/documentation.rst b/contributing/documentation.rst index d8756cc1623c..3e6c3f43204f 100644 --- a/contributing/documentation.rst +++ b/contributing/documentation.rst @@ -15,6 +15,7 @@ It is created automatically by inserting the following: .. contents:: :local: + :depth: 2 .. contents:: :local: From 6c1a326e8cb68c8211b7ff1fb55ef69f9a4cd150 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 7 Dec 2021 11:18:46 +0900 Subject: [PATCH 279/407] docs: add how to make references --- contributing/documentation.rst | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/contributing/documentation.rst b/contributing/documentation.rst index 3e6c3f43204f..eba3eb99437e 100644 --- a/contributing/documentation.rst +++ b/contributing/documentation.rst @@ -81,3 +81,32 @@ create these with the following tab triggers:: SubSubSubSubSection (!) """"""""""""""""""""""" + +********** +References +********** + +References to a Section +======================= + +If you need to link to a specific section, the first you add the label before a header:: + + .. _curlrequest-request-options-headers: + + headers + ======= + +And then you can reference it like this:: + + See :ref:`CURLRequest Class ` for how to add. + + See :ref:`curlrequest-request-options-headers` for how to add. + +References to a Page +==================== + +You can reference a page like the following:: + + :doc:`Session <../libraries/sessions>` library + + :doc:`../libraries/sessions` library From 1911a805a8c906e10dca1320d26e3100e9d88f39 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 7 Dec 2021 11:26:48 +0900 Subject: [PATCH 280/407] docs: update the user guide URL --- user_guide_src/ghpages.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/ghpages.rst b/user_guide_src/ghpages.rst index 15619a060e0d..682c1eee49ce 100644 --- a/user_guide_src/ghpages.rst +++ b/user_guide_src/ghpages.rst @@ -8,7 +8,7 @@ in the meantime. The user guide takes advantage of GitHub pages, where the "gh-pages" branch of a repo, containing HTML only, is accessible through `github.io -`_. +`_. Setup for Repo Maintainers ========================== From c873c354ca0e4d6ab5d491e807d14678a3f39f23 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 7 Dec 2021 12:51:56 +0900 Subject: [PATCH 281/407] refactor: add \ for regex string Both the string before and after the change are the same string in PHP, but I got a pattern error when I entered the string before the change in https://regex101.com/. --- system/Helpers/array_helper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Helpers/array_helper.php b/system/Helpers/array_helper.php index 423f9c266dd5..258a1874a766 100644 --- a/system/Helpers/array_helper.php +++ b/system/Helpers/array_helper.php @@ -20,7 +20,8 @@ */ function dot_array_search(string $index, array $array) { - $segments = preg_split('/(? Date: Tue, 7 Dec 2021 12:54:27 +0900 Subject: [PATCH 282/407] style: break long line --- system/Helpers/array_helper.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/Helpers/array_helper.php b/system/Helpers/array_helper.php index 258a1874a766..2f8a5f9c8366 100644 --- a/system/Helpers/array_helper.php +++ b/system/Helpers/array_helper.php @@ -21,7 +21,12 @@ function dot_array_search(string $index, array $array) { // See https://regex101.com/r/44Ipql/1 - $segments = preg_split('/(? Date: Tue, 7 Dec 2021 17:16:54 +0900 Subject: [PATCH 283/407] refactor: early return --- system/Model.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/Model.php b/system/Model.php index 767f7de08048..418b3057eeb9 100644 --- a/system/Model.php +++ b/system/Model.php @@ -588,11 +588,13 @@ protected function shouldUpdate($data): bool return false; } + if ($this->useAutoIncrement === true) { + return true; + } + // When useAutoIncrement feature is disabled, check // in the database if given record already exists - return $this->useAutoIncrement - ? true - : $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1; + return $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1; } /** From bb82f4e76035075d36fcf455d6ce4fd0c295fea2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 7 Dec 2021 18:32:51 +0900 Subject: [PATCH 284/407] refactor: compare it to the return value to make it easier to understand what it is doing Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- system/I18n/Time.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/I18n/Time.php b/system/I18n/Time.php index c182bee32e7e..01698444587d 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -479,7 +479,7 @@ public function getQuarter(): string */ public function getDst(): bool { - return (bool) $this->format('I'); + return $this->format('I') === '1'; // 1 if Daylight Saving Time, 0 otherwise. } /** From 9ddc23980d8ad21e69ff5e04fb766690ccf33e53 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 10:02:37 +0900 Subject: [PATCH 285/407] fix: string literals to be enclosed in single quotes Fixes #5423 --- system/Database/MySQLi/Connection.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/system/Database/MySQLi/Connection.php b/system/Database/MySQLi/Connection.php index 62881620c46b..9736bf0b03c6 100644 --- a/system/Database/MySQLi/Connection.php +++ b/system/Database/MySQLi/Connection.php @@ -100,19 +100,19 @@ public function connect(bool $persistent = false) if ($this->strictOn) { $this->mysqli->options( MYSQLI_INIT_COMMAND, - 'SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")' + "SET SESSION sql_mode = CONCAT(@@sql_mode, ',', 'STRICT_ALL_TABLES')" ); } else { $this->mysqli->options( MYSQLI_INIT_COMMAND, - 'SET SESSION sql_mode = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( + "SET SESSION sql_mode = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( @@sql_mode, - "STRICT_ALL_TABLES,", ""), - ",STRICT_ALL_TABLES", ""), - "STRICT_ALL_TABLES", ""), - "STRICT_TRANS_TABLES,", ""), - ",STRICT_TRANS_TABLES", ""), - "STRICT_TRANS_TABLES", "")' + 'STRICT_ALL_TABLES,', ''), + ',STRICT_ALL_TABLES', ''), + 'STRICT_ALL_TABLES', ''), + 'STRICT_TRANS_TABLES,', ''), + ',STRICT_TRANS_TABLES', ''), + 'STRICT_TRANS_TABLES', '')" ); } } From e943b691e1f5b71cbf390c899f566bb41de88a25 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 1 Dec 2021 15:26:38 +0900 Subject: [PATCH 286/407] feat: add SecureHeaders filter --- app/Config/Filters.php | 11 ++-- system/Filters/SecureHeaders.php | 71 ++++++++++++++++++++++ tests/system/Filters/SecureHeadersTest.php | 40 ++++++++++++ user_guide_src/source/incoming/filters.rst | 2 +- 4 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 system/Filters/SecureHeaders.php create mode 100644 tests/system/Filters/SecureHeadersTest.php diff --git a/app/Config/Filters.php b/app/Config/Filters.php index 02aaec533c17..14685207f71b 100644 --- a/app/Config/Filters.php +++ b/app/Config/Filters.php @@ -7,6 +7,7 @@ use CodeIgniter\Filters\DebugToolbar; use CodeIgniter\Filters\Honeypot; use CodeIgniter\Filters\InvalidChars; +use CodeIgniter\Filters\SecureHeaders; class Filters extends BaseConfig { @@ -17,10 +18,11 @@ class Filters extends BaseConfig * @var array */ public $aliases = [ - 'csrf' => CSRF::class, - 'toolbar' => DebugToolbar::class, - 'honeypot' => Honeypot::class, - 'invalidchars' => InvalidChars::class, + 'csrf' => CSRF::class, + 'toolbar' => DebugToolbar::class, + 'honeypot' => Honeypot::class, + 'invalidchars' => InvalidChars::class, + 'secureheaders' => SecureHeaders::class, ]; /** @@ -38,6 +40,7 @@ class Filters extends BaseConfig 'after' => [ 'toolbar', // 'honeypot', + // 'secureheaders', ], ]; diff --git a/system/Filters/SecureHeaders.php b/system/Filters/SecureHeaders.php new file mode 100644 index 000000000000..fd656af6a80f --- /dev/null +++ b/system/Filters/SecureHeaders.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Filters; + +use CodeIgniter\HTTP\RequestInterface; +use CodeIgniter\HTTP\ResponseInterface; + +/** + * Add Common Security Headers + */ +class SecureHeaders implements FilterInterface +{ + /** + * @var array + */ + protected $headers = [ + // https://owasp.org/www-project-secure-headers/#x-frame-options + 'X-Frame-Options' => 'SAMEORIGIN', + + // https://owasp.org/www-project-secure-headers/#x-content-type-options + 'X-Content-Type-Options' => 'nosniff', + + // https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/jj542450(v=vs.85)#the-noopen-directive + 'X-Download-Options' => 'noopen', + + // https://owasp.org/www-project-secure-headers/#x-permitted-cross-domain-policies + 'X-Permitted-Cross-Domain-Policies' => 'none', + + // https://owasp.org/www-project-secure-headers/#referrer-policy + 'Referrer-Policy' => 'same-origin', + + // https://owasp.org/www-project-secure-headers/#x-xss-protection + // If you do not need to support legacy browsers, it is recommended that you use + // Content-Security-Policy without allowing unsafe-inline scripts instead. + // 'X-XSS-Protection' => '1; mode=block', + ]; + + /** + * We don't have anything to do here. + * + * @param array|null $arguments + * + * @return void + */ + public function before(RequestInterface $request, $arguments = null) + { + } + + /** + * Add security headers. + * + * @param array|null $arguments + * + * @return void + */ + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + { + foreach ($this->headers as $header => $value) { + $response->setHeader($header, $value); + } + } +} diff --git a/tests/system/Filters/SecureHeadersTest.php b/tests/system/Filters/SecureHeadersTest.php new file mode 100644 index 000000000000..038ef81003ab --- /dev/null +++ b/tests/system/Filters/SecureHeadersTest.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Filters; + +use CodeIgniter\Config\Services; +use CodeIgniter\Test\CIUnitTestCase; + +/** + * @internal + */ +final class SecureHeadersTest extends CIUnitTestCase +{ + protected $request; + protected $response; + + public function testAfter() + { + $filter = new SecureHeaders(); + $request = Services::request(null, false); + $response = Services::response(null, false); + + $filter->after($request, $response); + + $responseHeaders = $response->headers(); + $headers = $this->getPrivateProperty($filter, 'headers'); + + foreach ($headers as $header => $value) { + $this->assertSame($value, $responseHeaders[$header]->getValue()); + } + } +} diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 60e2ea90cc76..f0d6d7fbf6cb 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -193,6 +193,6 @@ In this example, the array ``['dual', 'noreturn']`` will be passed in ``$argumen Provided Filters **************** -The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``DebugToolbar``, and ``InvalidChars``. +The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``InvalidChars``, ``SecureHeaders``, and ``DebugToolbar``. .. note:: The filters are executed in the order defined in the config file. However, if enabled, ``DebugToolbar`` is always executed last because it should be able to capture everything that happens in the other filters. From 32ca70c732274d28f5d945f84eda1888ad29f891 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 8 Dec 2021 10:01:18 +0900 Subject: [PATCH 287/407] docs: add how to customize SecureHeaders --- user_guide_src/source/incoming/filters.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index f0d6d7fbf6cb..bbed197e7702 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -196,3 +196,17 @@ Provided Filters The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``InvalidChars``, ``SecureHeaders``, and ``DebugToolbar``. .. note:: The filters are executed in the order defined in the config file. However, if enabled, ``DebugToolbar`` is always executed last because it should be able to capture everything that happens in the other filters. + +SecureHeaders +============= + +This filter adds HTTP response headers that your application can use to increase the security of your application. + +If you want to customize the headers, extend ``CodeIgniter\Filters\SecureHeaders`` and override the ``$headers`` property. And change the ``$aliases`` property in **app/Config/Filters.php**:: + + public $aliases = [ + ... + 'secureheaders' => \App\Filters\SecureHeaders::class, + ]; + +If you want to know about secure headers, see `OWASP Secure Headers Project `_. From 27d9984476d17a1e997ac98961f88e555b4768af Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 16:03:58 +0900 Subject: [PATCH 288/407] fix: move secure cookie check from Security to CookieStore --- system/Cookie/CookieStore.php | 8 ++++++ system/Security/Security.php | 3 --- tests/system/HTTP/ResponseSendTest.php | 36 ++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/system/Cookie/CookieStore.php b/system/Cookie/CookieStore.php index 87dc472d1fe5..3edcd506d644 100644 --- a/system/Cookie/CookieStore.php +++ b/system/Cookie/CookieStore.php @@ -13,6 +13,8 @@ use ArrayIterator; use CodeIgniter\Cookie\Exceptions\CookieException; +use CodeIgniter\Security\Exceptions\SecurityException; +use Config\Services; use Countable; use IteratorAggregate; use Traversable; @@ -161,7 +163,13 @@ public function remove(string $name, string $prefix = '') */ public function dispatch(): void { + $request = Services::request(); + foreach ($this->cookies as $cookie) { + if ($cookie->isSecure() && ! $request->isSecure()) { + throw SecurityException::forDisallowedAction(); + } + $name = $cookie->getPrefixedName(); $value = $cookie->getValue(); $options = $cookie->getOptions(); diff --git a/system/Security/Security.php b/system/Security/Security.php index 35e889a85d69..dd03d4ac68d9 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -538,9 +538,6 @@ private function saveHashInCookie(): void */ protected function sendCookie(RequestInterface $request) { - if ($this->cookie->isSecure() && ! $request->isSecure()) { - return false; - } $this->doSendCookie(); log_message('info', 'CSRF cookie sent.'); diff --git a/tests/system/HTTP/ResponseSendTest.php b/tests/system/HTTP/ResponseSendTest.php index 5fedc69da7b1..6610321040a2 100644 --- a/tests/system/HTTP/ResponseSendTest.php +++ b/tests/system/HTTP/ResponseSendTest.php @@ -11,8 +11,10 @@ namespace CodeIgniter\HTTP; +use CodeIgniter\Security\Exceptions\SecurityException; use CodeIgniter\Test\CIUnitTestCase; use Config\App; +use Config\Services; /** * This test suite has been created separately from @@ -135,4 +137,38 @@ public function testRedirectResponseCookies() $this->assertHeaderEmitted('Set-Cookie: foo=bar;'); $this->assertHeaderEmitted('Set-Cookie: login_time'); } + + /** + * Make sure secure cookies are not sent with HTTP request + * + * @ runInSeparateProcess + * @ preserveGlobalState disabled + */ + public function testDoNotSendUnSecureCookie(): void + { + $this->expectException(SecurityException::class); + $this->expectExceptionMessage('The action you requested is not allowed'); + + $request = $this->createMock(IncomingRequest::class); + $request->method('isSecure')->willReturn(false); + Services::injectMock('request', $request); + + $response = new Response(new App()); + $response->pretend(false); + $body = 'Hello'; + $response->setBody($body); + + $response->setCookie( + 'foo', + 'bar', + '', + '', + '/', + '', + true + ); + + // send it + $response->send(); + } } From a3c65d75fef7c95fb322214544aaa89383bb80c6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 16:06:36 +0900 Subject: [PATCH 289/407] docs: fix doc comments --- system/HTTP/ResponseTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 7ec5f1e69e6b..39657af8464f 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -22,7 +22,7 @@ use InvalidArgumentException; /** - * Request Trait + * Response Trait * * Additional methods to make a PSR-7 Response class * compliant with the framework's own ResponseInterface. @@ -446,7 +446,7 @@ public function send() } /** - * Sends the headers of this HTTP request to the browser. + * Sends the headers of this HTTP response to the browser. * * @return Response */ From fd72e192cb9050abf6233bdd4f2daa10a73d4739 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 16:06:58 +0900 Subject: [PATCH 290/407] test: fix setUp() --- tests/system/CommonFunctionsTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index ba4c1e7a4e07..c6f1d6b9b2e1 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -41,10 +41,10 @@ final class CommonFunctionsTest extends CIUnitTestCase { protected function setUp(): void { - parent::setUp(); - $renderer = Services::renderer(); - $renderer->resetData(); unset($_ENV['foo'], $_SERVER['foo']); + Services::reset(); + + parent::setUp(); } public function testStringifyAttributes() From 3aadd002fa4753cfe5ae97aed93fb9a278ff423a Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 16:09:28 +0900 Subject: [PATCH 291/407] fix: Security class does not send cookies Add Response::setCookieStore() --- system/HTTP/ResponseTrait.php | 8 ++++ system/Security/Security.php | 28 ++----------- tests/system/Security/SecurityTest.php | 58 +++----------------------- 3 files changed, 17 insertions(+), 77 deletions(-) diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 39657af8464f..46835cc515c6 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -596,6 +596,14 @@ public function getCookieStore() return $this->cookieStore; } + /** + * Sets the CookieStore. + */ + public function setCookieStore(CookieStore $cookieStore) + { + $this->cookieStore = $cookieStore; + } + /** * Checks to see if the Response has a specified cookie or not. */ diff --git a/system/Security/Security.php b/system/Security/Security.php index dd03d4ac68d9..a484310d40c5 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -528,32 +528,12 @@ private function saveHashInCookie(): void 'expires' => $this->expires === 0 ? 0 : time() + $this->expires, ] ); - $this->sendCookie($this->request); - } - - /** - * CSRF Send Cookie - * - * @return false|Security - */ - protected function sendCookie(RequestInterface $request) - { - - $this->doSendCookie(); - log_message('info', 'CSRF cookie sent.'); - return $this; - } + $response = Services::response(); + $cookieStore = $response->getCookieStore(); + $cookieStore = $cookieStore->put($this->cookie); - /** - * Actual dispatching of cookies. - * Extracted for this to be unit tested. - * - * @codeCoverageIgnore - */ - protected function doSendCookie(): void - { - cookies([$this->cookie], false)->dispatch(); + $response->setCookieStore($cookieStore); } private function saveHashInSession(): void diff --git a/tests/system/Security/SecurityTest.php b/tests/system/Security/SecurityTest.php index cc9fcf753853..6bb8d3a809b5 100644 --- a/tests/system/Security/SecurityTest.php +++ b/tests/system/Security/SecurityTest.php @@ -20,8 +20,8 @@ use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\Mock\MockAppConfig; use CodeIgniter\Test\Mock\MockSecurity; -use Config\Cookie as CookieConfig; use Config\Security as SecurityConfig; +use Config\Services; /** * @backupGlobals enabled @@ -41,11 +41,7 @@ protected function setUp(): void public function testBasicConfigIsSaved() { - $config = new MockAppConfig(); - $security = $this->getMockBuilder(Security::class) - ->setConstructorArgs([$config]) - ->onlyMethods(['doSendCookie']) - ->getMock(); + $security = new MockSecurity(new MockAppConfig()); $hash = $security->getHash(); @@ -57,11 +53,7 @@ public function testHashIsReadFromCookie() { $_COOKIE['csrf_cookie_name'] = '8b9218a55906f9dcc1dc263dce7f005a'; - $config = new MockAppConfig(); - $security = $this->getMockBuilder(Security::class) - ->setConstructorArgs([$config]) - ->onlyMethods(['doSendCookie']) - ->getMock(); + $security = new MockSecurity(new MockAppConfig()); $this->assertSame('8b9218a55906f9dcc1dc263dce7f005a', $security->getHash()); } @@ -74,7 +66,8 @@ public function testGetHashSetsCookieWhenGETWithoutCSRFCookie() $security->verify(new Request(new MockAppConfig())); - $this->assertSame($_COOKIE['csrf_cookie_name'], $security->getHash()); + $cookie = Services::response()->getCookie('csrf_cookie_name'); + $this->assertSame($security->getHash(), $cookie->getValue()); } public function testGetHashReturnsCSRFCookieWhenGETWithCSRFCookie() @@ -238,45 +231,4 @@ public function testGetters(): void $this->assertIsString($security->getCookieName()); $this->assertIsBool($security->shouldRedirect()); } - - public function testSendingCookiesFalse(): void - { - $request = $this->createMock(IncomingRequest::class); - $request->method('isSecure')->willReturn(false); - - $config = new CookieConfig(); - - $config->secure = true; - Factories::injectMock('config', CookieConfig::class, $config); - - $security = $this->getMockBuilder(Security::class) - ->setConstructorArgs([new MockAppConfig()]) - ->onlyMethods(['doSendCookie']) - ->getMock(); - - $sendCookie = $this->getPrivateMethodInvoker($security, 'sendCookie'); - - $security->expects($this->never())->method('doSendCookie'); - $this->assertFalse($sendCookie($request)); - } - - public function testSendingGoodCookies(): void - { - $request = $this->createMock(IncomingRequest::class); - $request->method('isSecure')->willReturn(true); - - $config = new MockAppConfig(); - - $config->cookieSecure = true; - - $security = $this->getMockBuilder(Security::class) - ->setConstructorArgs([$config]) - ->onlyMethods(['doSendCookie']) - ->getMock(); - - $sendCookie = $this->getPrivateMethodInvoker($security, 'sendCookie'); - - $security->expects($this->once())->method('doSendCookie'); - $this->assertInstanceOf(Security::class, $sendCookie($request)); - } } From 7ea464cd4d44b713d4d86a558bcf23865cc69b53 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 16:10:36 +0900 Subject: [PATCH 292/407] test: break long lines --- tests/system/Security/SecurityTest.php | 69 ++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/tests/system/Security/SecurityTest.php b/tests/system/Security/SecurityTest.php index 6bb8d3a809b5..160e35b17cb6 100644 --- a/tests/system/Security/SecurityTest.php +++ b/tests/system/Security/SecurityTest.php @@ -55,7 +55,10 @@ public function testHashIsReadFromCookie() $security = new MockSecurity(new MockAppConfig()); - $this->assertSame('8b9218a55906f9dcc1dc263dce7f005a', $security->getHash()); + $this->assertSame( + '8b9218a55906f9dcc1dc263dce7f005a', + $security->getHash() + ); } public function testGetHashSetsCookieWhenGETWithoutCSRFCookie() @@ -89,7 +92,12 @@ public function testCSRFVerifyPostThrowsExceptionOnNoMatch() $_COOKIE['csrf_cookie_name'] = '8b9218a55906f9dcc1dc263dce7f005b'; $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); $this->expectException(SecurityException::class); $security->verify($request); @@ -103,7 +111,12 @@ public function testCSRFVerifyPostReturnsSelfOnMatch() $_COOKIE['csrf_cookie_name'] = '8b9218a55906f9dcc1dc263dce7f005a'; $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); @@ -117,7 +130,12 @@ public function testCSRFVerifyHeaderThrowsExceptionOnNoMatch() $_COOKIE['csrf_cookie_name'] = '8b9218a55906f9dcc1dc263dce7f005b'; $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); $request->setHeader('X-CSRF-TOKEN', '8b9218a55906f9dcc1dc263dce7f005a'); @@ -132,7 +150,12 @@ public function testCSRFVerifyHeaderReturnsSelfOnMatch() $_COOKIE['csrf_cookie_name'] = '8b9218a55906f9dcc1dc263dce7f005a'; $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); $request->setHeader('X-CSRF-TOKEN', '8b9218a55906f9dcc1dc263dce7f005a'); @@ -148,9 +171,16 @@ public function testCSRFVerifyJsonThrowsExceptionOnNoMatch() $_COOKIE['csrf_cookie_name'] = '8b9218a55906f9dcc1dc263dce7f005b'; $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); - $request->setBody('{"csrf_test_name":"8b9218a55906f9dcc1dc263dce7f005a"}'); + $request->setBody( + '{"csrf_test_name":"8b9218a55906f9dcc1dc263dce7f005a"}' + ); $this->expectException(SecurityException::class); $security->verify($request); @@ -162,9 +192,16 @@ public function testCSRFVerifyJsonReturnsSelfOnMatch() $_COOKIE['csrf_cookie_name'] = '8b9218a55906f9dcc1dc263dce7f005a'; $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); - $request->setBody('{"csrf_test_name":"8b9218a55906f9dcc1dc263dce7f005a","foo":"bar"}'); + $request->setBody( + '{"csrf_test_name":"8b9218a55906f9dcc1dc263dce7f005a","foo":"bar"}' + ); $this->assertInstanceOf(Security::class, $security->verify($request)); $this->assertLogged('info', 'CSRF token verified.'); @@ -192,7 +229,12 @@ public function testRegenerateWithFalseSecurityRegenerateProperty() Factories::injectMock('config', 'Security', $config); $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); $oldHash = $security->getHash(); $security->verify($request); @@ -212,7 +254,12 @@ public function testRegenerateWithTrueSecurityRegenerateProperty() Factories::injectMock('config', 'Security', $config); $security = new MockSecurity(new MockAppConfig()); - $request = new IncomingRequest(new MockAppConfig(), new URI('http://badurl.com'), null, new UserAgent()); + $request = new IncomingRequest( + new MockAppConfig(), + new URI('http://badurl.com'), + null, + new UserAgent() + ); $oldHash = $security->getHash(); $security->verify($request); From 628db685b1fa1667535f08aa50828739cebcd707 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 2 Dec 2021 17:29:18 +0900 Subject: [PATCH 293/407] test: fix setUp() --- tests/system/HTTP/ResponseTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/system/HTTP/ResponseTest.php b/tests/system/HTTP/ResponseTest.php index b4eba4c547c9..a94cd8e8b2b5 100644 --- a/tests/system/HTTP/ResponseTest.php +++ b/tests/system/HTTP/ResponseTest.php @@ -30,14 +30,18 @@ final class ResponseTest extends CIUnitTestCase protected function setUp(): void { - parent::setUp(); $this->server = $_SERVER; + + Services::reset(); + + parent::setUp(); } protected function tearDown(): void { - $_SERVER = $this->server; Factories::reset('config'); + + $_SERVER = $this->server; } public function testCanSetStatusCode() From d94cca96462ff14108160ed447b4814d964f4a4f Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 09:24:55 +0900 Subject: [PATCH 294/407] chore: add rule Cookie depends on Security --- depfile.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/depfile.yaml b/depfile.yaml index 2c87969f4fc4..61b85383b329 100644 --- a/depfile.yaml +++ b/depfile.yaml @@ -157,6 +157,8 @@ ruleset: Controller: - HTTP - Validation + Cookie: + - Security Database: - Entity - Events From d472ec1faafaee79e386aa68176b88f98c3eae7b Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 19:52:07 +0900 Subject: [PATCH 295/407] refactor: move cookie dispatching to Response class --- system/Cookie/CookieStore.php | 14 +++++------ system/HTTP/ResponseTrait.php | 47 ++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/system/Cookie/CookieStore.php b/system/Cookie/CookieStore.php index 3edcd506d644..af7dd2f0e437 100644 --- a/system/Cookie/CookieStore.php +++ b/system/Cookie/CookieStore.php @@ -13,8 +13,6 @@ use ArrayIterator; use CodeIgniter\Cookie\Exceptions\CookieException; -use CodeIgniter\Security\Exceptions\SecurityException; -use Config\Services; use Countable; use IteratorAggregate; use Traversable; @@ -160,16 +158,12 @@ public function remove(string $name, string $prefix = '') /** * Dispatches all cookies in store. + * + * @deprecated Response should dispatch cookies. */ public function dispatch(): void { - $request = Services::request(); - foreach ($this->cookies as $cookie) { - if ($cookie->isSecure() && ! $request->isSecure()) { - throw SecurityException::forDisallowedAction(); - } - $name = $cookie->getPrefixedName(); $value = $cookie->getValue(); $options = $cookie->getOptions(); @@ -240,6 +234,8 @@ protected function validateCookies(array $cookies): void * Extracted call to `setrawcookie()` in order to run unit tests on it. * * @codeCoverageIgnore + * + * @deprecated */ protected function setRawCookie(string $name, string $value, array $options): void { @@ -250,6 +246,8 @@ protected function setRawCookie(string $name, string $value, array $options): vo * Extracted call to `setcookie()` in order to run unit tests on it. * * @codeCoverageIgnore + * + * @deprecated */ protected function setCookie(string $name, string $value, array $options): void { diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 46835cc515c6..3b2a42c9b82d 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -16,6 +16,7 @@ use CodeIgniter\Cookie\Exceptions\CookieException; use CodeIgniter\HTTP\Exceptions\HTTPException; use CodeIgniter\Pager\PagerInterface; +use CodeIgniter\Security\Exceptions\SecurityException; use Config\Services; use DateTime; use DateTimeZone; @@ -697,7 +698,51 @@ protected function sendCookies() return; } - $this->cookieStore->dispatch(); + $this->dispatchCookies(); + } + + private function dispatchCookies(): void + { + /** @var IncomingRequest $request */ + $request = Services::request(); + + foreach ($this->cookieStore->display() as $cookie) { + if ($cookie->isSecure() && ! $request->isSecure()) { + throw SecurityException::forDisallowedAction(); + } + + $name = $cookie->getPrefixedName(); + $value = $cookie->getValue(); + $options = $cookie->getOptions(); + + if ($cookie->isRaw()) { + $this->doSetRawCookie($name, $value, $options); + } else { + $this->doSetCookie($name, $value, $options); + } + } + + $this->cookieStore->clear(); + } + + /** + * Extracted call to `setrawcookie()` in order to run unit tests on it. + * + * @codeCoverageIgnore + */ + private function doSetRawCookie(string $name, string $value, array $options): void + { + setrawcookie($name, $value, $options); + } + + /** + * Extracted call to `setcookie()` in order to run unit tests on it. + * + * @codeCoverageIgnore + */ + private function doSetCookie(string $name, string $value, array $options): void + { + setcookie($name, $value, $options); } /** From 246f3358ba33118f842cfc32a76f500feb506f5e Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 19:53:56 +0900 Subject: [PATCH 296/407] refactor: add @var To explicitly indicate dependency --- system/Security/Security.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/Security/Security.php b/system/Security/Security.php index a484310d40c5..bacbc9ee74d9 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -13,6 +13,7 @@ use CodeIgniter\Cookie\Cookie; use CodeIgniter\HTTP\RequestInterface; +use CodeIgniter\HTTP\Response; use CodeIgniter\Security\Exceptions\SecurityException; use CodeIgniter\Session\Session; use Config\App; @@ -529,6 +530,7 @@ private function saveHashInCookie(): void ] ); + /** @var Response $response */ $response = Services::response(); $cookieStore = $response->getCookieStore(); $cookieStore = $cookieStore->put($this->cookie); From 11e22972ca7190026b42bad84195ed11a9d934da Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 19:55:38 +0900 Subject: [PATCH 297/407] chore: update deptrac rule --- depfile.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/depfile.yaml b/depfile.yaml index 61b85383b329..301f17076f82 100644 --- a/depfile.yaml +++ b/depfile.yaml @@ -157,8 +157,6 @@ ruleset: Controller: - HTTP - Validation - Cookie: - - Security Database: - Entity - Events @@ -174,6 +172,7 @@ ruleset: HTTP: - Cookie - Files + - Security - URI Images: - Files From 3376a7cbe4e188bb32906a8040b9cc26791e7d0e Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 20:10:10 +0900 Subject: [PATCH 298/407] fix: restore removed methods as deprecated --- system/Security/Security.php | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/system/Security/Security.php b/system/Security/Security.php index bacbc9ee74d9..344ef5cfe00c 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -538,6 +538,38 @@ private function saveHashInCookie(): void $response->setCookieStore($cookieStore); } + /** + * CSRF Send Cookie + * + * @return false|Security + * + * @deprecated Set cookies to Response object instead. + */ + protected function sendCookie(RequestInterface $request) + { + if ($this->cookie->isSecure() && ! $request->isSecure()) { + return false; + } + + $this->doSendCookie(); + log_message('info', 'CSRF cookie sent.'); + + return $this; + } + + /** + * Actual dispatching of cookies. + * Extracted for this to be unit tested. + * + * @codeCoverageIgnore + * + * @deprecated Set cookies to Response object instead. + */ + protected function doSendCookie(): void + { + cookies([$this->cookie], false)->dispatch(); + } + private function saveHashInSession(): void { $this->session->set($this->tokenName, $this->hash); From 23ba12cfe1b3ee5354559258cde5947120a16c54 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 4 Dec 2021 10:35:43 +0900 Subject: [PATCH 299/407] feat: Response::setCookie() can get Cookie object as the first parameter --- system/HTTP/ResponseTrait.php | 24 +++++++++++++++--------- tests/system/HTTP/ResponseCookieTest.php | 11 +++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 3b2a42c9b82d..7caa5ebbbcca 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -536,15 +536,15 @@ public function redirect(string $uri, string $method = 'auto', ?int $code = null * Accepts an arbitrary number of binds (up to 7) or an associative * array in the first parameter containing all the values. * - * @param array|string $name Cookie name or array containing binds - * @param string $value Cookie value - * @param string $expire Cookie expiration time in seconds - * @param string $domain Cookie domain (e.g.: '.yourdomain.com') - * @param string $path Cookie path (default: '/') - * @param string $prefix Cookie name prefix - * @param bool $secure Whether to only transfer cookies via SSL - * @param bool $httponly Whether only make the cookie accessible via HTTP (no javascript) - * @param string|null $samesite + * @param array|Cookie|string $name Cookie name / array containing binds / Cookie object + * @param string $value Cookie value + * @param string $expire Cookie expiration time in seconds + * @param string $domain Cookie domain (e.g.: '.yourdomain.com') + * @param string $path Cookie path (default: '/') + * @param string $prefix Cookie name prefix + * @param bool $secure Whether to only transfer cookies via SSL + * @param bool $httponly Whether only make the cookie accessible via HTTP (no javascript) + * @param string|null $samesite * * @return $this */ @@ -559,6 +559,12 @@ public function setCookie( $httponly = false, $samesite = null ) { + if ($name instanceof Cookie) { + $this->cookieStore = $this->cookieStore->put($name); + + return $this; + } + if (is_array($name)) { // always leave 'name' in last place, as the loop will break otherwise, due to $$item foreach (['samesite', 'value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name'] as $item) { diff --git a/tests/system/HTTP/ResponseCookieTest.php b/tests/system/HTTP/ResponseCookieTest.php index 721a2fbd47b7..678928463cc4 100644 --- a/tests/system/HTTP/ResponseCookieTest.php +++ b/tests/system/HTTP/ResponseCookieTest.php @@ -65,6 +65,17 @@ public function testCookiesAll() $this->assertTrue($response->hasCookie('bee')); } + public function testSetCookieObject() + { + $cookie = new Cookie('foo', 'bar'); + $response = new Response(new App()); + + $response->setCookie($cookie); + + $this->assertCount(1, $response->getCookies()); + $this->assertTrue($response->hasCookie('foo')); + } + public function testCookieGet() { $response = new Response(new App()); From 943b4e04051774fa5be8ca89ea8667dc7dca832b Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 4 Dec 2021 10:37:53 +0900 Subject: [PATCH 300/407] refactor: use Response::setCookie() --- system/HTTP/ResponseTrait.php | 8 -------- system/Security/Security.php | 7 ++----- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 7caa5ebbbcca..278143fd3c3a 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -603,14 +603,6 @@ public function getCookieStore() return $this->cookieStore; } - /** - * Sets the CookieStore. - */ - public function setCookieStore(CookieStore $cookieStore) - { - $this->cookieStore = $cookieStore; - } - /** * Checks to see if the Response has a specified cookie or not. */ diff --git a/system/Security/Security.php b/system/Security/Security.php index 344ef5cfe00c..008e94aeb612 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -531,11 +531,8 @@ private function saveHashInCookie(): void ); /** @var Response $response */ - $response = Services::response(); - $cookieStore = $response->getCookieStore(); - $cookieStore = $cookieStore->put($this->cookie); - - $response->setCookieStore($cookieStore); + $response = Services::response(); + $response->setCookie($this->cookie); } /** From 6817dc6f5f99cf9636e36479daf0259c512f136d Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 8 Dec 2021 10:21:19 +0900 Subject: [PATCH 301/407] docs: fix header level --- user_guide_src/source/changelogs/v4.1.6.rst | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 4cddcc21f953..e747e9181fa8 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -10,13 +10,15 @@ Release Date: Not released :depth: 2 BREAKING -======== +******** + - Multiple table names will no longer be stored in ``BaseBuilder::$tableName`` - an empty string will be used instead. .. _changelog-v416-validation-changes: Validation changes ------------------- +================== + - The previous version of the Validation can't handle an array item. Because of the bug fix, the validation results may be different, or raise a ``TypeError``. @@ -28,14 +30,15 @@ Validation changes On the other hand, the current version passes the array to the validation rule as a whole. Enhancements -============ +************ + - Database pane on debug toolbar now displays location where Query was called from. Also displays full backtrace. Changes -======= +******* Deprecations -============ +************ Bugs Fixed -========== +********** From 49cd87991b218e67641557285ef5f3b4ba3c51fb Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 8 Dec 2021 10:46:06 +0900 Subject: [PATCH 302/407] docs: add changelog and update Response::setCookie() --- user_guide_src/source/changelogs/v4.1.6.rst | 14 ++++++++++++++ user_guide_src/source/outgoing/response.rst | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index e747e9181fa8..82b03127cda2 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -37,8 +37,22 @@ Enhancements Changes ******* +- The process of sending cookies has been moved to the ``Response`` class. Now the ``Security`` and ``CookieStore`` class don't send cookies, set them to the Response. + Deprecations ************ +Sending Cookies +=============== + +The process of sending cookies has been moved to the ``Response`` class. +And the following methods are deprecated: + +- ``CookieStore::dispatch()`` +- ``CookieStore::setRawCookie()`` +- ``CookieStore::setCookie()`` +- ``Security::sendCookie()`` +- ``Security::doSendCookie()`` + Bugs Fixed ********** diff --git a/user_guide_src/source/outgoing/response.rst b/user_guide_src/source/outgoing/response.rst index 060e2cd28291..2cd619dbd390 100644 --- a/user_guide_src/source/outgoing/response.rst +++ b/user_guide_src/source/outgoing/response.rst @@ -396,7 +396,7 @@ The methods provided by the parent class that are available are: .. php:method:: setCookie($name = ''[, $value = ''[, $expire = ''[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = false[, $httponly = false[, $samesite = null]]]]]]]]) - :param mixed $name: Cookie name or an array of parameters + :param array|Cookie|string $name: Cookie name or an array of parameters or an instance of ``CodeIgniter\Cookie\Cookie`` :param string $value: Cookie value :param int $expire: Cookie expiration time in seconds :param string $domain: Cookie domain From 004f42ab6c8169ed518aec8dad3662312a74babe Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 30 Nov 2021 16:46:20 +0900 Subject: [PATCH 303/407] fix: SQL in MySQLi\Connection::_foreignKeyData() Fixes #4996 --- system/Database/MySQLi/Connection.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/Database/MySQLi/Connection.php b/system/Database/MySQLi/Connection.php index 9736bf0b03c6..5badaf1c4881 100644 --- a/system/Database/MySQLi/Connection.php +++ b/system/Database/MySQLi/Connection.php @@ -485,8 +485,10 @@ protected function _foreignKeyData(string $table): array FROM information_schema.TABLE_CONSTRAINTS AS tc INNER JOIN information_schema.REFERENTIAL_CONSTRAINTS AS rc ON tc.CONSTRAINT_NAME = rc.CONSTRAINT_NAME + AND tc.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA INNER JOIN information_schema.KEY_COLUMN_USAGE AS kcu ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME + AND tc.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA WHERE tc.CONSTRAINT_TYPE = ' . $this->escape('FOREIGN KEY') . ' AND tc.TABLE_SCHEMA = ' . $this->escape($this->database) . ' AND From 29f8bf85c7dbd19d88c1728f917ab60e8dd3c715 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Nov 2021 09:15:05 +0900 Subject: [PATCH 304/407] fix: is_cli() returns true when $_SERVER['HTTP_USER_AGENT'] is missing Fixes #5336 --- system/Common.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/system/Common.php b/system/Common.php index 32943189b56b..bf91834ac0b1 100644 --- a/system/Common.php +++ b/system/Common.php @@ -643,16 +643,7 @@ function helper($filenames) */ function is_cli(): bool { - if (defined('STDIN')) { - return true; - } - - if (! isset($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']) && isset($_SERVER['argv']) && count($_SERVER['argv']) > 0) { - return true; - } - - // if source of request is from CLI, the `$_SERVER` array will not populate this key - return ! isset($_SERVER['REQUEST_METHOD']); + return in_array(PHP_SAPI, ['cli', 'phpdbg'], true); } } From 00fc5852a8fc199e70e967b84faa7cbaa71b0315 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 3 Dec 2021 14:52:45 +0900 Subject: [PATCH 305/407] fix: handle edge case of 'cgi-fcgi' and 'fpm-fcgi' --- system/Common.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/system/Common.php b/system/Common.php index bf91834ac0b1..85a2506dfb9f 100644 --- a/system/Common.php +++ b/system/Common.php @@ -643,7 +643,13 @@ function helper($filenames) */ function is_cli(): bool { - return in_array(PHP_SAPI, ['cli', 'phpdbg'], true); + if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) { + return true; + } + + // PHP_SAPI could be 'cgi-fcgi', 'fpm-fcgi'. + // See https://github.com/codeigniter4/CodeIgniter4/pull/5393 + return ! isset($_SERVER['REMOTE_ADDR']) && ! isset($_SERVER['REQUEST_METHOD']); } } From 19057bff9ed577966b47605f9193d3a9b3c32df0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 9 Dec 2021 10:01:47 +0900 Subject: [PATCH 306/407] docs: improve text decoration --- user_guide_src/source/general/helpers.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/user_guide_src/source/general/helpers.rst b/user_guide_src/source/general/helpers.rst index 51deea953590..c454bee36180 100644 --- a/user_guide_src/source/general/helpers.rst +++ b/user_guide_src/source/general/helpers.rst @@ -24,10 +24,10 @@ in your :doc:`controller ` and :doc:`views `. Helpers are typically stored in your **system/Helpers**, or -**app/Helpers directory**. CodeIgniter will look first in your -**app/Helpers directory**. If the directory does not exist or the +**app/Helpers** directory. CodeIgniter will look first in your +**app/Helpers** directory. If the directory does not exist or the specified helper is not located there CI will instead look in your -global *system/Helpers/* directory. +global **system/Helpers** directory. Loading a Helper ================ @@ -36,8 +36,8 @@ Loading a helper file is quite simple using the following method:: helper('name'); -Where **name** is the file name of the helper, without the .php file -extension or the "_helper" part. +Where ``name`` is the file name of the helper, without the "**.php**" file +extension or the "**_helper**" part. For example, to load the **Cookie Helper** file, which is named **cookie_helper.php**, you would do this:: @@ -69,7 +69,7 @@ Helpers can be loaded from directories outside of **app/Helpers** and has been set up within the PSR-4 section of the :doc:`Autoloader config file <../concepts/autoloader>`. You would prefix the name of the Helper with the namespace that it can be located in. Within that namespaced directory, the loader expects it to live within a -sub-directory named ``Helpers``. An example will help understand this. +sub-directory named **Helpers**. An example will help understand this. For this example, assume that we have grouped together all of our Blog-related code into its own namespace, ``Example\Blog``. The files exist on our server at @@ -94,7 +94,7 @@ your view files you would do this:: -Where "Click Here" is the name of the link, and "blog/comments" is the +Where ``Click Here`` is the name of the link, and ``blog/comments`` is the URI to the controller/method you wish to link to. "Extending" Helpers @@ -139,7 +139,7 @@ functions:: return array_pop($array); } -The **helper()** method will scan through all PSR-4 namespaces defined in **app/Config/Autoload.php** +The ``helper()`` method will scan through all PSR-4 namespaces defined in **app/Config/Autoload.php** and load in ALL matching helpers of the same name. This allows any module's helpers to be loaded, as well as any helpers you've created specifically for this application. The load order is as follows: From 18138fa4c781b05ff4f091135644963a1024cad9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Nov 2021 17:10:10 +0900 Subject: [PATCH 307/407] fix: remove unserialize() in old() I can't think of any use cases. --- system/Common.php | 5 ----- tests/system/CommonFunctionsTest.php | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/system/Common.php b/system/Common.php index 32943189b56b..61e2716fb56b 100644 --- a/system/Common.php +++ b/system/Common.php @@ -813,11 +813,6 @@ function old(string $key, $default = null, $escape = 'html') return $default; } - // If the result was serialized array or string, then unserialize it for use... - if (is_string($value) && (strpos($value, 'a:') === 0 || strpos($value, 's:') === 0)) { - $value = unserialize($value); - } - return $escape === false ? $value : esc($value, $escape); } } diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index c6f1d6b9b2e1..0febdb038c1f 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -300,7 +300,7 @@ public function testOldInput() $_GET = ['foo' => 'bar']; $_POST = [ 'bar' => 'baz', - 'zibble' => serialize('fritz'), + 'zibble' => 'fritz', ]; $response = new RedirectResponse(new App()); From c2ab3d24504b70893be116e09fb7c8b7fa0475c6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 12:42:22 +0900 Subject: [PATCH 308/407] docs: add security advisories URL in SECURITY.md --- SECURITY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SECURITY.md b/SECURITY.md index 7879188492b5..87b894ee713c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -20,6 +20,7 @@ This person will coordinate the fix and release process, involving the following - Confirm the problem and determine the affected versions. - Audit code to find any potential similar problems. - Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible. +- Publish security advisories at https://github.com/codeigniter4/CodeIgniter4/security/advisories ## Comments on this Policy From 7c69140b65a1d4705a63c0bbd55e61171bfd132e Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 14:08:04 +0900 Subject: [PATCH 309/407] docs: remove out-of-dated comment --- tests/system/CommonFunctionsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index 0febdb038c1f..1b9bcbbbf3ad 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -308,7 +308,7 @@ public function testOldInput() $this->assertSame('bar', old('foo')); // regular parameter $this->assertSame('doo', old('yabba dabba', 'doo')); // non-existing parameter - $this->assertSame('fritz', old('zibble')); // serialized parameter + $this->assertSame('fritz', old('zibble')); } /** From 78e4b27a16300c430248c0797a2d980093ef68e2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 14:09:37 +0900 Subject: [PATCH 310/407] test: add test for serialize data --- tests/system/CommonFunctionsTest.php | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index 1b9bcbbbf3ad..35175209da64 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -311,6 +311,39 @@ public function testOldInput() $this->assertSame('fritz', old('zibble')); } + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testOldInputSerializeData() + { + $this->injectSessionMock(); + // setup from RedirectResponseTest... + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $this->config = new App(); + $this->config->baseURL = 'http://example.com/'; + + $this->routes = new RouteCollection(Services::locator(), new Modules()); + Services::injectMock('routes', $this->routes); + + $this->request = new MockIncomingRequest($this->config, new URI('http://example.com'), null, new UserAgent()); + Services::injectMock('request', $this->request); + + // setup & ask for a redirect... + $_SESSION = []; + $_GET = []; + $_POST = [ + 'zibble' => serialize('fritz'), + ]; + + $response = new RedirectResponse(new App()); + $response->withInput(); + + // serialized parameters are only HTML-escaped. + $this->assertSame('s:5:"fritz";', old('zibble')); + } + /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/1492 * @runInSeparateProcess From b2d27c354c89b740a4c63443066a06b1bdf2469e Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Nov 2021 14:24:49 +0900 Subject: [PATCH 311/407] docs: add about Deserialization of Untrusted Data in old() to changelogs/v4.1.6.rst --- user_guide_src/source/changelogs/v4.1.6.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 82b03127cda2..f3c513b48b99 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -9,6 +9,11 @@ Release Date: Not released :local: :depth: 2 +SECURITY +======== + +- *Deserialization of Untrusted Data* found in the ``old()`` function was fixed. See the `Security advisory `_ for more information. + BREAKING ******** From 19d27497ca0c5bbcfb978d23581285cef03d058f Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 08:06:30 +0900 Subject: [PATCH 312/407] docs: move // comments into PHPDoc --- tests/system/HTTP/IncomingRequestTest.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/system/HTTP/IncomingRequestTest.php b/tests/system/HTTP/IncomingRequestTest.php index 4229d5d264ec..2ea9dd38914f 100644 --- a/tests/system/HTTP/IncomingRequestTest.php +++ b/tests/system/HTTP/IncomingRequestTest.php @@ -107,7 +107,9 @@ public function testMissingOldInput() $this->assertNull($this->request->getOldInput('pineapple.name')); } - // Reference: https://github.com/codeigniter4/CodeIgniter4/issues/1492 + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/1492 + */ public function testCanGetOldInputArray() { $_SESSION['_ci_old_input'] = [ @@ -119,9 +121,9 @@ public function testCanGetOldInputArray() $this->assertSame(['name' => 'foo'], $this->request->getOldInput('banana')); } - // Reference: https://github.com/codeigniter4/CodeIgniter4/issues/1492 - /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/1492 + * * @runInSeparateProcess * @preserveGlobalState disabled */ From 24ae7250a91208a9dfd1ba0d14ccad6aad028d01 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Nov 2021 08:12:18 +0900 Subject: [PATCH 313/407] test: refactor: fix test method names --- tests/system/HTTP/IncomingRequestTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/HTTP/IncomingRequestTest.php b/tests/system/HTTP/IncomingRequestTest.php index 2ea9dd38914f..e8c91268a8e2 100644 --- a/tests/system/HTTP/IncomingRequestTest.php +++ b/tests/system/HTTP/IncomingRequestTest.php @@ -110,7 +110,7 @@ public function testMissingOldInput() /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/1492 */ - public function testCanGetOldInputArray() + public function testCanGetOldInputArrayWithSESSION() { $_SESSION['_ci_old_input'] = [ 'get' => ['apple' => ['name' => 'two']], @@ -127,7 +127,7 @@ public function testCanGetOldInputArray() * @runInSeparateProcess * @preserveGlobalState disabled */ - public function testCanSerializeOldArray() + public function testCanGetOldInputArrayWithSessionService() { $locations = [ 'AB' => 'Alberta', From 025a63bb2a0a0c9a1a34334b35e87f8ac19d6c96 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 9 Dec 2021 10:14:03 +0900 Subject: [PATCH 314/407] docs: update header level --- user_guide_src/source/changelogs/v4.1.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index f3c513b48b99..60b2dca40e30 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -10,7 +10,7 @@ Release Date: Not released :depth: 2 SECURITY -======== +******** - *Deserialization of Untrusted Data* found in the ``old()`` function was fixed. See the `Security advisory `_ for more information. From 6c7742cfadf4c3c3df8be9e4c2a61ea3e15cd460 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 9 Dec 2021 10:39:29 +0900 Subject: [PATCH 315/407] docs: fix wrong sample code --- user_guide_src/source/libraries/sessions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst index d38ec66e8994..cb6e78c25330 100644 --- a/user_guide_src/source/libraries/sessions.rst +++ b/user_guide_src/source/libraries/sessions.rst @@ -91,7 +91,7 @@ longer need it. So, what you need is to close the session for the current request after you no longer need it. :: - $session->destroy(); + session_write_close(); What is Session Data? ===================== From 2778b37527edd1411b3bf14285570fb481170822 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 9 Dec 2021 21:20:08 +0900 Subject: [PATCH 316/407] docs: update command option --- user_guide_src/source/dbmgmt/migration.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/dbmgmt/migration.rst b/user_guide_src/source/dbmgmt/migration.rst index 9f748da69521..4d76e04d903b 100644 --- a/user_guide_src/source/dbmgmt/migration.rst +++ b/user_guide_src/source/dbmgmt/migration.rst @@ -199,13 +199,13 @@ You can use (migrate) with the following options: - ``-g`` - to chose database group, otherwise default database group will be used. - ``-n`` - to choose namespace, otherwise (App) namespace will be used. -- ``-all`` - to migrate all namespaces to the latest migration +- ``--all`` - to migrate all namespaces to the latest migration This example will migrate Blog namespace with any new migrations on the test database group:: > php spark migrate -g test -n Blog -When using the ``-all`` option, it will scan through all namespaces attempting to find any migrations that have +When using the ``--all`` option, it will scan through all namespaces attempting to find any migrations that have not been run. These will all be collected and then sorted as a group by date created. This should help to minimize any potential conflicts between the main application and any modules. @@ -231,7 +231,7 @@ You can use (refresh) with the following options: - ``-g`` - to choose database group, otherwise default database group will be used. - ``-n`` - to choose namespace, otherwise (App) namespace will be used. -- ``-all`` - to refresh all namespaces +- ``--all`` - to refresh all namespaces - ``-f`` - to force a bypass confirmation question, it is only asked in a production environment **status** From 641873bed9c8bdc0f297aad607f8b4949b033270 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 9 Dec 2021 21:24:35 +0900 Subject: [PATCH 317/407] docs: improve command sample '\' is a meta character in the shell. --- user_guide_src/source/dbmgmt/migration.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/dbmgmt/migration.rst b/user_guide_src/source/dbmgmt/migration.rst index 4d76e04d903b..e7bd41f34bc0 100644 --- a/user_guide_src/source/dbmgmt/migration.rst +++ b/user_guide_src/source/dbmgmt/migration.rst @@ -201,9 +201,9 @@ You can use (migrate) with the following options: - ``-n`` - to choose namespace, otherwise (App) namespace will be used. - ``--all`` - to migrate all namespaces to the latest migration -This example will migrate Blog namespace with any new migrations on the test database group:: +This example will migrate ``Acme\Blog`` namespace with any new migrations on the test database group:: - > php spark migrate -g test -n Blog + > php spark migrate -g test -n 'Acme\Blog' When using the ``--all`` option, it will scan through all namespaces attempting to find any migrations that have not been run. These will all be collected and then sorted as a group by date created. This should help From 05ac0503b4f2dab6607ff796c93e548e19bc1720 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 10 Dec 2021 14:24:47 +0900 Subject: [PATCH 318/407] docs: add note and warning Waring about the possibility of bypassing the filter. --- user_guide_src/source/incoming/filters.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index bbed197e7702..267ef4c921f4 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -91,6 +91,13 @@ Configuring Filters Once you've created your filters, you need to configure when they get run. This is done in **app/Config/Filters.php**. This file contains four properties that allow you to configure exactly when the filters run. +.. Note:: The safest way to apply filters is to :ref:`disable auto-routing `, and :ref:`set filters to routes `. + +.. Warning:: It is recommended that you should always add ``*`` at the end of a URI in the filter settings. + Because a controller method might be accessible by different URLs than you think. + For example, when auto-routing is enabled, if you have ``Blog::index``, + it can be accessible with ``blog``, ``blog/index``, and ``blog/index/1``, etc. + $aliases ======== From bfd0812346b4b028f3d2970cea7806573a9a0be8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 10 Dec 2021 14:27:40 +0900 Subject: [PATCH 319/407] docs: replace uri with URI --- user_guide_src/source/incoming/filters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 267ef4c921f4..096d1020f77f 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -140,7 +140,7 @@ run on every request. Filters can be specified by adding their alias to either t There are times where you want to apply a filter to almost every request, but have a few that should be left alone. One common example is if you need to exclude a few URI's from the CSRF protection filter to allow requests from third-party websites to hit one or two specific URI's, while keeping the rest of them protected. To do this, add -an array with the 'except' key and a uri to match as the value alongside the alias:: +an array with the 'except' key and a URI to match as the value alongside the alias:: public $globals = [ 'before' => [ From 7d3f02ca53327e492ab15f3409b5f4e7ce95e68d Mon Sep 17 00:00:00 2001 From: Toto Date: Fri, 10 Dec 2021 21:49:51 +0700 Subject: [PATCH 320/407] update docs about `esc()` `null` is not `$context` --- user_guide_src/source/general/common_functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index dd4c69a9915e..c1cdb038984a 100755 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -81,7 +81,7 @@ Service Accessors If $data is a string, then it simply escapes and returns it. If $data is an array, then it loops over it, escaping each 'value' of the key/value pairs. - Valid context values: html, js, css, url, attr, raw, null + Valid context values: html, js, css, url, attr, raw .. php:function:: helper($filename) From 85de0fa9c2e753089ec3b95e9d6bc11eb4c5213b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Dec 2021 01:46:37 +0000 Subject: [PATCH 321/407] chore(deps-dev): update rector/rector requirement from 0.12.5 to 0.12.7 (#5451) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 064f7b392e05..ab1c999190bf 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.12.5" + "rector/rector": "0.12.7" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" From 19d9f111dcc87746efe4ca255062370d7a8bf31b Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 11 Dec 2021 10:59:30 +0900 Subject: [PATCH 322/407] fix: VENDORPATH definition When using multiple apps, vendor/ is not ROOTPATH/vendor/. --- system/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/bootstrap.php b/system/bootstrap.php index 17226d099974..4549fbc2c939 100644 --- a/system/bootstrap.php +++ b/system/bootstrap.php @@ -117,7 +117,7 @@ class_alias('Config\Services', 'CodeIgniter\Services'); * We do not want to enforce this, so set the constant if Composer was used. */ if (! defined('VENDORPATH')) { - define('VENDORPATH', realpath(ROOTPATH . 'vendor') . DIRECTORY_SEPARATOR); + define('VENDORPATH', dirname(COMPOSER_PATH) . DIRECTORY_SEPARATOR); } require_once COMPOSER_PATH; From 290b4d0dbf6db5dd8f57f9ba6d35c2aa8a8477b6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 11 Dec 2021 11:02:18 +0900 Subject: [PATCH 323/407] refactor: COMPOSER_PATH and VENDORPATH are defined above --- system/Test/bootstrap.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/system/Test/bootstrap.php b/system/Test/bootstrap.php index f6ddb2ad68d1..48a266d14600 100644 --- a/system/Test/bootstrap.php +++ b/system/Test/bootstrap.php @@ -84,20 +84,6 @@ class_alias('Config\Services', 'CodeIgniter\Services'); // Initialize and register the loader with the SPL autoloader stack. Services::autoloader()->initialize(new Autoload(), new Modules())->register(); -// Now load Composer's if it's available -if (is_file(COMPOSER_PATH)) { - /* - * The path to the vendor directory. - * - * We do not want to enforce this, so set the constant if Composer was used. - */ - if (! defined('VENDORPATH')) { - define('VENDORPATH', realpath(ROOTPATH . 'vendor') . DIRECTORY_SEPARATOR); - } - - require_once COMPOSER_PATH; -} - // Load environment settings from .env files into $_SERVER and $_ENV require_once SYSTEMPATH . 'Config/DotEnv.php'; From e2ec0fea517bde7319f3208c628484233b3aebb9 Mon Sep 17 00:00:00 2001 From: Toto Prayogo Date: Sat, 11 Dec 2021 10:07:18 +0700 Subject: [PATCH 324/407] remove null as `$context` Co-authored-by: kenjis --- system/Common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Common.php b/system/Common.php index 85a2506dfb9f..f531a82f7284 100644 --- a/system/Common.php +++ b/system/Common.php @@ -380,7 +380,7 @@ function env(string $key, $default = null) * If $data is an array, then it loops over it, escaping each * 'value' of the key/value pairs. * - * Valid context values: html, js, css, url, attr, raw, null + * Valid context values: html, js, css, url, attr, raw * * @param array|string $data * @param string $encoding From 9792a6b25f53640bca4d59715c58389df6bcc578 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 11 Dec 2021 13:03:35 +0900 Subject: [PATCH 325/407] fix: $fraction type NumberFormatter::setAttribute(): Passing null to parameter #2 ($value) of type int|float is deprecated --- system/Helpers/number_helper.php | 2 +- tests/system/Helpers/NumberHelperTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Helpers/number_helper.php b/system/Helpers/number_helper.php index b3d7c80c6006..7e5428455aaf 100644 --- a/system/Helpers/number_helper.php +++ b/system/Helpers/number_helper.php @@ -116,7 +116,7 @@ function number_to_amount($num, int $precision = 0, ?string $locale = null) * @param string $locale * @param int $fraction */ - function number_to_currency(float $num, string $currency, ?string $locale = null, ?int $fraction = null): string + function number_to_currency(float $num, string $currency, ?string $locale = null, int $fraction = 0): string { return format_number($num, 1, $locale, [ 'type' => NumberFormatter::CURRENCY, diff --git a/tests/system/Helpers/NumberHelperTest.php b/tests/system/Helpers/NumberHelperTest.php index 286440d7423b..006d0a650118 100755 --- a/tests/system/Helpers/NumberHelperTest.php +++ b/tests/system/Helpers/NumberHelperTest.php @@ -126,6 +126,7 @@ public function testQuadrillions() */ public function testCurrencyCurrentLocale() { + $this->assertSame('$1,235', number_to_currency(1234.56, 'USD', 'en_US')); $this->assertSame('$1,234.56', number_to_currency(1234.56, 'USD', 'en_US', 2)); $this->assertSame('£1,234.56', number_to_currency(1234.56, 'GBP', 'en_GB', 2)); $this->assertSame("1.234,56\u{a0}RSD", number_to_currency(1234.56, 'RSD', 'sr_RS', 2)); From a6eb95dcc44e194d6799dc95da203023e5fcb8b3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 11 Dec 2021 13:11:39 +0900 Subject: [PATCH 326/407] docs: remove unneeded doc comments --- system/Helpers/number_helper.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/system/Helpers/number_helper.php b/system/Helpers/number_helper.php index 7e5428455aaf..04c8b9e4c0c2 100644 --- a/system/Helpers/number_helper.php +++ b/system/Helpers/number_helper.php @@ -112,10 +112,7 @@ function number_to_amount($num, int $precision = 0, ?string $locale = null) } if (! function_exists('number_to_currency')) { - /** - * @param string $locale - * @param int $fraction - */ + function number_to_currency(float $num, string $currency, ?string $locale = null, int $fraction = 0): string { return format_number($num, 1, $locale, [ From ad3a204f6c6f1829d7ca9d1e944397dec0dc4af8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 11 Dec 2021 13:29:49 +0900 Subject: [PATCH 327/407] docs: fix number_helper.rst --- .../source/helpers/number_helper.rst | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/user_guide_src/source/helpers/number_helper.rst b/user_guide_src/source/helpers/number_helper.rst index eeca3a00614f..be5be2a8018c 100644 --- a/user_guide_src/source/helpers/number_helper.rst +++ b/user_guide_src/source/helpers/number_helper.rst @@ -27,7 +27,7 @@ Available Functions The following functions are available: -.. php:function:: number_to_size($num[, $precision = 1[, $locale = null]) +.. php:function:: number_to_size($num[, $precision = 1[, $locale = null]]) :param mixed $num: Number of bytes :param int $precision: Floating point precision @@ -86,21 +86,23 @@ The following functions are available: echo number_to_amount('123,456,789,012', 2, 'de_DE'); // Returns 123,46 billion -.. php:function:: number_to_currency($num, $currency[, $locale = null]) +.. php:function:: number_to_currency($num, $currency[, $locale = null[, $fraction = 0]]) - :param mixed $num: Number to format + :param float $num: Number to format :param string $currency: The currency type, i.e., USD, EUR, etc - :param string $locale: The locale to use for formatting + :param string|null $locale: The locale to use for formatting :param integer $fraction: Number of fraction digits after decimal point :returns: The number as the appropriate currency for the locale :rtype: string Converts a number in common currency formats, like USD, EUR, GBP, etc:: - echo number_to_currency(1234.56, 'USD'); // Returns $1,234.56 - echo number_to_currency(1234.56, 'EUR'); // Returns €1,234.56 - echo number_to_currency(1234.56, 'GBP'); // Returns £1,234.56 - echo number_to_currency(1234.56, 'YEN'); // Returns YEN1,234.56 + echo number_to_currency(1234.56, 'USD', 'en_US', 2); // Returns $1,234.56 + echo number_to_currency(1234.56, 'EUR', 'de_DE', 2); // Returns 1.234,56 € + echo number_to_currency(1234.56, 'GBP', 'en_GB', 2); // Returns £1,234.56 + echo number_to_currency(1234.56, 'YEN', 'ja_JP', 2); // Returns YEN 1,234.56 + + If you don't specify a locale, the Request locale is used. .. php:function:: number_to_roman($num) From ce3d3cc9d5a4633e6c5f464c2295420d54b807ba Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 11 Dec 2021 13:56:09 +0900 Subject: [PATCH 328/407] style: remove empty line --- system/Helpers/number_helper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/system/Helpers/number_helper.php b/system/Helpers/number_helper.php index 04c8b9e4c0c2..35e748978fbb 100644 --- a/system/Helpers/number_helper.php +++ b/system/Helpers/number_helper.php @@ -112,7 +112,6 @@ function number_to_amount($num, int $precision = 0, ?string $locale = null) } if (! function_exists('number_to_currency')) { - function number_to_currency(float $num, string $currency, ?string $locale = null, int $fraction = 0): string { return format_number($num, 1, $locale, [ From 9e9b9cd7324d43c72a493c1fb9518aa446f1a349 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 11 Dec 2021 14:17:22 +0900 Subject: [PATCH 329/407] docs: add about COMPOSER_PATH change --- user_guide_src/source/general/managing_apps.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index c967c4a296bc..8b82a697698c 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -69,8 +69,13 @@ This would have two apps, **foo** and **bar**, both having standard application and a **public** folder, and sharing a common **codeigniter** framework. The **index.php** inside each application would refer to its own configuration, -``../app/Config/Paths.php``, and the ``$systemDirectory`` variable inside each +``../app/Config/Paths.php``, and the ``$systemDirectory`` variable in **app/Config/Paths.php** inside each of those would be set to refer to the shared common **system** folder. If either of the applications had a command-line component, then you would also modify **spark** inside each application's project folder, as directed above. + +When you use Composer autoloader, fix the ``COMPOSER_PATH`` constant in **app/Config/Constants.php** inside each +of those:: + + defined('COMPOSER_PATH') || define('COMPOSER_PATH', ROOTPATH . '../vendor/autoload.php'); From 544e0c15c87bf1bb3ac5744aa7ed08c9894ad6bf Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Sat, 11 Dec 2021 16:36:48 +0800 Subject: [PATCH 330/407] The View class. Optimizing duplicate code. --- system/View/View.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/system/View/View.php b/system/View/View.php index 6005b5f40582..e65416e5cf48 100644 --- a/system/View/View.php +++ b/system/View/View.php @@ -199,11 +199,7 @@ public function render(string $view, ?array $options = null, ?bool $saveData = n } // Make our view data available to the view. - $this->tempData = $this->tempData ?? $this->data; - - if ($saveData) { - $this->data = $this->tempData; - } + $this->prepareTemplateData($saveData); // Save current vars $renderVars = $this->renderVars; @@ -275,13 +271,9 @@ public function render(string $view, ?array $options = null, ?bool $saveData = n */ public function renderString(string $view, ?array $options = null, ?bool $saveData = null): string { - $start = microtime(true); - $saveData = $saveData ?? $this->saveData; - $this->tempData = $this->tempData ?? $this->data; - - if ($saveData) { - $this->data = $this->tempData; - } + $start = microtime(true); + $saveData = $saveData ?? $this->saveData; + $this->prepareTemplateData($saveData); $output = (function (string $view): string { extract($this->tempData); @@ -454,4 +446,13 @@ protected function logPerformance(float $start, float $end, string $view) ]; } } + + protected function prepareTemplateData(bool $saveData): void + { + $this->tempData = $this->tempData ?? $this->data; + + if ($saveData) { + $this->data = $this->tempData; + } + } } From 623b1024963bbfc119c8ddfb1e7b5ecf367ba8d0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 12 Dec 2021 09:53:51 +0900 Subject: [PATCH 331/407] test: fix: restore `require_once` that was accidentally deleted --- system/Test/bootstrap.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/Test/bootstrap.php b/system/Test/bootstrap.php index 48a266d14600..00a4341c6e2a 100644 --- a/system/Test/bootstrap.php +++ b/system/Test/bootstrap.php @@ -84,6 +84,11 @@ class_alias('Config\Services', 'CodeIgniter\Services'); // Initialize and register the loader with the SPL autoloader stack. Services::autoloader()->initialize(new Autoload(), new Modules())->register(); +// Now load Composer's if it's available +if (is_file(COMPOSER_PATH)) { + require_once COMPOSER_PATH; +} + // Load environment settings from .env files into $_SERVER and $_ENV require_once SYSTEMPATH . 'Config/DotEnv.php'; From b22183c7a280debd5f084d0ffb43d723a041932e Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 12 Dec 2021 19:57:41 +0900 Subject: [PATCH 332/407] docs: add space after // --- user_guide_src/source/models/entities.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/models/entities.rst b/user_guide_src/source/models/entities.rst index 10828c0dc56b..9df5239cb820 100644 --- a/user_guide_src/source/models/entities.rst +++ b/user_guide_src/source/models/entities.rst @@ -433,7 +433,7 @@ Let's say the class will be located in the 'app/Entity/Cast' directory:: use CodeIgniter\Entity\Cast\BaseCast; - //The class must inherit the CodeIgniter\Entity\Cast\BaseCast class + // The class must inherit the CodeIgniter\Entity\Cast\BaseCast class class CastBase64 extends BaseCast { public static function get($value, array $params = []) @@ -462,13 +462,13 @@ Now you need to register it:: 'key' => 'base64', ]; - //Bind the type to the handler + // Bind the type to the handler protected $castHandlers = [ 'base64' => \App\Entity\Cast\CastBase64::class, ]; } - //... + // ... $entity->key = 'test'; // dGVzdA== echo $entity->key; // test From 46d592a0f6be3eabc14ed0c42e94a7086b7cb6b9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 12 Dec 2021 19:58:16 +0900 Subject: [PATCH 333/407] docs: align `=>` positions --- user_guide_src/source/models/entities.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/user_guide_src/source/models/entities.rst b/user_guide_src/source/models/entities.rst index 9df5239cb820..7a170aa2790c 100644 --- a/user_guide_src/source/models/entities.rst +++ b/user_guide_src/source/models/entities.rst @@ -239,10 +239,10 @@ As an example, imagine you have the simplified User Entity that is used througho class User extends Entity { protected $attributes = [ - 'id' => null, - 'name' => null, // Represents a username - 'email' => null, - 'password' => null, + 'id' => null, + 'name' => null, // Represents a username + 'email' => null, + 'password' => null, 'created_at' => null, 'updated_at' => null, ]; @@ -266,10 +266,10 @@ simply map the ``full_name`` column in the database to the ``$name`` property, a class User extends Entity { protected $attributes = [ - 'id' => null, - 'name' => null, // Represents a username - 'email' => null, - 'password' => null, + 'id' => null, + 'name' => null, // Represents a username + 'email' => null, + 'password' => null, 'created_at' => null, 'updated_at' => null, ]; From b7e0f8b20921a69f8c04a95d1a37a2cd5b78da89 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 12 Dec 2021 20:00:30 +0900 Subject: [PATCH 334/407] docs: fix the variable name --- user_guide_src/source/models/entities.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/models/entities.rst b/user_guide_src/source/models/entities.rst index 7a170aa2790c..1ac2f2c3ebf6 100644 --- a/user_guide_src/source/models/entities.rst +++ b/user_guide_src/source/models/entities.rst @@ -299,7 +299,7 @@ By default, the Entity class will convert fields named `created_at`, `updated_at :doc:`Time ` instances whenever they are set or retrieved. The Time class provides a large number of helpful methods in an immutable, localized way. -You can define which properties are automatically converted by adding the name to the **options['dates']** array:: +You can define which properties are automatically converted by adding the name to the ``$dates`` property:: Date: Sun, 12 Dec 2021 20:01:21 +0900 Subject: [PATCH 335/407] docs: fix the classname --- user_guide_src/source/models/entities.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/models/entities.rst b/user_guide_src/source/models/entities.rst index 1ac2f2c3ebf6..54c0c0ed8b00 100644 --- a/user_guide_src/source/models/entities.rst +++ b/user_guide_src/source/models/entities.rst @@ -107,8 +107,8 @@ Now that all of the pieces are in place, you would work with the Entity class as $userModel->save($user); You may have noticed that the User class has not set any properties for the columns, but you can still -access them as if they were public properties. The base class, **CodeIgniter\\Entity**, takes care of this for you, as well as providing the ability to check the properties with **isset()**, or **unset()** the property, and keep track +access them as if they were public properties. The base class, ``CodeIgniter\Entity\Entity``, takes care of this for you, as of what columns have changed since the object was created or pulled from the database. When the User is passed to the model's **save()** method, it automatically takes care of reading the properties From 155d16b222e4bcd7117182d06e489a216a9cece7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 12 Dec 2021 20:02:09 +0900 Subject: [PATCH 336/407] docs: improve text decoration Code is decrated with ``. File paths are decrated with **. --- user_guide_src/source/models/entities.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/user_guide_src/source/models/entities.rst b/user_guide_src/source/models/entities.rst index 54c0c0ed8b00..489685a8c5ff 100644 --- a/user_guide_src/source/models/entities.rst +++ b/user_guide_src/source/models/entities.rst @@ -106,13 +106,13 @@ Now that all of the pieces are in place, you would work with the Entity class as $user->email = 'foo@example.com'; $userModel->save($user); -You may have noticed that the User class has not set any properties for the columns, but you can still -well as providing the ability to check the properties with **isset()**, or **unset()** the property, and keep track +You may have noticed that the ``User`` class has not set any properties for the columns, but you can still access them as if they were public properties. The base class, ``CodeIgniter\Entity\Entity``, takes care of this for you, as +well as providing the ability to check the properties with ``isset()``, or ``unset()`` the property, and keep track of what columns have changed since the object was created or pulled from the database. -When the User is passed to the model's **save()** method, it automatically takes care of reading the properties -and saving any changes to columns listed in the model's **$allowedFields** property. It also knows whether to create +When the User is passed to the model's ``save()`` method, it automatically takes care of reading the properties +and saving any changes to columns listed in the model's ``$allowedFields`` property. It also knows whether to create a new row, or update an existing one. .. note:: When we are making a call to the ``insert()`` all the values from Entity are passed to the method, but when we @@ -123,7 +123,7 @@ Filling Properties Quickly The Entity class also provides a method, ``fill()`` that allows you to shove an array of key/value pairs into the class and populate the class properties. Any property in the array will be set on the Entity. However, when saving through -the model, only the fields in $allowedFields will actually be saved to the database, so you can store additional data +the model, only the fields in ``$allowedFields`` will actually be saved to the database, so you can store additional data on your entities without worrying much about stray fields getting saved incorrectly. :: @@ -198,7 +198,7 @@ Here's an updated User entity to provide some examples of how this could be used The first thing to notice is the name of the methods we've added. For each one, the class expects the snake_case column name to be converted into PascalCase, and prefixed with either ``set`` or ``get``. These methods will then -be automatically called whenever you set or retrieve the class property using the direct syntax (i.e., $user->email). +be automatically called whenever you set or retrieve the class property using the direct syntax (i.e., ``$user->email``). The methods do not need to be public unless you want them accessed from other classes. For example, the ``created_at`` class property will be accessed through the ``setCreatedAt()`` and ``getCreatedAt()`` methods. @@ -327,14 +327,14 @@ current timezone, as set in **app/Config/App.php**:: Property Casting ---------------- -You can specify that properties in your Entity should be converted to common data types with the **casts** property. +You can specify that properties in your Entity should be converted to common data types with the ``$casts`` property. This option should be an array where the key is the name of the class property, and the value is the data type it should be cast to. Casting only affects when values are read. No conversions happen that affect the permanent value in either the entity or the database. Properties can be cast to any of the following data types: **integer**, **float**, **double**, **string**, **boolean**, **object**, **array**, **datetime**, **timestamp**, and **uri**. Add a question mark at the beginning of type to mark property as nullable, i.e., **?string**, **?integer**. -For example, if you had a User entity with an **is_banned** property, you can cast it as a boolean:: +For example, if you had a User entity with an ``is_banned`` property, you can cast it as a boolean:: Date: Mon, 13 Dec 2021 09:14:59 +0900 Subject: [PATCH 337/407] docs: remove out of dated raw html --- user_guide_src/source/helpers/html_helper.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/user_guide_src/source/helpers/html_helper.rst b/user_guide_src/source/helpers/html_helper.rst index 3e88f19360fc..978f0ea67f04 100755 --- a/user_guide_src/source/helpers/html_helper.rst +++ b/user_guide_src/source/helpers/html_helper.rst @@ -8,10 +8,6 @@ HTML. .. contents:: :local: -.. raw:: html - -
    - Loading this Helper =================== From f941858bcf244e7925d6f0513a11efbeaf1c3312 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Mon, 13 Dec 2021 15:05:13 +0800 Subject: [PATCH 338/407] Use PHPStan's baseline instead of global ignore of errors --- phpstan-baseline.neon.dist | 1022 +++++++++++++++++ phpstan.neon.dist | 27 +- system/Autoloader/Autoloader.php | 4 +- system/Cache/Handlers/FileHandler.php | 1 - system/Cache/Handlers/MemcachedHandler.php | 6 +- system/CodeIgniter.php | 7 +- system/Common.php | 1 - system/Database/BaseConnection.php | 1 - system/Database/BaseResult.php | 2 - system/Database/Postgre/Connection.php | 1 - system/Database/SQLite3/Result.php | 16 +- system/Debug/Exceptions.php | 2 +- system/Debug/Toolbar/Collectors/Events.php | 2 +- system/Debug/Toolbar/Collectors/Views.php | 6 +- system/HTTP/CURLRequest.php | 2 +- system/HTTP/RequestTrait.php | 1 - system/HTTP/URI.php | 2 +- system/Helpers/number_helper.php | 2 +- system/Helpers/text_helper.php | 1 - system/Helpers/url_helper.php | 2 +- system/Images/Handlers/ImageMagickHandler.php | 6 +- system/Model.php | 2 +- system/Router/Router.php | 1 - system/Session/Handlers/DatabaseHandler.php | 1 - system/Session/Handlers/RedisHandler.php | 1 - system/Test/CIUnitTestCase.php | 2 +- system/Test/Fabricator.php | 6 +- system/Test/FeatureTestCase.php | 2 +- system/Test/FeatureTestTrait.php | 2 +- system/Test/Mock/MockConnection.php | 2 +- 30 files changed, 1060 insertions(+), 73 deletions(-) create mode 100644 phpstan-baseline.neon.dist diff --git a/phpstan-baseline.neon.dist b/phpstan-baseline.neon.dist new file mode 100644 index 000000000000..0a91bd7fc64f --- /dev/null +++ b/phpstan-baseline.neon.dist @@ -0,0 +1,1022 @@ +parameters: + ignoreErrors: + - + message: "#^Parameter \\#1 \\$callback of function spl_autoload_register expects \\(callable\\(string\\)\\: void\\)\\|null, array\\{\\$this\\(CodeIgniter\\\\Autoloader\\\\Autoloader\\), 'loadClass'\\} given\\.$#" + count: 1 + path: system/Autoloader/Autoloader.php + + - + message: "#^Parameter \\#1 \\$callback of function spl_autoload_register expects \\(callable\\(string\\)\\: void\\)\\|null, array\\{\\$this\\(CodeIgniter\\\\Autoloader\\\\Autoloader\\), 'loadClassmap'\\} given\\.$#" + count: 1 + path: system/Autoloader/Autoloader.php + + - + message: "#^Property Config\\\\Autoload\\:\\:\\$classmap \\(array\\\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Autoloader/Autoloader.php + + - + message: "#^Property Config\\\\Autoload\\:\\:\\$files \\(array\\\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Autoloader/Autoloader.php + + - + message: "#^Property Config\\\\Autoload\\:\\:\\$psr4 \\(array\\\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Autoloader/Autoloader.php + + - + message: "#^Method CodeIgniter\\\\Validation\\\\ValidationInterface\\:\\:run\\(\\) invoked with 3 parameters, 0\\-2 required\\.$#" + count: 1 + path: system/BaseModel.php + + - + message: "#^Property Config\\\\Cache\\:\\:\\$backupHandler \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Cache/CacheFactory.php + + - + message: "#^Property Config\\\\Cache\\:\\:\\$handler \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Cache/CacheFactory.php + + - + message: "#^Property Config\\\\Cache\\:\\:\\$validHandlers \\(array\\\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Cache/CacheFactory.php + + - + message: "#^Comparison operation \"\\>\" between int\\<1, max\\> and \\(array\\|float\\|int\\) results in an error\\.$#" + count: 1 + path: system/Cache/Handlers/FileHandler.php + + - + message: "#^If condition is always true\\.$#" + count: 1 + path: system/Cache/Handlers/FileHandler.php + + - + message: "#^Property Config\\\\Cache\\:\\:\\$storePath \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Cache/Handlers/FileHandler.php + + - + message: "#^Method MemcachePool\\:\\:decrement\\(\\) invoked with 4 parameters, 1\\-2 required\\.$#" + count: 1 + path: system/Cache/Handlers/MemcachedHandler.php + + - + message: "#^Method MemcachePool\\:\\:increment\\(\\) invoked with 4 parameters, 1\\-2 required\\.$#" + count: 1 + path: system/Cache/Handlers/MemcachedHandler.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: system/Cache/Handlers/MemcachedHandler.php + + - + message: "#^Variable \\$config in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: system/Cache/Handlers/MemcachedHandler.php + + - + message: "#^Variable \\$data might not be defined\\.$#" + count: 1 + path: system/Cache/Handlers/MemcachedHandler.php + + - + message: "#^Property Config\\\\Cache\\:\\:\\$redis \\(array\\\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Cache/Handlers/PredisHandler.php + + - + message: "#^Property CodeIgniter\\\\Cache\\\\Handlers\\\\RedisHandler\\:\\:\\$redis \\(Redis\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Cache/Handlers/RedisHandler.php + + - + message: "#^Variable \\$config in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: system/Cache/Handlers/RedisHandler.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\HTTP\\\\Request\\:\\:getPost\\(\\)\\.$#" + count: 1 + path: system/CodeIgniter.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\HTTP\\\\Request\\:\\:getSegments\\(\\)\\.$#" + count: 1 + path: system/CodeIgniter.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\HTTP\\\\Request\\:\\:setLocale\\(\\)\\.$#" + count: 1 + path: system/CodeIgniter.php + + - + message: "#^Dead catch \\- CodeIgniter\\\\Exceptions\\\\PageNotFoundException is never thrown in the try block\\.$#" + count: 1 + path: system/CodeIgniter.php + + - + message: "#^Property Config\\\\App\\:\\:\\$appTimezone \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/CodeIgniter.php + + - + message: "#^Property Config\\\\App\\:\\:\\$defaultLocale \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/CodeIgniter.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: system/CodeIgniter.php + + - + message: "#^Binary operation \"\\+\" between array\\\\|false and non\\-empty\\-array\\ results in an error\\.$#" + count: 1 + path: system/Common.php + + - + message: "#^Variable \\$params on left side of \\?\\? always exists and is not nullable\\.$#" + count: 1 + path: system/Common.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\BaseBuilder\\:\\:\\$db \\(CodeIgniter\\\\Database\\\\BaseConnection\\) in empty\\(\\) is not falsy\\.$#" + count: 1 + path: system/Database/BaseBuilder.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Database\\\\BaseConnection\\:\\:_disableForeignKeyChecks\\(\\)\\.$#" + count: 1 + path: system/Database/BaseConnection.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Database\\\\BaseConnection\\:\\:_enableForeignKeyChecks\\(\\)\\.$#" + count: 1 + path: system/Database/BaseConnection.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Database\\\\QueryInterface\\:\\:getOriginalQuery\\(\\)\\.$#" + count: 1 + path: system/Database/BaseConnection.php + + - + message: "#^Negated boolean expression is always true\\.$#" + count: 1 + path: system/Database/BaseConnection.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 3 + path: system/Database/BaseResult.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 2 + path: system/Database/BaseResult.php + + - + message: "#^While loop condition is always true\\.$#" + count: 2 + path: system/Database/BaseResult.php + + - + message: "#^Access to an undefined property CodeIgniter\\\\Database\\\\ConnectionInterface\\:\\:\\$DBDriver\\.$#" + count: 2 + path: system/Database/Database.php + + - + message: "#^Access to an undefined property CodeIgniter\\\\Database\\\\ConnectionInterface\\:\\:\\$connID\\.$#" + count: 2 + path: system/Database/Database.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\Migration\\:\\:\\$DBGroup \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Database/Migration.php + + - + message: "#^Property Config\\\\Migrations\\:\\:\\$enabled \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Database/MigrationRunner.php + + - + message: "#^Property Config\\\\Migrations\\:\\:\\$table \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Database/MigrationRunner.php + + - + message: "#^Cannot access property \\$affected_rows on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot access property \\$errno on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot access property \\$error on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot access property \\$insert_id on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method autocommit\\(\\) on bool\\|object\\|resource\\.$#" + count: 3 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method begin_transaction\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method close\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method commit\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method more_results\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method next_result\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method query\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method real_escape_string\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method rollback\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method select_db\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Cannot call method store_result\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\BaseConnection\\:\\:\\$strictOn \\(bool\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\MySQLi\\\\Connection\\:\\:\\$mysqli \\(mysqli\\) in empty\\(\\) is not falsy\\.$#" + count: 1 + path: system/Database/MySQLi/Connection.php + + - + message: "#^Access to an undefined property CodeIgniter\\\\Database\\\\BaseConnection\\:\\:\\$mysqli\\.$#" + count: 3 + path: system/Database/MySQLi/PreparedQuery.php + + - + message: "#^Cannot call method bind_param\\(\\) on object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/PreparedQuery.php + + - + message: "#^Cannot call method execute\\(\\) on object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/PreparedQuery.php + + - + message: "#^Cannot call method get_result\\(\\) on object\\|resource\\.$#" + count: 1 + path: system/Database/MySQLi/PreparedQuery.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\BasePreparedQuery\\:\\:\\$statement \\(object\\|resource\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Database/MySQLi/PreparedQuery.php + + - + message: "#^Cannot access property \\$field_count on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Cannot access property \\$num_rows on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Cannot call method data_seek\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Cannot call method fetch_assoc\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Cannot call method fetch_field\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Cannot call method fetch_fields\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Cannot call method fetch_object\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Cannot call method field_seek\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/MySQLi/Result.php + + - + message: "#^Strict comparison using \\=\\=\\= between array and false will always evaluate to false\\.$#" + count: 1 + path: system/Database/Postgre/Connection.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\BasePreparedQuery\\:\\:\\$statement \\(object\\|resource\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Database/Postgre/PreparedQuery.php + + - + message: "#^Access to an undefined property CodeIgniter\\\\Database\\\\BaseConnection\\:\\:\\$schema\\.$#" + count: 2 + path: system/Database/SQLSRV/Builder.php + + - + message: "#^Access to an undefined property CodeIgniter\\\\Database\\\\BaseConnection\\:\\:\\$schema\\.$#" + count: 14 + path: system/Database/SQLSRV/Forge.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\BasePreparedQuery\\:\\:\\$statement \\(object\\|resource\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Database/SQLSRV/PreparedQuery.php + + - + message: "#^Cannot call method changes\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method close\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method escapeString\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method exec\\(\\) on bool\\|object\\|resource\\.$#" + count: 4 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method lastErrorCode\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method lastErrorMsg\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method lastInsertRowID\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method query\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/Connection.php + + - + message: "#^Cannot call method bindValue\\(\\) on object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/PreparedQuery.php + + - + message: "#^Cannot call method execute\\(\\) on object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/PreparedQuery.php + + - + message: "#^Cannot call method lastErrorCode\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/PreparedQuery.php + + - + message: "#^Cannot call method lastErrorMsg\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/PreparedQuery.php + + - + message: "#^Cannot call method prepare\\(\\) on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Database/SQLite3/PreparedQuery.php + + - + message: "#^Property CodeIgniter\\\\Database\\\\BasePreparedQuery\\:\\:\\$statement \\(object\\|resource\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Database/SQLite3/PreparedQuery.php + + - + message: "#^Cannot call method columnName\\(\\) on object\\|resource\\|false\\.$#" + count: 2 + path: system/Database/SQLite3/Result.php + + - + message: "#^Cannot call method columnType\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/SQLite3/Result.php + + - + message: "#^Cannot call method fetchArray\\(\\) on object\\|resource\\|false\\.$#" + count: 2 + path: system/Database/SQLite3/Result.php + + - + message: "#^Cannot call method numColumns\\(\\) on object\\|resource\\|false\\.$#" + count: 1 + path: system/Database/SQLite3/Result.php + + - + message: "#^Cannot call method reset\\(\\) on object\\|resource\\|false\\.$#" + count: 2 + path: system/Database/SQLite3/Result.php + + - + message: "#^Property Config\\\\Database\\:\\:\\$filesPath \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Database/Seeder.php + + - + message: "#^Expression on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Debug/Exceptions.php + + - + message: "#^Parameter \\#4 \\$replacement of function array_splice expects array\\|string, true given\\.$#" + count: 1 + path: system/Debug/Exceptions.php + + - + message: "#^Property CodeIgniter\\\\Debug\\\\Exceptions\\:\\:\\$formatter \\(CodeIgniter\\\\Format\\\\FormatterInterface\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Debug/Exceptions.php + + - + message: "#^Property Config\\\\Exceptions\\:\\:\\$sensitiveDataInTrace \\(array\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Debug/Exceptions.php + + - + message: "#^Property Config\\\\Toolbar\\:\\:\\$collectVarData \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Debug/Toolbar.php + + - + message: "#^Variable \\$request on left side of \\?\\? always exists and is not nullable\\.$#" + count: 1 + path: system/Debug/Toolbar.php + + - + message: "#^Variable \\$response on left side of \\?\\? always exists and is not nullable\\.$#" + count: 1 + path: system/Debug/Toolbar.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\View\\\\RendererInterface\\:\\:getPerformanceData\\(\\)\\.$#" + count: 1 + path: system/Debug/Toolbar/Collectors/Events.php + + - + message: "#^Property CodeIgniter\\\\Log\\\\Logger\\:\\:\\$logCache \\(array\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Debug/Toolbar/Collectors/Logs.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\View\\\\RendererInterface\\:\\:getData\\(\\)\\.$#" + count: 1 + path: system/Debug/Toolbar/Collectors/Views.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\View\\\\RendererInterface\\:\\:getPerformanceData\\(\\)\\.$#" + count: 2 + path: system/Debug/Toolbar/Collectors/Views.php + + - + message: "#^Static property CodeIgniter\\\\Email\\\\Email\\:\\:\\$func_overload \\(bool\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Email/Email.php + + - + message: "#^Property Config\\\\Encryption\\:\\:\\$digest \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 2 + path: system/Encryption/Encryption.php + + - + message: "#^Property CodeIgniter\\\\Files\\\\File\\:\\:\\$size \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Files/File.php + + - + message: "#^Expression on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Filters/Filters.php + + - + message: "#^Property Config\\\\Filters\\:\\:\\$filters \\(array\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Filters/Filters.php + + - + message: "#^Property Config\\\\Filters\\:\\:\\$globals \\(array\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Filters/Filters.php + + - + message: "#^Property Config\\\\Filters\\:\\:\\$methods \\(array\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Filters/Filters.php + + - + message: "#^Parameter \\#1 \\$seconds of function sleep expects int, float given\\.$#" + count: 1 + path: system/HTTP/CURLRequest.php + + - + message: "#^Expression on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/HTTP/Files/UploadedFile.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\Files\\\\UploadedFile\\:\\:\\$error \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 2 + path: system/HTTP/Files/UploadedFile.php + + - + message: "#^Return type \\(bool\\) of method CodeIgniter\\\\HTTP\\\\Files\\\\UploadedFile\\:\\:move\\(\\) should be compatible with return type \\(CodeIgniter\\\\Files\\\\File\\) of method CodeIgniter\\\\Files\\\\File\\:\\:move\\(\\)$#" + count: 1 + path: system/HTTP/Files/UploadedFile.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\IncomingRequest\\:\\:\\$locale \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/HTTP/IncomingRequest.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\Message\\:\\:\\$protocolVersion \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/HTTP/Message.php + + - + message: "#^Variable \\$_GET on left side of \\?\\? always exists and is not nullable\\.$#" + count: 1 + path: system/HTTP/RedirectResponse.php + + - + message: "#^Variable \\$_POST on left side of \\?\\? always exists and is not nullable\\.$#" + count: 1 + path: system/HTTP/RedirectResponse.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\Request\\:\\:\\$proxyIPs \\(array\\|string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/HTTP/Request.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\Request\\:\\:\\$uri \\(CodeIgniter\\\\HTTP\\\\URI\\) in empty\\(\\) is not falsy\\.$#" + count: 1 + path: system/HTTP/Request.php + + - + message: "#^Property Config\\\\App\\:\\:\\$cookieSameSite \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 3 + path: system/HTTP/Response.php + + - + message: "#^Cannot unset offset 'path' on array\\{host\\: mixed\\}\\.$#" + count: 1 + path: system/HTTP/URI.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\URI\\:\\:\\$fragment \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/HTTP/URI.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\URI\\:\\:\\$host \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/HTTP/URI.php + + - + message: "#^Property CodeIgniter\\\\HTTP\\\\URI\\:\\:\\$path \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/HTTP/URI.php + + - + message: "#^Right side of && is always true\\.$#" + count: 1 + path: system/Helpers/filesystem_helper.php + + - + message: "#^Offset 'checked' on array\\{type\\: 'checkbox', name\\: mixed, value\\: string\\} in isset\\(\\) does not exist\\.$#" + count: 1 + path: system/Helpers/form_helper.php + + - + message: "#^Binary operation \"\\+\" between 0 and string results in an error\\.$#" + count: 1 + path: system/Helpers/number_helper.php + + - + message: "#^Variable \\$mockService in empty\\(\\) always exists and is always falsy\\.$#" + count: 1 + path: system/Helpers/test_helper.php + + - + message: "#^Parameter \\#2 \\$times of function str_repeat expects int, float given\\.$#" + count: 1 + path: system/Helpers/text_helper.php + + - + message: "#^Variable \\$pool might not be defined\\.$#" + count: 2 + path: system/Helpers/text_helper.php + + - + message: "#^Variable \\$count might not be defined\\.$#" + count: 1 + path: system/Helpers/url_helper.php + + - + message: "#^Property CodeIgniter\\\\Images\\\\Handlers\\\\BaseHandler\\:\\:\\$image \\(CodeIgniter\\\\Images\\\\Image\\) in empty\\(\\) is not falsy\\.$#" + count: 1 + path: system/Images/Handlers/BaseHandler.php + + - + message: "#^Comparison operation \"\\>\\=\" between \\(array\\|float\\|int\\) and 0 results in an error\\.$#" + count: 2 + path: system/Images/Handlers/ImageMagickHandler.php + + - + message: "#^PHPDoc type string\\|null of property CodeIgniter\\\\Images\\\\Handlers\\\\ImageMagickHandler\\:\\:\\$resource is not covariant with PHPDoc type resource\\|null of overridden property CodeIgniter\\\\Images\\\\Handlers\\\\BaseHandler\\:\\:\\$resource\\.$#" + count: 1 + path: system/Images/Handlers/ImageMagickHandler.php + + - + message: "#^Property CodeIgniter\\\\Images\\\\Handlers\\\\BaseHandler\\:\\:\\$height \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 4 + path: system/Images/Handlers/ImageMagickHandler.php + + - + message: "#^Property CodeIgniter\\\\Images\\\\Handlers\\\\BaseHandler\\:\\:\\$width \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 4 + path: system/Images/Handlers/ImageMagickHandler.php + + - + message: "#^Variable \\$gravity might not be defined\\.$#" + count: 1 + path: system/Images/Handlers/ImageMagickHandler.php + + - + message: "#^Variable \\$xAxis might not be defined\\.$#" + count: 1 + path: system/Images/Handlers/ImageMagickHandler.php + + - + message: "#^Variable \\$yAxis might not be defined\\.$#" + count: 1 + path: system/Images/Handlers/ImageMagickHandler.php + + - + message: "#^Property Config\\\\Logger\\:\\:\\$dateFormat \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Log/Logger.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Database\\\\BaseBuilder\\:\\:asArray\\(\\)\\.$#" + count: 1 + path: system/Model.php + + - + message: "#^Property CodeIgniter\\\\RESTful\\\\ResourceController\\:\\:\\$formatter \\(CodeIgniter\\\\Format\\\\FormatterInterface\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/RESTful/ResourceController.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getDefaultNamespace\\(\\)\\.$#" + count: 2 + path: system/Router/Router.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getFilterForRoute\\(\\)\\.$#" + count: 1 + path: system/Router/Router.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getFiltersForRoute\\(\\)\\.$#" + count: 1 + path: system/Router/Router.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getRoutesOptions\\(\\)\\.$#" + count: 2 + path: system/Router/Router.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:isFiltered\\(\\)\\.$#" + count: 1 + path: system/Router/Router.php + + - + message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:setHTTPVerb\\(\\)\\.$#" + count: 1 + path: system/Router/Router.php + + - + message: "#^Expression on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Router/Router.php + + - + message: "#^Method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getRoutes\\(\\) invoked with 1 parameter, 0 required\\.$#" + count: 2 + path: system/Router/Router.php + + - + message: "#^Property Config\\\\App\\:\\:\\$CSRFCookieName \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\App\\:\\:\\$CSRFExpire \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\App\\:\\:\\$CSRFHeaderName \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\App\\:\\:\\$CSRFRegenerate \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\App\\:\\:\\$CSRFTokenName \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\Security\\:\\:\\$cookieName \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\Security\\:\\:\\$csrfProtection \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\Security\\:\\:\\$expires \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\Security\\:\\:\\$headerName \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\Security\\:\\:\\$regenerate \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\Security\\:\\:\\$tokenName \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Property Config\\\\Security\\:\\:\\$tokenRandomize \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Security/Security.php + + - + message: "#^Access to an undefined property Config\\\\App\\:\\:\\$sessionDBGroup\\.$#" + count: 1 + path: system/Session/Handlers/DatabaseHandler.php + + - + message: "#^Property CodeIgniter\\\\Session\\\\Handlers\\\\BaseHandler\\:\\:\\$sessionID \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Session/Handlers/DatabaseHandler.php + + - + message: "#^Property CodeIgniter\\\\Session\\\\Handlers\\\\BaseHandler\\:\\:\\$sessionID \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Session/Handlers/FileHandler.php + + - + message: "#^Property CodeIgniter\\\\Session\\\\Handlers\\\\BaseHandler\\:\\:\\$sessionID \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Session/Handlers/MemcachedHandler.php + + - + message: "#^Property CodeIgniter\\\\Session\\\\Handlers\\\\BaseHandler\\:\\:\\$sessionID \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Session/Handlers/RedisHandler.php + + - + message: "#^Strict comparison using \\=\\=\\= between string and true will always evaluate to false\\.$#" + count: 1 + path: system/Session/Handlers/RedisHandler.php + + - + message: "#^Property CodeIgniter\\\\Session\\\\Session\\:\\:\\$sessionExpiration \\(int\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$cookieDomain \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$cookiePath \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$cookieSameSite \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 2 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$cookieSecure \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$sessionCookieName \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$sessionExpiration \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$sessionMatchIP \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$sessionRegenerateDestroy \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\App\\:\\:\\$sessionTimeToUpdate \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\Cookie\\:\\:\\$domain \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\Cookie\\:\\:\\$path \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\Cookie\\:\\:\\$raw \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\Cookie\\:\\:\\$samesite \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Property Config\\\\Cookie\\:\\:\\$secure \\(bool\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Session/Session.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: system/Test/CIUnitTestCase.php + + - + message: "#^Access to an undefined property object\\:\\:\\$createdField\\.$#" + count: 1 + path: system/Test/Fabricator.php + + - + message: "#^Access to an undefined property object\\:\\:\\$deletedField\\.$#" + count: 1 + path: system/Test/Fabricator.php + + - + message: "#^Access to an undefined property object\\:\\:\\$updatedField\\.$#" + count: 1 + path: system/Test/Fabricator.php + + - + message: "#^Access to protected property CodeIgniter\\\\HTTP\\\\Request\\:\\:\\$uri\\.$#" + count: 1 + path: system/Test/FeatureTestCase.php + + - + message: "#^Property CodeIgniter\\\\Test\\\\CIUnitTestCase\\:\\:\\$bodyFormat \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Test/FeatureTestCase.php + + - + message: "#^Property CodeIgniter\\\\Test\\\\CIUnitTestCase\\:\\:\\$clean \\(bool\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Test/FeatureTestCase.php + + - + message: "#^Property CodeIgniter\\\\Test\\\\CIUnitTestCase\\:\\:\\$session \\(array\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Test/FeatureTestCase.php + + - + message: "#^Cannot access property \\$insert_id on bool\\|object\\|resource\\.$#" + count: 1 + path: system/Test/Mock/MockConnection.php + + - + message: "#^Property CodeIgniter\\\\Test\\\\Mock\\\\MockResourcePresenter\\:\\:\\$formatter \\(CodeIgniter\\\\Format\\\\FormatterInterface\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: system/Test/Mock/MockResourcePresenter.php + + - + message: "#^Property CodeIgniter\\\\Throttle\\\\Throttler\\:\\:\\$testTime \\(int\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Throttle/Throttler.php + + - + message: "#^Property CodeIgniter\\\\Validation\\\\Validation\\:\\:\\$errors \\(array\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/Validation/Validation.php + + - + message: "#^Variable \\$error on left side of \\?\\? always exists and is always null\\.$#" + count: 1 + path: system/Validation/Validation.php + + - + message: "#^Property CodeIgniter\\\\View\\\\Cell\\:\\:\\$cache \\(CodeIgniter\\\\Cache\\\\CacheInterface\\) in empty\\(\\) is not falsy\\.$#" + count: 2 + path: system/View/Cell.php + + - + message: "#^Property Config\\\\View\\:\\:\\$plugins \\(array\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: system/View/Parser.php + diff --git a/phpstan.neon.dist b/phpstan.neon.dist index bf23eb5303ed..741b147136b3 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,6 +8,9 @@ services: tags: - phpstan.rules.rule +includes: + - phpstan-baseline.neon.dist + parameters: tmpDir: build/phpstan level: 5 @@ -28,30 +31,6 @@ parameters: - system/Test/Filters/CITestStreamFilter.php - system/ThirdParty/* - system/Validation/Views/single.php - ignoreErrors: - - '#Access to an undefined property CodeIgniter\\Database\\BaseConnection::\$mysqli|\$schema#' - - '#Access to an undefined property CodeIgniter\\Database\\ConnectionInterface::(\$DBDriver|\$connID|\$likeEscapeStr|\$likeEscapeChar|\$escapeChar|\$protectIdentifiers|\$schema)#' - - '#Call to an undefined method CodeIgniter\\Database\\BaseConnection::_(disable|enable)ForeignKeyChecks\(\)#' - - '#Call to an undefined method CodeIgniter\\Router\\RouteCollectionInterface::(getDefaultNamespace|isFiltered|getFilterForRoute|getFiltersForRoute|getRoutesOptions)\(\)#' - - '#Cannot access property [\$a-z_]+ on ((bool\|)?object\|resource)#' - - '#Cannot call method [a-zA-Z_]+\(\) on ((bool\|)?object\|resource)#' - - '#Method CodeIgniter\\Router\\RouteCollectionInterface::getRoutes\(\) invoked with 1 parameter, 0 required#' - - '#Method CodeIgniter\\Validation\\ValidationInterface::run\(\) invoked with 3 parameters, 0-2 required#' - - '#Negated boolean expression is always (true|false)#' - - '#Return type \(bool\) of method CodeIgniter\\HTTP\\Files\\UploadedFile::move\(\) should be compatible with return type \(CodeIgniter\\Files\\File\) of method CodeIgniter\\Files\\File::move\(\)#' - - '#.*\son left side of \?\? is not nullable#' - - '#While loop condition is always true#' - - '#Right side of && is always true#' - - '#.*in isset\(\) is not nullable#' - - '#.*in empty\(\) is not falsy#' - - '#.*on left side of \?\? always exists and is not nullable#' - - '#Variable \$error on left side of \?\? always exists and is always null#' - - '#Variable \$config in empty\(\) always exists and is not falsy#' - - '#If condition is always true#' - - '#Dead catch - CodeIgniter\\Exceptions\\PageNotFoundException is never thrown in the try block#' - - '#.* in isset\(\) does not exist#' - - '#Variable \$mockService in empty\(\) always exists and is always falsy#' - - '#PHPDoc type string\|null of property CodeIgniter\\Images\\Handlers\\ImageMagickHandler::\$resource is not covariant with PHPDoc type resource\|null of overridden property CodeIgniter\\Images\\Handlers\\BaseHandler::\$resource#' parallel: processTimeout: 300.0 scanDirectories: diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 3472756ad4dd..492fb09930f0 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -114,10 +114,10 @@ public function initialize(Autoload $config, Modules $modules) public function register() { // Prepend the PSR4 autoloader for maximum performance. - spl_autoload_register([$this, 'loadClass'], true, true); // @phpstan-ignore-line + spl_autoload_register([$this, 'loadClass'], true, true); // Now prepend another loader for the files in our class map. - spl_autoload_register([$this, 'loadClassmap'], true, true); // @phpstan-ignore-line + spl_autoload_register([$this, 'loadClassmap'], true, true); // Load our non-class files foreach ($this->files as $file) { diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index a7df6971b4bc..2517c6a5df11 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -241,7 +241,6 @@ protected function getItem(string $filename) return false; } - // @phpstan-ignore-next-line if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl']) { // If the file is still there then try to remove it if (is_file($this->path . $filename)) { diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index 93c8cc59e0b5..f240a5d08de2 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -146,7 +146,7 @@ public function get(string $key) } } - return is_array($data) ? $data[0] : $data; // @phpstan-ignore-line + return is_array($data) ? $data[0] : $data; } /** @@ -172,7 +172,6 @@ public function save(string $key, $value, int $ttl = 60) return $this->memcached->set($key, $value, 0, $ttl); } - // @phpstan-ignore-next-line return false; } @@ -205,7 +204,6 @@ public function increment(string $key, int $offset = 1) $key = static::validateKey($key, $this->prefix); - // @phpstan-ignore-next-line return $this->memcached->increment($key, $offset, $offset, 60); } @@ -221,7 +219,7 @@ public function decrement(string $key, int $offset = 1) $key = static::validateKey($key, $this->prefix); // FIXME: third parameter isn't other handler actions. - // @phpstan-ignore-next-line + return $this->memcached->decrement($key, $offset, $offset, 60); } diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index a8ebeef1b5cf..41e775dbf58d 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -537,7 +537,6 @@ protected function getRequestObject() return; } - // @phpstan-ignore-next-line if (is_cli() && ENVIRONMENT !== 'testing') { // @codeCoverageIgnoreStart $this->request = Services::clirequest($this->config); @@ -721,7 +720,7 @@ protected function tryToRouteIt(?RouteCollectionInterface $routes = null) // If a {locale} segment was matched in the final route, // then we need to set the correct locale on our Request. if ($this->router->hasLocale()) { - $this->request->setLocale($this->router->getLocale()); // @phpstan-ignore-line + $this->request->setLocale($this->router->getLocale()); } $this->benchmark->stop('routing'); @@ -816,7 +815,7 @@ protected function createController() protected function runController($class) { // If this is a console request then use the input segments as parameters - $params = defined('SPARKED') ? $this->request->getSegments() : $this->router->params(); // @phpstan-ignore-line + $params = defined('SPARKED') ? $this->request->getSegments() : $this->router->params(); if (method_exists($class, '_remap')) { $output = $class->_remap($this->method, ...$params); @@ -969,7 +968,7 @@ public function spoofRequestMethod() return; } - $method = $this->request->getPost('_method'); // @phpstan-ignore-line + $method = $this->request->getPost('_method'); if (empty($method)) { return; diff --git a/system/Common.php b/system/Common.php index f531a82f7284..567135babe1f 100644 --- a/system/Common.php +++ b/system/Common.php @@ -1153,7 +1153,6 @@ function class_uses_recursive($class) $results = []; - // @phpstan-ignore-next-line foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) { $results += trait_uses_recursive($class); } diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index f2ceb5a0f907..5f678e5114d7 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -883,7 +883,6 @@ public function prepare(Closure $func, array $options = []) $this->pretend(false); if ($sql instanceof QueryInterface) { - // @phpstan-ignore-next-line $sql = $sql->getOriginalQuery(); } diff --git a/system/Database/BaseResult.php b/system/Database/BaseResult.php index 49a970f5bf11..5d223c7fc08b 100644 --- a/system/Database/BaseResult.php +++ b/system/Database/BaseResult.php @@ -154,7 +154,6 @@ public function getCustomResultObject(string $className) $this->customResultObject[$className][] = $row; } - // @phpstan-ignore-next-line return $this->customResultObject[$className]; } @@ -233,7 +232,6 @@ public function getResultObject(): array $this->resultObject[] = $row; } - // @phpstan-ignore-next-line return $this->resultObject; } diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index d39587821036..57b4c78fd749 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -117,7 +117,6 @@ public function getVersion(): string return $this->dataCache['version']; } - // @phpstan-ignore-next-line if (! $this->connID || ($pgVersion = pg_version($this->connID)) === false) { $this->initialize(); } diff --git a/system/Database/SQLite3/Result.php b/system/Database/SQLite3/Result.php index 6ad8e5dc939f..6afc04c51578 100644 --- a/system/Database/SQLite3/Result.php +++ b/system/Database/SQLite3/Result.php @@ -27,7 +27,7 @@ class Result extends BaseResult */ public function getFieldCount(): int { - return $this->resultID->numColumns(); // @phpstan-ignore-line + return $this->resultID->numColumns(); } /** @@ -38,7 +38,7 @@ public function getFieldNames(): array $fieldNames = []; for ($i = 0, $c = $this->getFieldCount(); $i < $c; $i++) { - $fieldNames[] = $this->resultID->columnName($i); // @phpstan-ignore-line + $fieldNames[] = $this->resultID->columnName($i); } return $fieldNames; @@ -58,18 +58,18 @@ public function getFieldData(): array ]; $retVal = []; - $this->resultID->fetchArray(SQLITE3_NUM); // @phpstan-ignore-line + $this->resultID->fetchArray(SQLITE3_NUM); for ($i = 0, $c = $this->getFieldCount(); $i < $c; $i++) { $retVal[$i] = new stdClass(); - $retVal[$i]->name = $this->resultID->columnName($i); // @phpstan-ignore-line - $type = $this->resultID->columnType($i); // @phpstan-ignore-line + $retVal[$i]->name = $this->resultID->columnName($i); + $type = $this->resultID->columnType($i); $retVal[$i]->type = $type; $retVal[$i]->type_name = $dataTypes[$type] ?? null; $retVal[$i]->max_length = null; $retVal[$i]->length = null; } - $this->resultID->reset(); // @phpstan-ignore-line + $this->resultID->reset(); return $retVal; } @@ -100,7 +100,7 @@ public function dataSeek(int $n = 0) throw new DatabaseException('SQLite3 doesn\'t support seeking to other offset.'); } - return $this->resultID->reset(); // @phpstan-ignore-line + return $this->resultID->reset(); } /** @@ -112,7 +112,7 @@ public function dataSeek(int $n = 0) */ protected function fetchAssoc() { - return $this->resultID->fetchArray(SQLITE3_ASSOC); // @phpstan-ignore-line + return $this->resultID->fetchArray(SQLITE3_ASSOC); } /** diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php index c594bc4eac9f..d319c2f9746e 100644 --- a/system/Debug/Exceptions.php +++ b/system/Debug/Exceptions.php @@ -394,7 +394,7 @@ public static function highlightFile(string $file, int $lineNumber, int $lines = $start = max($lineNumber - (int) round($lines / 2), 0); // Get just the lines we need to display, while keeping line numbers... - $source = array_splice($source, $start, $lines, true); // @phpstan-ignore-line + $source = array_splice($source, $start, $lines, true); // Used to format the line number in the source $format = '% ' . strlen((string) ($start + $lines)) . 'd'; diff --git a/system/Debug/Toolbar/Collectors/Events.php b/system/Debug/Toolbar/Collectors/Events.php index b8c59f4566bb..a8a7e7aa4c35 100644 --- a/system/Debug/Toolbar/Collectors/Events.php +++ b/system/Debug/Toolbar/Collectors/Events.php @@ -74,7 +74,7 @@ protected function formatTimelineData(): array { $data = []; - $rows = $this->viewer->getPerformanceData(); // @phpstan-ignore-line + $rows = $this->viewer->getPerformanceData(); foreach ($rows as $info) { $data[] = [ diff --git a/system/Debug/Toolbar/Collectors/Views.php b/system/Debug/Toolbar/Collectors/Views.php index 75fea1d6cc6d..fae3385fffbc 100644 --- a/system/Debug/Toolbar/Collectors/Views.php +++ b/system/Debug/Toolbar/Collectors/Views.php @@ -89,7 +89,7 @@ protected function formatTimelineData(): array { $data = []; - $rows = $this->viewer->getPerformanceData(); // @phpstan-ignore-line + $rows = $this->viewer->getPerformanceData(); foreach ($rows as $info) { $data[] = [ @@ -122,7 +122,7 @@ protected function formatTimelineData(): array public function getVarData(): array { return [ - // @phpstan-ignore-next-line + 'View Data' => $this->viewer->getData(), ]; } @@ -132,7 +132,7 @@ public function getVarData(): array */ public function getBadgeValue(): int { - return count($this->viewer->getPerformanceData()); // @phpstan-ignore-line + return count($this->viewer->getPerformanceData()); } /** diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 9a66e632783b..e00ac44f97e0 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -358,7 +358,7 @@ public function send(string $method, string $url) // Do we need to delay this request? if ($this->delay > 0) { - sleep($this->delay); // @phpstan-ignore-line + sleep($this->delay); } $output = $this->sendRequest($curlOptions); diff --git a/system/HTTP/RequestTrait.php b/system/HTTP/RequestTrait.php index c0bb005099ab..327cddcb0e7f 100644 --- a/system/HTTP/RequestTrait.php +++ b/system/HTTP/RequestTrait.php @@ -273,7 +273,6 @@ public function fetchGlobal(string $method, $index = null, ?int $filter = null, $value = $this->globals[$method][$index] ?? null; } - // @phpstan-ignore-next-line if (is_array($value) && ( $filter !== FILTER_DEFAULT diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index c7bdbb135354..f9e9d34c277d 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -625,7 +625,7 @@ public function setAuthority(string $str) if (empty($parts['host']) && $parts['path'] !== '') { $parts['host'] = $parts['path']; - unset($parts['path']); // @phpstan-ignore-line + unset($parts['path']); } $this->applyParts($parts); diff --git a/system/Helpers/number_helper.php b/system/Helpers/number_helper.php index 35e748978fbb..a9a2a938c36f 100644 --- a/system/Helpers/number_helper.php +++ b/system/Helpers/number_helper.php @@ -77,7 +77,7 @@ function number_to_amount($num, int $precision = 0, ?string $locale = null) { // Strip any formatting & ensure numeric input try { - $num = 0 + str_replace(',', '', $num); // @phpstan-ignore-line + $num = 0 + str_replace(',', '', $num); } catch (ErrorException $ee) { return false; } diff --git a/system/Helpers/text_helper.php b/system/Helpers/text_helper.php index 5f0738421908..4e7e5d855302 100755 --- a/system/Helpers/text_helper.php +++ b/system/Helpers/text_helper.php @@ -564,7 +564,6 @@ function random_string(string $type = 'alnum', int $len = 8): string break; } - // @phpstan-ignore-next-line return substr(str_shuffle(str_repeat($pool, ceil($len / strlen($pool)))), 0, $len); case 'md5': diff --git a/system/Helpers/url_helper.php b/system/Helpers/url_helper.php index 8d089083eddd..42bcdc473619 100644 --- a/system/Helpers/url_helper.php +++ b/system/Helpers/url_helper.php @@ -352,7 +352,7 @@ function safe_mailto(string $email, string $title = '', $attributes = ''): strin $temp[] = $ordinal; - if (count($temp) === $count) { // @phpstan-ignore-line + if (count($temp) === $count) { $number = ($count === 3) ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64) : (($temp[0] % 32) * 64) + ($temp[1] % 64); $x[] = '|' . $number; $count = 1; diff --git a/system/Images/Handlers/ImageMagickHandler.php b/system/Images/Handlers/ImageMagickHandler.php index 5ec6a23cc4f7..37bd168ead02 100644 --- a/system/Images/Handlers/ImageMagickHandler.php +++ b/system/Images/Handlers/ImageMagickHandler.php @@ -384,10 +384,10 @@ protected function _text(string $text, array $options = []) break; } - $xAxis = $xAxis >= 0 ? '+' . $xAxis : $xAxis; // @phpstan-ignore-line - $yAxis = $yAxis >= 0 ? '+' . $yAxis : $yAxis; // @phpstan-ignore-line + $xAxis = $xAxis >= 0 ? '+' . $xAxis : $xAxis; + $yAxis = $yAxis >= 0 ? '+' . $yAxis : $yAxis; - $cmd .= " -gravity {$gravity} -geometry {$xAxis}{$yAxis}"; // @phpstan-ignore-line + $cmd .= " -gravity {$gravity} -geometry {$xAxis}{$yAxis}"; } // Color diff --git a/system/Model.php b/system/Model.php index 418b3057eeb9..32fa82fcff64 100644 --- a/system/Model.php +++ b/system/Model.php @@ -158,7 +158,7 @@ protected function doFind(bool $singleton, $id = null) */ protected function doFindColumn(string $columnName) { - return $this->select($columnName)->asArray()->find(); // @phpstan-ignore-line + return $this->select($columnName)->asArray()->find(); } /** diff --git a/system/Router/Router.php b/system/Router/Router.php index 621c54a5e9dd..5c4b3f0255d7 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -124,7 +124,6 @@ public function __construct(RouteCollectionInterface $routes, ?Request $request $this->controller = $this->collection->getDefaultController(); $this->method = $this->collection->getDefaultMethod(); - // @phpstan-ignore-next-line $this->collection->setHTTPVerb($request->getMethod() ?? strtolower($_SERVER['REQUEST_METHOD'])); } diff --git a/system/Session/Handlers/DatabaseHandler.php b/system/Session/Handlers/DatabaseHandler.php index f0164d2dfc3c..dfaa472029fd 100644 --- a/system/Session/Handlers/DatabaseHandler.php +++ b/system/Session/Handlers/DatabaseHandler.php @@ -69,7 +69,6 @@ public function __construct(AppConfig $config, string $ipAddress) throw SessionException::forMissingDatabaseTable(); } - // @phpstan-ignore-next-line $this->DBGroup = $config->sessionDBGroup ?? config(Database::class)->defaultGroup; $this->db = Database::connect($this->DBGroup); diff --git a/system/Session/Handlers/RedisHandler.php b/system/Session/Handlers/RedisHandler.php index ce6e7bde5180..93a601eade70 100644 --- a/system/Session/Handlers/RedisHandler.php +++ b/system/Session/Handlers/RedisHandler.php @@ -206,7 +206,6 @@ public function close(): bool try { $pingReply = $this->redis->ping(); - // @phpstan-ignore-next-line if (($pingReply === true) || ($pingReply === '+PONG')) { if (isset($this->lockKey)) { $this->redis->del($this->lockKey); diff --git a/system/Test/CIUnitTestCase.php b/system/Test/CIUnitTestCase.php index 50a28e13d2da..e2c6eab609bb 100644 --- a/system/Test/CIUnitTestCase.php +++ b/system/Test/CIUnitTestCase.php @@ -231,7 +231,7 @@ protected function setUp(): void { parent::setUp(); - if (! $this->app) { // @phpstan-ignore-line + if (! $this->app) { $this->app = $this->createApplication(); } diff --git a/system/Test/Fabricator.php b/system/Test/Fabricator.php index 0fb013cb1820..d4369765f0ee 100644 --- a/system/Test/Fabricator.php +++ b/system/Test/Fabricator.php @@ -510,12 +510,12 @@ protected function createMock(?int $count = null) $fields = []; if (! empty($this->model->useTimestamps)) { - $fields[$this->model->createdField] = $datetime; // @phpstan-ignore-line - $fields[$this->model->updatedField] = $datetime; // @phpstan-ignore-line + $fields[$this->model->createdField] = $datetime; + $fields[$this->model->updatedField] = $datetime; } if (! empty($this->model->useSoftDeletes)) { - $fields[$this->model->deletedField] = null; // @phpstan-ignore-line + $fields[$this->model->deletedField] = null; } // Iterate over new entities and add the necessary fields diff --git a/system/Test/FeatureTestCase.php b/system/Test/FeatureTestCase.php index 87423271cd63..d1a75edb8f62 100644 --- a/system/Test/FeatureTestCase.php +++ b/system/Test/FeatureTestCase.php @@ -349,7 +349,7 @@ protected function populateGlobals(string $method, Request $request, ?array $par // otherwise set it from the URL. $get = ! empty($params) && $method === 'get' ? $params - : $this->getPrivateProperty($request->uri, 'query'); // @phpstan-ignore-line + : $this->getPrivateProperty($request->uri, 'query'); $request->setGlobal('get', $get); if ($method !== 'get') { diff --git a/system/Test/FeatureTestTrait.php b/system/Test/FeatureTestTrait.php index b44ff8c65491..afb93376b9a0 100644 --- a/system/Test/FeatureTestTrait.php +++ b/system/Test/FeatureTestTrait.php @@ -344,7 +344,7 @@ protected function populateGlobals(string $method, Request $request, ?array $par // otherwise set it from the URL. $get = ! empty($params) && $method === 'get' ? $params - : $this->getPrivateProperty($request->uri, 'query'); // @phpstan-ignore-line + : $this->getPrivateProperty($request->uri, 'query'); $request->setGlobal('get', $get); if ($method !== 'get') { diff --git a/system/Test/Mock/MockConnection.php b/system/Test/Mock/MockConnection.php index 78bd405babad..c9d03e7638d6 100644 --- a/system/Test/Mock/MockConnection.php +++ b/system/Test/Mock/MockConnection.php @@ -166,7 +166,7 @@ public function error(): array */ public function insertID(): int { - return $this->connID->insert_id; // @phpstan-ignore-line + return $this->connID->insert_id; } /** From a0b8140b4f5b5ebe1cb7cb1b7d4b751e97fb174e Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Mon, 13 Dec 2021 20:23:40 +0800 Subject: [PATCH 339/407] Test phpstan on PHP 8.0+ --- .github/workflows/test-phpstan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-phpstan.yml b/.github/workflows/test-phpstan.yml index 0e59e3bf4e3a..eceb97524605 100644 --- a/.github/workflows/test-phpstan.yml +++ b/.github/workflows/test-phpstan.yml @@ -29,7 +29,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['7.4', '8.0'] + php-versions: ['8.0', '8.1'] steps: - name: Checkout uses: actions/checkout@v2 From 01ca5857fb3b64982670b1f808dad6129476cf0c Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 14 Dec 2021 10:29:38 +0900 Subject: [PATCH 340/407] docs: use BaseController instead of Controller --- user_guide_src/source/tutorial/news_section.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/user_guide_src/source/tutorial/news_section.rst b/user_guide_src/source/tutorial/news_section.rst index 42bda88c5d06..396c74255962 100644 --- a/user_guide_src/source/tutorial/news_section.rst +++ b/user_guide_src/source/tutorial/news_section.rst @@ -142,9 +142,8 @@ a new ``News`` controller is defined. Create the new controller at namespace App\Controllers; use App\Models\NewsModel; - use CodeIgniter\Controller; - class News extends Controller + class News extends BaseController { public function index() { From 2f8d694d77717e5166a100b6cbda8a47660bb779 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 14 Dec 2021 13:13:41 +0900 Subject: [PATCH 341/407] docs: improve text decoration --- user_guide_src/source/incoming/content_negotiation.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/incoming/content_negotiation.rst b/user_guide_src/source/incoming/content_negotiation.rst index 11940b82092a..8122a4a910b5 100644 --- a/user_guide_src/source/incoming/content_negotiation.rst +++ b/user_guide_src/source/incoming/content_negotiation.rst @@ -60,7 +60,7 @@ be able to return data as raw HTML, JSON, or XML. This list should be provided i $format = $negotiate->media($supported); In this case, both the client and the server can agree on formatting the data as JSON so 'json' is returned from -the negotiate method. By default, if no match is found, the first element in the $supported array would be returned. +the negotiate method. By default, if no match is found, the first element in the ``$supported`` array would be returned. In some cases, though, you might need to enforce the format to be a strict match. If you pass ``true`` as the final value, it will return an empty string if no match is found:: @@ -92,7 +92,7 @@ and German you would do something like:: $lang = $negotiate->language($supported); In this example, 'en' would be returned as the current language. If no match is found, it will return the first element -in the $supported array, so that should always be the preferred language. +in the ``$supported`` array, so that should always be the preferred language. Encoding ======== From 5956d9821fd44b4c5ee882141b1399e273f8c710 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Dec 2021 15:02:53 +0000 Subject: [PATCH 342/407] chore(deps-dev): update rector/rector requirement from 0.12.7 to 0.12.8 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/0.12.7...0.12.8) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ab1c999190bf..38ddfd6ef3c7 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.12.7" + "rector/rector": "0.12.8" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" From eaab880886eff83b87734087b258754fe3d73ce5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 15 Dec 2021 10:50:31 +0900 Subject: [PATCH 343/407] docs: fix view() $options explanation --- user_guide_src/source/general/common_functions.rst | 9 +++++---- user_guide_src/source/testing/debugging.rst | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index c1cdb038984a..f4b61548f4da 100755 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -179,11 +179,12 @@ Service Accessors a convenience method that can be used in Controllers, libraries, and routed closures. - Currently, only one option is available for use within the `$options` array, `saveData` which specifies - that data will persistent between multiple calls to `view()` within the same request. By default, the - data for that view is forgotten after displaying that single view file. + Currently, only two options are available for use within the ``$options`` array: - The $option array is provided primarily to facilitate third-party integrations with + - ``saveData`` specifies that data will persistent between multiple calls to ``view()`` within the same request. If you do not want the data to be persisted, specify false. + - ``debug`` can be set to false to disable the addition of debug code for :ref:`Debug Toolbar `. + + The ``$option`` array is provided primarily to facilitate third-party integrations with libraries like Twig. Example:: diff --git a/user_guide_src/source/testing/debugging.rst b/user_guide_src/source/testing/debugging.rst index 3e456d118793..22c77141e116 100644 --- a/user_guide_src/source/testing/debugging.rst +++ b/user_guide_src/source/testing/debugging.rst @@ -45,6 +45,8 @@ This provides a backtrace to the current execution point, with Kint's own unique For more information, see `Kint's page `_. +.. _the-debug-toolbar: + ================= The Debug Toolbar ================= From 36d9c137e95300636da4232012746d40d1a06f05 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 15 Dec 2021 11:03:56 +0900 Subject: [PATCH 344/407] docs: add sample code --- user_guide_src/source/incoming/routing.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 97c2b1aa1fdd..954fc8ca24b1 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -259,7 +259,13 @@ This would handle the URL at ``admin/users/list``. Note that options passed to t At some point, you may want to group routes for the purpose of applying filters or other route config options like namespace, subdomain, etc. Without necessarily needing to add a prefix to the group, you can pass an empty string in place of the prefix and the routes in the group will be routed as though the group never existed but with the -given route config options. +given route config options:: + + $routes->group('', ['namespace' => 'Myth\Auth\Controllers'], function ($routes) { + $routes->get('login', 'AuthController::login', ['as' => 'login']); + $routes->post('login', 'AuthController::attemptLogin'); + $routes->get('logout', 'AuthController::logout'); + }); Environment Restrictions ======================== From c890ef7bc56b79e416a52b52a7d44455c44d2257 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 15 Dec 2021 11:23:52 +0900 Subject: [PATCH 345/407] docs: fix sample code Co-authored-by: John Paul E. Balandan, CPA <51850998+paulbalandan@users.noreply.github.com> --- user_guide_src/source/incoming/routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 954fc8ca24b1..9d4ab0d88998 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -261,7 +261,7 @@ config options like namespace, subdomain, etc. Without necessarily needing to ad an empty string in place of the prefix and the routes in the group will be routed as though the group never existed but with the given route config options:: - $routes->group('', ['namespace' => 'Myth\Auth\Controllers'], function ($routes) { + $routes->group('', ['namespace' => 'Myth\Auth\Controllers'], static function ($routes) { $routes->get('login', 'AuthController::login', ['as' => 'login']); $routes->post('login', 'AuthController::attemptLogin'); $routes->get('logout', 'AuthController::logout'); From f7c42268f6a99ab4cb3c503b2b30389ed371fe4a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 14 Dec 2021 09:29:43 +0900 Subject: [PATCH 346/407] fix: use $this->time() instead of time() For testing, we need to use testTime in all places. --- system/Throttle/Throttler.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system/Throttle/Throttler.php b/system/Throttle/Throttler.php index 0bdf8a95522d..5154f386439b 100644 --- a/system/Throttle/Throttler.php +++ b/system/Throttle/Throttler.php @@ -100,7 +100,7 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): // If it hasn't been created, then we'll set it to the maximum // capacity - 1, and save it to the cache. $this->cache->save($tokenName, $capacity - $cost, $seconds); - $this->cache->save($tokenName . 'Time', time(), $seconds); + $this->cache->save($tokenName . 'Time', $this->time(), $seconds); return true; } @@ -129,7 +129,7 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): // we need to decrement the number of available tokens. if ($tokens >= 1) { $this->cache->save($tokenName, $tokens - $cost, $seconds); - $this->cache->save($tokenName . 'Time', time(), $seconds); + $this->cache->save($tokenName . 'Time', $this->time(), $seconds); return true; } @@ -164,6 +164,8 @@ public function setTestTime(int $time) /** * Return the test time, defaulting to current. + * + * @TODO should be private */ public function time(): int { From f8c22452d3ebce55460d0add9b82481b827671c3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 14 Dec 2021 09:31:40 +0900 Subject: [PATCH 347/407] test: fix time dependent test Fixes #5444 --- tests/system/Throttle/ThrottleTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/system/Throttle/ThrottleTest.php b/tests/system/Throttle/ThrottleTest.php index a7905a2f59bf..498cbf0673d5 100644 --- a/tests/system/Throttle/ThrottleTest.php +++ b/tests/system/Throttle/ThrottleTest.php @@ -127,7 +127,10 @@ public function testOverload() public function testFlooding() { + $time = 1639441295; + $throttler = new Throttler($this->cache); + $throttler->setTestTime($time); $rate = 60; // allow 1 per second after the bucket is emptied $cost = 1; @@ -141,7 +144,7 @@ public function testFlooding() $this->assertFalse($throttler->check('127.0.0.1', $rate, MINUTE, $cost)); $this->assertSame(0, $this->cache->get('throttler_127.0.0.1')); - $throttler = $throttler->setTestTime(strtotime('+10 seconds')); + $throttler = $throttler->setTestTime($time + 10); $this->assertTrue($throttler->check('127.0.0.1', $rate, MINUTE, 0)); $this->assertSame(10.0, round($this->cache->get('throttler_127.0.0.1'))); From 0ca3ef9aa722799b8120abf3edc2b2b5ddc8bdc0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 16 Dec 2021 10:39:11 +0900 Subject: [PATCH 348/407] docs: add InvalidChars filter explanation --- user_guide_src/source/incoming/filters.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 096d1020f77f..cb62defe02a3 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -204,6 +204,14 @@ The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``InvalidChar .. note:: The filters are executed in the order defined in the config file. However, if enabled, ``DebugToolbar`` is always executed last because it should be able to capture everything that happens in the other filters. +InvalidChars +============= + +This filter checks if user input data (``$_GET``, ``$_POST``, ``$_COOKIE``, ``php://input``) do not contain the following characters: + +- invalid UTF-8 characters +- control characters except line break and tab code + SecureHeaders ============= From 1ebc173f9519875518ac47b750e8f33ca6337c0d Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 16 Dec 2021 10:39:45 +0900 Subject: [PATCH 349/407] docs: add links to other pages --- user_guide_src/source/incoming/filters.rst | 2 +- user_guide_src/source/libraries/security.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index cb62defe02a3..b8b16bb1c9ce 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -200,7 +200,7 @@ In this example, the array ``['dual', 'noreturn']`` will be passed in ``$argumen Provided Filters **************** -The filters bundled with CodeIgniter4 are: ``Honeypot``, ``CSRF``, ``InvalidChars``, ``SecureHeaders``, and ``DebugToolbar``. +The filters bundled with CodeIgniter4 are: :doc:`Honeypot <../libraries/honeypot>`, :ref:`CSRF `, ``InvalidChars``, ``SecureHeaders``, and :ref:`DebugToolbar `. .. note:: The filters are executed in the order defined in the config file. However, if enabled, ``DebugToolbar`` is always executed last because it should be able to capture everything that happens in the other filters. diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index b0a11af06b6d..00c6173ee4f3 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -19,6 +19,8 @@ If you find a case where you do need direct access though, you may load it throu $security = \Config\Services::security(); +.. _cross-site-request-forgery: + ********************************* Cross-site request forgery (CSRF) ********************************* From 0924a0c965dc760c89cc367ad7da0a9d1498bc1f Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 16 Dec 2021 11:26:09 +0900 Subject: [PATCH 350/407] docs: change TOC depth 2 or more --- user_guide_src/source/changelogs/v4.1.5.rst | 2 +- user_guide_src/source/dbmgmt/migration.rst | 3 ++- user_guide_src/source/helpers/array_helper.rst | 1 + user_guide_src/source/helpers/cookie_helper.rst | 3 ++- user_guide_src/source/helpers/date_helper.rst | 3 ++- user_guide_src/source/helpers/filesystem_helper.rst | 3 ++- user_guide_src/source/helpers/form_helper.rst | 3 ++- user_guide_src/source/helpers/html_helper.rst | 1 + user_guide_src/source/helpers/inflector_helper.rst | 3 ++- user_guide_src/source/helpers/number_helper.rst | 3 ++- user_guide_src/source/helpers/security_helper.rst | 3 ++- user_guide_src/source/helpers/test_helper.rst | 3 ++- user_guide_src/source/helpers/text_helper.rst | 3 ++- user_guide_src/source/helpers/url_helper.rst | 3 ++- user_guide_src/source/helpers/xml_helper.rst | 3 ++- user_guide_src/source/installation/installing_composer.rst | 2 +- user_guide_src/source/installation/installing_manual.rst | 4 ++++ user_guide_src/source/installation/running.rst | 2 +- user_guide_src/source/installation/upgrade_415.rst | 2 +- user_guide_src/source/installation/upgrade_configuration.rst | 2 +- user_guide_src/source/installation/upgrade_controllers.rst | 2 +- user_guide_src/source/installation/upgrade_database.rst | 2 +- user_guide_src/source/installation/upgrade_emails.rst | 2 +- user_guide_src/source/installation/upgrade_encryption.rst | 2 +- user_guide_src/source/installation/upgrade_file_upload.rst | 2 +- user_guide_src/source/installation/upgrade_html_tables.rst | 2 +- user_guide_src/source/installation/upgrade_localization.rst | 2 +- user_guide_src/source/installation/upgrade_migrations.rst | 2 +- user_guide_src/source/installation/upgrade_models.rst | 2 +- user_guide_src/source/installation/upgrade_pagination.rst | 2 +- user_guide_src/source/installation/upgrade_responses.rst | 2 +- user_guide_src/source/installation/upgrade_routing.rst | 2 +- user_guide_src/source/installation/upgrade_security.rst | 2 +- user_guide_src/source/installation/upgrade_sessions.rst | 2 +- user_guide_src/source/installation/upgrade_validations.rst | 2 +- user_guide_src/source/installation/upgrade_view_parser.rst | 2 +- user_guide_src/source/installation/upgrade_views.rst | 2 +- user_guide_src/source/libraries/encryption.rst | 3 ++- user_guide_src/source/libraries/time.rst | 2 +- user_guide_src/source/outgoing/table.rst | 3 ++- user_guide_src/source/testing/mocking.rst | 2 +- 41 files changed, 58 insertions(+), 38 deletions(-) diff --git a/user_guide_src/source/changelogs/v4.1.5.rst b/user_guide_src/source/changelogs/v4.1.5.rst index 67589933074f..1ef2ec8775a0 100644 --- a/user_guide_src/source/changelogs/v4.1.5.rst +++ b/user_guide_src/source/changelogs/v4.1.5.rst @@ -7,7 +7,7 @@ Release Date: November 8, 2021 .. contents:: :local: - :depth: 1 + :depth: 2 BREAKING ======== diff --git a/user_guide_src/source/dbmgmt/migration.rst b/user_guide_src/source/dbmgmt/migration.rst index e7bd41f34bc0..d88d3e226118 100644 --- a/user_guide_src/source/dbmgmt/migration.rst +++ b/user_guide_src/source/dbmgmt/migration.rst @@ -15,7 +15,8 @@ state. You can also use ``$migration->setNamespace(null)->latest()`` to include migrations from all namespaces. .. contents:: - :local: + :local: + :depth: 2 ******************** Migration file names diff --git a/user_guide_src/source/helpers/array_helper.rst b/user_guide_src/source/helpers/array_helper.rst index 2457790e4ad6..21e798a1ee2e 100644 --- a/user_guide_src/source/helpers/array_helper.rst +++ b/user_guide_src/source/helpers/array_helper.rst @@ -7,6 +7,7 @@ any of the existing functionality that PHP provides - unless it is to vastly sim .. contents:: :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/cookie_helper.rst b/user_guide_src/source/helpers/cookie_helper.rst index c7df02f6461f..597adaa66c9a 100755 --- a/user_guide_src/source/helpers/cookie_helper.rst +++ b/user_guide_src/source/helpers/cookie_helper.rst @@ -6,7 +6,8 @@ The Cookie Helper file contains functions that assist in working with cookies. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst index 876a09bfbae6..cc97b46a9dbf 100644 --- a/user_guide_src/source/helpers/date_helper.rst +++ b/user_guide_src/source/helpers/date_helper.rst @@ -6,7 +6,8 @@ The Date Helper file contains functions that assist in working with dates. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/filesystem_helper.rst b/user_guide_src/source/helpers/filesystem_helper.rst index 2d884aeee08d..c7a7e8ad22a2 100644 --- a/user_guide_src/source/helpers/filesystem_helper.rst +++ b/user_guide_src/source/helpers/filesystem_helper.rst @@ -6,7 +6,8 @@ The Directory Helper file contains functions that assist in working with directories. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/form_helper.rst b/user_guide_src/source/helpers/form_helper.rst index e8788de0a499..490a4cd3ccc1 100644 --- a/user_guide_src/source/helpers/form_helper.rst +++ b/user_guide_src/source/helpers/form_helper.rst @@ -6,7 +6,8 @@ The Form Helper file contains functions that assist in working with forms. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/html_helper.rst b/user_guide_src/source/helpers/html_helper.rst index 978f0ea67f04..b73b3222f711 100755 --- a/user_guide_src/source/helpers/html_helper.rst +++ b/user_guide_src/source/helpers/html_helper.rst @@ -7,6 +7,7 @@ HTML. .. contents:: :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/inflector_helper.rst b/user_guide_src/source/helpers/inflector_helper.rst index 31e603b2941d..924ee5b75559 100755 --- a/user_guide_src/source/helpers/inflector_helper.rst +++ b/user_guide_src/source/helpers/inflector_helper.rst @@ -6,7 +6,8 @@ The Inflector Helper file contains functions that permit you to change **English** words to plural, singular, camel case, etc. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/number_helper.rst b/user_guide_src/source/helpers/number_helper.rst index be5be2a8018c..c085a59f8d12 100644 --- a/user_guide_src/source/helpers/number_helper.rst +++ b/user_guide_src/source/helpers/number_helper.rst @@ -6,7 +6,8 @@ The Number Helper file contains functions that help you work with numeric data in a locale-aware manner. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/security_helper.rst b/user_guide_src/source/helpers/security_helper.rst index 2c3812a49def..b5ada61fe254 100644 --- a/user_guide_src/source/helpers/security_helper.rst +++ b/user_guide_src/source/helpers/security_helper.rst @@ -5,7 +5,8 @@ Security Helper The Security Helper file contains security related functions. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/test_helper.rst b/user_guide_src/source/helpers/test_helper.rst index 4d98f005fb0a..f6a59d6e6c11 100644 --- a/user_guide_src/source/helpers/test_helper.rst +++ b/user_guide_src/source/helpers/test_helper.rst @@ -5,7 +5,8 @@ Test Helper The Test Helper file contains functions that assist in testing your project. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/text_helper.rst b/user_guide_src/source/helpers/text_helper.rst index d83fb54835ae..0c842677a001 100755 --- a/user_guide_src/source/helpers/text_helper.rst +++ b/user_guide_src/source/helpers/text_helper.rst @@ -5,7 +5,8 @@ Text Helper The Text Helper file contains functions that assist in working with Text. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/url_helper.rst b/user_guide_src/source/helpers/url_helper.rst index 780becac13d8..b3f5daf5e439 100644 --- a/user_guide_src/source/helpers/url_helper.rst +++ b/user_guide_src/source/helpers/url_helper.rst @@ -5,7 +5,8 @@ URL Helper The URL Helper file contains functions that assist in working with URLs. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/helpers/xml_helper.rst b/user_guide_src/source/helpers/xml_helper.rst index ebccaca79f91..ac72f26891f9 100644 --- a/user_guide_src/source/helpers/xml_helper.rst +++ b/user_guide_src/source/helpers/xml_helper.rst @@ -6,7 +6,8 @@ The XML Helper file contains functions that assist in working with XML data. .. contents:: - :local: + :local: + :depth: 2 Loading this Helper =================== diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index 41b288c02037..ac1be8c5e12c 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -3,7 +3,7 @@ Composer Installation .. contents:: :local: - :depth: 1 + :depth: 2 Composer can be used in several ways to install CodeIgniter4 on your system. diff --git a/user_guide_src/source/installation/installing_manual.rst b/user_guide_src/source/installation/installing_manual.rst index c64f7dc5b212..daf7ea26c55f 100644 --- a/user_guide_src/source/installation/installing_manual.rst +++ b/user_guide_src/source/installation/installing_manual.rst @@ -1,6 +1,10 @@ Manual Installation ################### +.. contents:: + :local: + :depth: 2 + The `CodeIgniter 4 framework `_ repository holds the released versions of the framework. It is intended for developers who do not wish to use Composer. diff --git a/user_guide_src/source/installation/running.rst b/user_guide_src/source/installation/running.rst index f16bb7636672..8b2d0668a867 100644 --- a/user_guide_src/source/installation/running.rst +++ b/user_guide_src/source/installation/running.rst @@ -3,7 +3,7 @@ Running Your App .. contents:: :local: - :depth: 1 + :depth: 2 A CodeIgniter 4 app can be run in a number of different ways: hosted on a web server, using virtualization, or using CodeIgniter’s command line tool for testing. diff --git a/user_guide_src/source/installation/upgrade_415.rst b/user_guide_src/source/installation/upgrade_415.rst index a029724b3bfb..d995a58d8ffd 100644 --- a/user_guide_src/source/installation/upgrade_415.rst +++ b/user_guide_src/source/installation/upgrade_415.rst @@ -4,7 +4,7 @@ Upgrading from 4.1.4 to 4.1.5 .. contents:: :local: - :depth: 1 + :depth: 2 Breaking Changes ================ diff --git a/user_guide_src/source/installation/upgrade_configuration.rst b/user_guide_src/source/installation/upgrade_configuration.rst index cad74dc1e713..4592f2d1e001 100644 --- a/user_guide_src/source/installation/upgrade_configuration.rst +++ b/user_guide_src/source/installation/upgrade_configuration.rst @@ -3,7 +3,7 @@ Upgrade Configuration .. contents:: :local: - :depth: 1 + :depth: 2 Documentations ============== diff --git a/user_guide_src/source/installation/upgrade_controllers.rst b/user_guide_src/source/installation/upgrade_controllers.rst index 003cad92a295..44999b0dc6ec 100644 --- a/user_guide_src/source/installation/upgrade_controllers.rst +++ b/user_guide_src/source/installation/upgrade_controllers.rst @@ -3,7 +3,7 @@ Upgrade Controllers .. contents:: :local: - :depth: 1 + :depth: 2 Documentations ============== diff --git a/user_guide_src/source/installation/upgrade_database.rst b/user_guide_src/source/installation/upgrade_database.rst index f2f4ee65440f..666a51e97716 100644 --- a/user_guide_src/source/installation/upgrade_database.rst +++ b/user_guide_src/source/installation/upgrade_database.rst @@ -3,7 +3,7 @@ Upgrade Database .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_emails.rst b/user_guide_src/source/installation/upgrade_emails.rst index d64a6bb2afea..0ce8b0792bc1 100644 --- a/user_guide_src/source/installation/upgrade_emails.rst +++ b/user_guide_src/source/installation/upgrade_emails.rst @@ -3,7 +3,7 @@ Upgrade Emails .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_encryption.rst b/user_guide_src/source/installation/upgrade_encryption.rst index 003abc7ae218..04c857ba8f4e 100644 --- a/user_guide_src/source/installation/upgrade_encryption.rst +++ b/user_guide_src/source/installation/upgrade_encryption.rst @@ -3,7 +3,7 @@ Upgrade Encryption .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_file_upload.rst b/user_guide_src/source/installation/upgrade_file_upload.rst index 6161e999f45e..6ad3c533a03a 100644 --- a/user_guide_src/source/installation/upgrade_file_upload.rst +++ b/user_guide_src/source/installation/upgrade_file_upload.rst @@ -3,7 +3,7 @@ Upgrade Working with Uploaded Files .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_html_tables.rst b/user_guide_src/source/installation/upgrade_html_tables.rst index 9fc98e1fd838..715d80660876 100644 --- a/user_guide_src/source/installation/upgrade_html_tables.rst +++ b/user_guide_src/source/installation/upgrade_html_tables.rst @@ -3,7 +3,7 @@ Upgrade HTML Tables .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_localization.rst b/user_guide_src/source/installation/upgrade_localization.rst index ca919c7cdb1b..cde7f81c0e31 100644 --- a/user_guide_src/source/installation/upgrade_localization.rst +++ b/user_guide_src/source/installation/upgrade_localization.rst @@ -3,7 +3,7 @@ Upgrade Localization .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_migrations.rst b/user_guide_src/source/installation/upgrade_migrations.rst index ce1e92664d6d..90e1999e29f6 100644 --- a/user_guide_src/source/installation/upgrade_migrations.rst +++ b/user_guide_src/source/installation/upgrade_migrations.rst @@ -3,7 +3,7 @@ Upgrade Migrations .. contents:: :local: - :depth: 1 + :depth: 2 Documentations ============== diff --git a/user_guide_src/source/installation/upgrade_models.rst b/user_guide_src/source/installation/upgrade_models.rst index 12e0680e7320..b76bc10d67d5 100644 --- a/user_guide_src/source/installation/upgrade_models.rst +++ b/user_guide_src/source/installation/upgrade_models.rst @@ -3,7 +3,7 @@ Upgrade Models .. contents:: :local: - :depth: 1 + :depth: 2 Documentations ============== diff --git a/user_guide_src/source/installation/upgrade_pagination.rst b/user_guide_src/source/installation/upgrade_pagination.rst index 23c8564d1390..f952da0c5074 100644 --- a/user_guide_src/source/installation/upgrade_pagination.rst +++ b/user_guide_src/source/installation/upgrade_pagination.rst @@ -3,7 +3,7 @@ Upgrade Pagination .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_responses.rst b/user_guide_src/source/installation/upgrade_responses.rst index aafcf9731faa..2f87f9ec50ef 100644 --- a/user_guide_src/source/installation/upgrade_responses.rst +++ b/user_guide_src/source/installation/upgrade_responses.rst @@ -3,7 +3,7 @@ Upgrade HTTP Responses .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_routing.rst b/user_guide_src/source/installation/upgrade_routing.rst index 5ea14f16e74d..1d2540b2ded1 100644 --- a/user_guide_src/source/installation/upgrade_routing.rst +++ b/user_guide_src/source/installation/upgrade_routing.rst @@ -3,7 +3,7 @@ Upgrade Routing .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_security.rst b/user_guide_src/source/installation/upgrade_security.rst index 12990ba63347..18b61209ec1b 100644 --- a/user_guide_src/source/installation/upgrade_security.rst +++ b/user_guide_src/source/installation/upgrade_security.rst @@ -3,7 +3,7 @@ Upgrade Security .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_sessions.rst b/user_guide_src/source/installation/upgrade_sessions.rst index 23688000ff96..e935b08cfd16 100644 --- a/user_guide_src/source/installation/upgrade_sessions.rst +++ b/user_guide_src/source/installation/upgrade_sessions.rst @@ -3,7 +3,7 @@ Upgrade Sessions .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_validations.rst b/user_guide_src/source/installation/upgrade_validations.rst index 083479d210db..825b8be9ccdf 100644 --- a/user_guide_src/source/installation/upgrade_validations.rst +++ b/user_guide_src/source/installation/upgrade_validations.rst @@ -3,7 +3,7 @@ Upgrade Validations .. contents:: :local: - :depth: 1 + :depth: 2 Documentations of Library diff --git a/user_guide_src/source/installation/upgrade_view_parser.rst b/user_guide_src/source/installation/upgrade_view_parser.rst index 96f821b81922..a970a5ab5e88 100644 --- a/user_guide_src/source/installation/upgrade_view_parser.rst +++ b/user_guide_src/source/installation/upgrade_view_parser.rst @@ -3,7 +3,7 @@ Upgrade View Parser .. contents:: :local: - :depth: 1 + :depth: 2 Documentations diff --git a/user_guide_src/source/installation/upgrade_views.rst b/user_guide_src/source/installation/upgrade_views.rst index 38da7443ea53..903ac6838be1 100644 --- a/user_guide_src/source/installation/upgrade_views.rst +++ b/user_guide_src/source/installation/upgrade_views.rst @@ -3,7 +3,7 @@ Upgrade Views .. contents:: :local: - :depth: 1 + :depth: 2 Documentations ============== diff --git a/user_guide_src/source/libraries/encryption.rst b/user_guide_src/source/libraries/encryption.rst index 2c45e7ad79d9..1a8bf834d94c 100644 --- a/user_guide_src/source/libraries/encryption.rst +++ b/user_guide_src/source/libraries/encryption.rst @@ -31,7 +31,8 @@ A more comprehensive package like `Halite ` been deprecated as of PHP 7.2. .. contents:: - :local: + :local: + :depth: 2 .. _usage: diff --git a/user_guide_src/source/libraries/time.rst b/user_guide_src/source/libraries/time.rst index 57ee4d4572d6..6e55cf87aed3 100644 --- a/user_guide_src/source/libraries/time.rst +++ b/user_guide_src/source/libraries/time.rst @@ -11,7 +11,7 @@ is the ``Time`` class and lives in the ``CodeIgniter\I18n`` namespace. .. contents:: :local: - :depth: 1 + :depth: 2 ============= Instantiating diff --git a/user_guide_src/source/outgoing/table.rst b/user_guide_src/source/outgoing/table.rst index 0c8810fdb277..01b7dabe5cef 100644 --- a/user_guide_src/source/outgoing/table.rst +++ b/user_guide_src/source/outgoing/table.rst @@ -6,7 +6,8 @@ The Table Class provides methods that enable you to auto-generate HTML tables from arrays or database result sets. .. contents:: - :local: + :local: + :depth: 2 ********************* Using the Table Class diff --git a/user_guide_src/source/testing/mocking.rst b/user_guide_src/source/testing/mocking.rst index 03b464cf6570..758f6c2f3a50 100644 --- a/user_guide_src/source/testing/mocking.rst +++ b/user_guide_src/source/testing/mocking.rst @@ -9,7 +9,7 @@ emails were sent correctly, etc. .. contents:: :local: - :depth: 1 + :depth: 2 Cache ===== From e1085c81c44ce5c094d3d279b6472d6a49088070 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 16 Dec 2021 13:34:53 +0900 Subject: [PATCH 351/407] docs: fix $request->getMethod() return values Now the method name is lower case by default. --- user_guide_src/source/concepts/http.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/concepts/http.rst b/user_guide_src/source/concepts/http.rst index 8ae030fc1811..bc9bb25fe2b9 100644 --- a/user_guide_src/source/concepts/http.rst +++ b/user_guide_src/source/concepts/http.rst @@ -95,7 +95,7 @@ is an object-oriented representation of the HTTP request. It provides everything $request->getHeader('host'); $request->getHeader('Content-Type'); - $request->getMethod(); // GET, POST, PUT, etc + $request->getMethod(); // get, post, put, etc The request class does a lot of work in the background for you, that you never need to worry about. The `isAJAX()` and `isSecure()` methods check several different methods to determine the correct answer. From 9a9ebccfe141e7cc289738d0bbe3932bbbdd1cfa Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 16 Dec 2021 13:38:32 +0900 Subject: [PATCH 352/407] docs: decorate method names with '``' --- user_guide_src/source/concepts/http.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/concepts/http.rst b/user_guide_src/source/concepts/http.rst index bc9bb25fe2b9..d5c82f2a1492 100644 --- a/user_guide_src/source/concepts/http.rst +++ b/user_guide_src/source/concepts/http.rst @@ -98,7 +98,7 @@ is an object-oriented representation of the HTTP request. It provides everything $request->getMethod(); // get, post, put, etc The request class does a lot of work in the background for you, that you never need to worry about. -The `isAJAX()` and `isSecure()` methods check several different methods to determine the correct answer. +The ``isAJAX()`` and ``isSecure()`` methods check several different methods to determine the correct answer. .. note:: The ``isAJAX()`` method depends on the ``X-Requested-With`` header, which in some cases is not sent by default in XHR requests via JavaScript (i.e., fetch). See the :doc:`AJAX Requests ` section on how to avoid this problem. From 757a9d630ef7da7fc55d23454f762fe2bc4f1601 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 16 Dec 2021 16:33:54 +0900 Subject: [PATCH 353/407] refactor: update deprecated method --- system/Entity/Cast/DatetimeCast.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Entity/Cast/DatetimeCast.php b/system/Entity/Cast/DatetimeCast.php index 4655b4e374e3..99f425a410be 100644 --- a/system/Entity/Cast/DatetimeCast.php +++ b/system/Entity/Cast/DatetimeCast.php @@ -32,7 +32,7 @@ public static function get($value, array $params = []) } if ($value instanceof DateTime) { - return Time::instance($value); + return Time::createFromInstance($value); } if (is_numeric($value)) { From 091b324102bc28b179514a7795128ad122f968a3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 17 Dec 2021 15:13:28 +0900 Subject: [PATCH 354/407] docs: remove environment-specific configuration files There is no such a thing. --- user_guide_src/source/general/environments.rst | 8 -------- 1 file changed, 8 deletions(-) diff --git a/user_guide_src/source/general/environments.rst b/user_guide_src/source/general/environments.rst index 057dd8e57dea..ca9c6efc1042 100644 --- a/user_guide_src/source/general/environments.rst +++ b/user_guide_src/source/general/environments.rst @@ -103,11 +103,3 @@ Conversely, setting the constant to 'production' will disable all error output. Disabling error reporting in production is a :doc:`good security practice `. -Configuration Files -------------------- - -Optionally, you can have CodeIgniter load environment-specific -configuration files. This may be useful for managing things like -differing API keys across multiple environments. This is described in -more detail in the Handling Different Environments section of the -:doc:`Working with Configuration Files ` documentation. From b3ea655665e101d068c0df6edcf7309176397387 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 17 Dec 2021 15:22:14 +0900 Subject: [PATCH 355/407] docs: change text decoration --- user_guide_src/source/general/environments.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/environments.rst b/user_guide_src/source/general/environments.rst index ca9c6efc1042..6abd709a00a9 100644 --- a/user_guide_src/source/general/environments.rst +++ b/user_guide_src/source/general/environments.rst @@ -97,7 +97,7 @@ is affected. Error Reporting --------------- -Setting the ENVIRONMENT constant to a value of 'development' will cause +Setting the ENVIRONMENT constant to a value of ``development`` will cause all PHP errors to be rendered to the browser when they occur. Conversely, setting the constant to 'production' will disable all error output. Disabling error reporting in production is a From a81c37d95aea6c4e15785e86d4067f36146ef1f1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 17 Dec 2021 15:26:49 +0900 Subject: [PATCH 356/407] docs: fix JSONFormatter namespace --- user_guide_src/source/outgoing/api_responses.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/outgoing/api_responses.rst b/user_guide_src/source/outgoing/api_responses.rst index 99e89783f7d5..dd9f9593278f 100644 --- a/user_guide_src/source/outgoing/api_responses.rst +++ b/user_guide_src/source/outgoing/api_responses.rst @@ -113,7 +113,7 @@ support both JSON and XML:: ]; So, if your request asks for JSON formatted data in an **Accept** header, the data array you pass any of the -``respond*`` or ``fail*`` methods will be formatted by the **CodeIgniter\\API\\JSONFormatter** class. The resulting +``respond*`` or ``fail*`` methods will be formatted by the ``CodeIgniter\Format\JSONFormatter`` class. The resulting JSON data will be sent back to the client. Class Reference From d8b2cdc0307a67740851bdf78e5766bec5344b22 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 17 Dec 2021 15:27:21 +0900 Subject: [PATCH 357/407] docs: change text decoration --- user_guide_src/source/outgoing/api_responses.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/outgoing/api_responses.rst b/user_guide_src/source/outgoing/api_responses.rst index dd9f9593278f..92eaa066f36f 100644 --- a/user_guide_src/source/outgoing/api_responses.rst +++ b/user_guide_src/source/outgoing/api_responses.rst @@ -104,7 +104,7 @@ type of response to return. If no matches are found between what the client requ format in this array is what will be returned. Next, you need to define the class that is used to format the array of data. This must be a fully qualified class -name, and the class must implement **CodeIgniter\\Format\\FormatterInterface**. Formatters come out of the box that +name, and the class must implement ``CodeIgniter\Format\FormatterInterface``. Formatters come out of the box that support both JSON and XML:: public $formatters = [ @@ -240,7 +240,7 @@ Class Reference :param string $message: A custom "reason" message to return. :returns: The value of the Response object's send() method. - Unlike ``failUnauthorized``, this method should be used when the requested API endpoint is never allowed. + Unlike ``failUnauthorized()``, this method should be used when the requested API endpoint is never allowed. Unauthorized implies the client is encouraged to try again with different credentials. Forbidden means the client should not try again because it won't help. Status code is 403. From 714235bf39517376c47126d37c77d140a7750391 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 08:56:10 +0900 Subject: [PATCH 358/407] docs: change from note to warning, because it is a security matter --- user_guide_src/source/outgoing/view_parser.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/outgoing/view_parser.rst b/user_guide_src/source/outgoing/view_parser.rst index 8bf3db46bb83..80c2f37d5c73 100644 --- a/user_guide_src/source/outgoing/view_parser.rst +++ b/user_guide_src/source/outgoing/view_parser.rst @@ -356,7 +356,7 @@ of the comparison operators you would normally, like ``==``, ``===``, ``!==``, `

    Welcome, User

    {endif} -.. note:: In the background, conditionals are parsed using an **eval()**, so you must ensure that you take +.. warning:: In the background, conditionals are parsed using an ``eval()``, so you must ensure that you take care with the user data that is used within conditionals, or you could open your application up to security risks. Escaping Data From fec61fb2db116ea766219fde563523c0b2a12c6a Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 09:04:37 +0900 Subject: [PATCH 359/407] docs: change text decration Code is decorated with '``'. --- .../source/outgoing/view_parser.rst | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/user_guide_src/source/outgoing/view_parser.rst b/user_guide_src/source/outgoing/view_parser.rst index 80c2f37d5c73..7070b1f8deac 100644 --- a/user_guide_src/source/outgoing/view_parser.rst +++ b/user_guide_src/source/outgoing/view_parser.rst @@ -53,9 +53,9 @@ can instantiate it directly:: $parser = new \CodeIgniter\View\Parser(); Then you can use any of the three standard rendering methods that it provides: -**render(viewpath, options, save)**, **setVar(name, value, context)** and -**setData(data, context)**. You will also be able to specify delimiters directly, -through the **setDelimiters(left, right)** method. +``render(viewpath, options, save)``, ``setVar(name, value, context)`` and +``setData(data, context)``. You will also be able to specify delimiters directly, +through the ``setDelimiters(left, right)`` method. Using the ``Parser``, your view templates are processed only by the Parser itself, and not like a conventional view PHP script. PHP code in such a script @@ -221,12 +221,12 @@ method:: ->render('blog_template'); If the array you are trying to loop over contains objects instead of arrays, -the parser will first look for an ``asArray`` method on the object. If it exists, +the parser will first look for an ``asArray()`` method on the object. If it exists, that method will be called and the resulting array is then looped over just as -described above. If no ``asArray`` method exists, the object will be cast as +described above. If no ``asArray()`` method exists, the object will be cast as an array and its public properties will be made available to the Parser. -This is especially useful with the Entity classes, which has an asArray method +This is especially useful with the Entity classes, which has an ``asArray()`` method that returns all public and protected properties (minus the _options property) and makes them available to the Parser. @@ -262,8 +262,8 @@ A **blog_template.php** that might work for the above::
    {/blog_entry} -If you would like the other pseudo-variables accessible inside the "blog_entry" -scope, then make sure that the "cascadeData" option is set to true. +If you would like the other pseudo-variables accessible inside the ``blog_entry`` +scope, then make sure that the ``cascadeData`` option is set to true. Comments ======== @@ -362,9 +362,9 @@ of the comparison operators you would normally, like ``==``, ``===``, ``!==``, ` Escaping Data ============= -By default, all variable substitution is escaped to help prevent XSS attacks on your pages. CodeIgniter's ``esc`` method -supports several different contexts, like general **html**, when it's in an HTML **attr**, in **css**, etc. If nothing -else is specified, the data will be assumed to be in an HTML context. You can specify the context used by using the **esc** +By default, all variable substitution is escaped to help prevent XSS attacks on your pages. CodeIgniter's ``esc()`` method +supports several different contexts, like general ``html``, when it's in an HTML ``attr``, in ``css``, etc. If nothing +else is specified, the data will be assumed to be in an HTML context. You can specify the context used by using the ``esc()`` filter:: { user_styles | esc(css) } From c9af04cf985b62d4caafaddf151b9a375e860fbc Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 09:41:31 +0900 Subject: [PATCH 360/407] docs: shorten the width of tables --- .../source/outgoing/view_parser.rst | 144 +++++++++--------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/user_guide_src/source/outgoing/view_parser.rst b/user_guide_src/source/outgoing/view_parser.rst index 7070b1f8deac..e182ce789b35 100644 --- a/user_guide_src/source/outgoing/view_parser.rst +++ b/user_guide_src/source/outgoing/view_parser.rst @@ -402,66 +402,65 @@ Provided Filters The following filters are available when using the parser: -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ **Filter** + **Arguments** + **Description** + **Example** + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ abs + + Displays the absolute value of a number. + { v|abs } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ capitalize + + Displays the string in sentence case: all lowercase + { v|capitalize} + -+ + + with firstletter capitalized. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ date + format (Y-m-d) + A PHP **date**-compatible formatting string. + { v|date(Y-m-d) } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ date_modify + value to add + A **strtotime** compatible string to modify the date, + { v|date_modify(+1 day) } + -+ + / subtract + like ``+5 day`` or ``-1 week``. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ default + default value + Displays the default value if the variable is empty or + { v|default(just in case) } + -+ + + undefined. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ esc + html, attr, css, js + Specifies the context to escape the data. + { v|esc(attr) } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ excerpt + phrase, radius + Returns the text within a radius of words from a given + { v|excerpt(green giant, 20) } + -+ + + phrase. Same as **excerpt** helper function. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ highlight + phrase + Highlights a given phrase within the text using + { v|highlight(view parser) } + -+ + + '' tags. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ highlight_code+ + Highlights code samples with HTML/CSS. + { v|highlight_code } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ limit_chars + limit + Limits the number of characters to $limit. + { v|limit_chars(100) } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ limit_words + limit + Limits the number of words to $limit. + { v|limit_words(20) } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ local_currency+ currency, locale + Displays a localized version of a currency. "currency" + { v|local_currency(EUR,en_US) } + -+ + + valueis any 3-letter ISO 4217 currency code. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ local_number + type, precision, + Displays a localized version of a number. "type" can be + { v|local_number(decimal,2,en_US) } + -+ + locale + one of: decimal, currency, percent, scientific, spellout, + + -+ + + ordinal, duration. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ lower + + Converts a string to lowercase. + { v|lower } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ nl2br + + Replaces all newline characters (\n) to an HTML
    tag. + { v|nl2br } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ number_format + places + Wraps PHP **number_format** function for use within the + { v|number_format(3) } + -+ + + parser. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ prose + + Takes a body of text and uses the **auto_typography()** + { v|prose } + -+ + + method to turn it into prettier, easier-to-read, prose. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ round + places, type + Rounds a number to the specified places. Types of **ceil** + { v|round(3) } { v|round(ceil) } + -+ + + and **floor** can be passed to use those functions instead. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ strip_tags + allowed chars + Wraps PHP **strip_tags**. Can accept a string of allowed + { v|strip_tags(
    ) } + -+ + + tags. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ title + + Displays a "title case" version of the string, with all + { v|title } + -+ + + lowercase, and each word capitalized. + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ upper + + Displays the string in all uppercase. + { v|upper } + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ -+ + + + + -+---------------+---------------------+--------------------------------------------------------------+-------------------------------------+ +================ ================= =========================================================== ====================================== +Filter Arguments Description Example +================ ================= =========================================================== ====================================== +abs Displays the absolute value of a number. { v|abs } + +capitalize Displays the string in sentence case: all lowercase { v|capitalize} + with firstletter capitalized. + +date format (Y-m-d) A PHP **date**-compatible formatting string. { v|date(Y-m-d) } + +date_modify value to add A **strtotime** compatible string to modify the date, { v|date_modify(+1 day) } + / subtract like ``+5 day`` or ``-1 week``. + +default default value Displays the default value if the variable is empty or { v|default(just in case) } + undefined. + +esc html, attr, Specifies the context to escape the data. { v|esc(attr) } + css, js + +excerpt phrase, radius Returns the text within a radius of words from a given { v|excerpt(green giant, 20) } + phrase. Same as **excerpt** helper function. + +highlight phrase Highlights a given phrase within the text using { v|highlight(view parser) } + '' tags. + +highlight_code Highlights code samples with HTML/CSS. { v|highlight_code } + +limit_chars limit Limits the number of characters to $limit. { v|limit_chars(100) } + +limit_words limit Limits the number of words to $limit. { v|limit_words(20) } + +local_currency currency, locale Displays a localized version of a currency. "currency" { v|local_currency(EUR,en_US) } + valueis any 3-letter ISO 4217 currency code. + +local_number type, precision, Displays a localized version of a number. "type" can be { v|local_number(decimal,2,en_US) } + locale one of: decimal, currency, percent, scientific, spellout, + ordinal, duration. + +lower Converts a string to lowercase. { v|lower } + +nl2br Replaces all newline characters (\n) to an HTML
    tag. { v|nl2br } + +number_format places Wraps PHP **number_format** function for use within the { v|number_format(3) } + parser. + +prose Takes a body of text and uses the **auto_typography()** { v|prose } + method to turn it into prettier, easier-to-read, prose. + +round places, type Rounds a number to the specified places. Types of **ceil** { v|round(3) } { v|round(ceil) } + and **floor** can be passed to use those functions instead. + +strip_tags allowed chars Wraps PHP **strip_tags**. Can accept a string of allowed { v|strip_tags(
    ) } + tags. + +title Displays a "title case" version of the string, with all { v|title } + lowercase, and each word capitalized. + +upper Displays the string in all uppercase. { v|upper } +================ ================= =========================================================== ====================================== See `PHP's NumberFormatter `_ for details relevant to the "local_number" filter. @@ -519,18 +518,19 @@ Provided Plugins The following plugins are available when using the parser: -==================== ========================== ================================================================================== ================================================================ -Plugin Arguments Description Example -==================== ========================== ================================================================================== ================================================================ -current_url Alias for the current_url helper function. {+ current_url +} -previous_url Alias for the previous_url helper function. {+ previous_url +} -siteURL Alias for the site_url helper function. {+ siteURL "login" +} -mailto email, title, attributes Alias for the mailto helper function. {+ mailto email=foo@example.com title="Stranger Things" +} -safe_mailto email, title, attributes Alias for the safe_mailto helper function. {+ safe_mailto email=foo@example.com title="Stranger Things" +} -lang language string Alias for the lang helper function. {+ lang number.terabyteAbbr +} -validation_errors fieldname(optional) Returns either error string for the field (if specified) or all validation errors. {+ validation_errors +} , {+ validation_errors field="email" +} -route route name Alias for the route_to helper function. {+ route "login" +} -==================== ========================== ================================================================================== ================================================================ +================== ========================= ============================================ ================================================================ +Plugin Arguments Description Example +================== ========================= ============================================ ================================================================ +current_url Alias for the current_url helper function. {+ current_url +} +previous_url Alias for the previous_url helper function. {+ previous_url +} +siteURL Alias for the site_url helper function. {+ siteURL "login" +} +mailto email, title, attributes Alias for the mailto helper function. {+ mailto email=foo@example.com title="Stranger Things" +} +safe_mailto email, title, attributes Alias for the safe_mailto helper function. {+ safe_mailto email=foo@example.com title="Stranger Things" +} +lang language string Alias for the lang helper function. {+ lang number.terabyteAbbr +} +validation_errors fieldname(optional) Returns either error string for the field {+ validation_errors +} , {+ validation_errors field="email" +} + (if specified) or all validation errors. +route route name Alias for the route_to helper function. {+ route "login" +} +================== ========================= ============================================ ================================================================ Registering a Plugin -------------------- From 3b1078f93aeb4d34f075817b81525078400ddb01 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 10:35:36 +0900 Subject: [PATCH 361/407] docs: change text decoration --- user_guide_src/source/libraries/validation.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index b29f6651d4eb..be46d861e747 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -527,7 +527,7 @@ or the value that was validated you can add the ``{field}``, ``{param}`` and ``{ 'min_length' => 'Supplied value ({value}) for {field} must have at least {param} characters.' -On a field with the human name Username and a rule of min_length[6] with a value of “Pizza”, an error would display: “Supplied value (Pizza) for Username must have +On a field with the human name Username and a rule of ``min_length[6]`` with a value of “Pizza”, an error would display: “Supplied value (Pizza) for Username must have at least 6 characters.” .. note:: If you pass the last parameter the labeled style error messages will be ignored. @@ -643,11 +643,11 @@ short alias they can be referenced by. If we were to add our example file from a Specifying the Template ======================= -You can specify the template to use by passing it's alias as the first parameter in ``listErrors``:: +You can specify the template to use by passing it's alias as the first parameter in ``listErrors()``:: listErrors('my_list') ?> -When showing field-specific errors, you can pass the alias as the second parameter to the ``showError`` method, +When showing field-specific errors, you can pass the alias as the second parameter to the ``showError()`` method, right after the name of the field the error should belong to:: showError('username', 'my_single') ?> From d16fec7fdf4def1b18d1f9c1c995ed03d149fb48 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 10:39:52 +0900 Subject: [PATCH 362/407] docs: fix note explanation --- user_guide_src/source/libraries/validation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index be46d861e747..137da33afdee 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -530,7 +530,7 @@ or the value that was validated you can add the ``{field}``, ``{param}`` and ``{ On a field with the human name Username and a rule of ``min_length[6]`` with a value of “Pizza”, an error would display: “Supplied value (Pizza) for Username must have at least 6 characters.” -.. note:: If you pass the last parameter the labeled style error messages will be ignored. +.. note:: When using label-style error messages, if you pass the second parameter to ``setRules()``, it will be overwritten with the value of the first parameter. Translation Of Messages And Validation Labels ============================================= From 6750eee38449c987b285c60ed85346bab3ee8a58 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 10:41:44 +0900 Subject: [PATCH 363/407] docs: add warning about XSS risk --- user_guide_src/source/libraries/validation.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index 137da33afdee..ae2e48962f3b 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -530,6 +530,8 @@ or the value that was validated you can add the ``{field}``, ``{param}`` and ``{ On a field with the human name Username and a rule of ``min_length[6]`` with a value of “Pizza”, an error would display: “Supplied value (Pizza) for Username must have at least 6 characters.” +.. warning:: If you get the error messages with ``getErrors()`` or ``getError()``, the messages are not HTML escaped. If you use user input data like ``({value})`` to make the error message, it might contain HTML tags. If you don't escape the messages before displying them, XSS attacks are possible. + .. note:: When using label-style error messages, if you pass the second parameter to ``setRules()``, it will be overwritten with the value of the first parameter. Translation Of Messages And Validation Labels From d2f12fb8da231ba027e52b00555ea19d19e762f3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 10:42:02 +0900 Subject: [PATCH 364/407] docs: remove uneeded '*' --- user_guide_src/source/libraries/validation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index ae2e48962f3b..960a1bce3dda 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -594,7 +594,7 @@ You can check to see if an error exists with the ``hasError()`` method. The only } Customizing Error Display -************************************************ +************************* When you call ``$validation->listErrors()`` or ``$validation->showError()``, it loads a view file in the background that determines how the errors are displayed. By default, they display with a class of ``errors`` on the wrapping div. From dc969c1f4272710b3dfa2386e91267dc1039e4cd Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 18 Dec 2021 10:54:29 +0900 Subject: [PATCH 365/407] docs: fix directory inconsistency --- user_guide_src/source/models/entities.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/models/entities.rst b/user_guide_src/source/models/entities.rst index 489685a8c5ff..34928d628dbe 100644 --- a/user_guide_src/source/models/entities.rst +++ b/user_guide_src/source/models/entities.rst @@ -425,11 +425,11 @@ Custom casting You can define your own conversion types for getting and setting data. At first you need to create a handler class for your type. -Let's say the class will be located in the **app/Entity/Cast** directory:: +Let's say the class will be located in the **app/Entities/Cast** directory:: \App\Entity\Cast\CastBase64::class, + 'base64' => \App\Entities\Cast\CastBase64::class, ]; } From 31fb03b98571c5453d18c773bfe99b96c569cfc7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 15 Dec 2021 16:38:05 +0900 Subject: [PATCH 366/407] fix: does not show correct token time until 1 token is available Fixes #5458 --- system/Throttle/Throttler.php | 30 +++++++++++++-------- tests/system/Throttle/ThrottleTest.php | 36 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/system/Throttle/Throttler.php b/system/Throttle/Throttler.php index 5154f386439b..28d08739e123 100644 --- a/system/Throttle/Throttler.php +++ b/system/Throttle/Throttler.php @@ -95,13 +95,21 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): { $tokenName = $this->prefix . $key; + // Number of tokens to add back per second + $rate = $capacity / $seconds; + // Number of seconds to get one token + $refresh = 1 / $rate; + // Check to see if the bucket has even been created yet. if (($tokens = $this->cache->get($tokenName)) === null) { // If it hasn't been created, then we'll set it to the maximum // capacity - 1, and save it to the cache. - $this->cache->save($tokenName, $capacity - $cost, $seconds); + $tokens = $capacity - $cost; + $this->cache->save($tokenName, $tokens, $seconds); $this->cache->save($tokenName . 'Time', $this->time(), $seconds); + $this->tokenTime = max(1, (int) $refresh); + return true; } @@ -110,15 +118,6 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): $throttleTime = $this->cache->get($tokenName . 'Time'); $elapsed = $this->time() - $throttleTime; - // Number of tokens to add back per second - $rate = $capacity / $seconds; - - // How many seconds till a new token is available. - // We must have a minimum wait of 1 second for a new token. - // Primarily stored to allow devs to report back to users. - $newTokenAvailable = (1 / $rate) - $elapsed; - $this->tokenTime = max(1, $newTokenAvailable); - // Add tokens based up on number per second that // should be refilled, then checked against capacity // to be sure the bucket didn't overflow. @@ -128,12 +127,21 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): // If $tokens >= 1, then we are safe to perform the action, but // we need to decrement the number of available tokens. if ($tokens >= 1) { - $this->cache->save($tokenName, $tokens - $cost, $seconds); + $tokens = $tokens - $cost; + $this->cache->save($tokenName, $tokens, $seconds); $this->cache->save($tokenName . 'Time', $this->time(), $seconds); + $this->tokenTime = max(1, (int) ($refresh - $elapsed)); + return true; } + // How many seconds till a new token is available. + // We must have a minimum wait of 1 second for a new token. + // Primarily stored to allow devs to report back to users. + $newTokenAvailable = (int) ($refresh - $elapsed - $refresh * $tokens); + $this->tokenTime = max(1, $newTokenAvailable); + return false; } diff --git a/tests/system/Throttle/ThrottleTest.php b/tests/system/Throttle/ThrottleTest.php index 498cbf0673d5..930e34c5e184 100644 --- a/tests/system/Throttle/ThrottleTest.php +++ b/tests/system/Throttle/ThrottleTest.php @@ -45,6 +45,42 @@ public function testTokenTime() $this->assertGreaterThanOrEqual(1, $throttler->getTokenTime()); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5458 + */ + public function testTokenTimeCalculation() + { + $time = 1639441295; + + $throttler = new Throttler($this->cache); + $throttler->setTestTime($time); + + $capacity = 2; + $seconds = 200; + + // refresh = 200 / 2 = 100 seconds + // refresh rate = 2 / 200 = 0.01 token per second + + // token should be 2 + $this->assertTrue($throttler->check('test', $capacity, $seconds)); + // token should be 2 - 1 = 1 + $this->assertSame(100, $throttler->getTokenTime(), 'Wrong token time'); + + // do nothing for 3 seconds + $throttler = $throttler->setTestTime($time + 3); + + // token should be 1 + 3 * 0.01 = 1.03 + $this->assertTrue($throttler->check('test', $capacity, $seconds)); + // token should be 1.03 - 1 = 0.03 + $this->assertSame(97, $throttler->getTokenTime(), 'Wrong token time'); + + $this->assertFalse($throttler->check('test', $capacity, $seconds)); + // token should still be 0.03 because check failed + + // expect remaining time: (1 - 0.03) * 100 = 97 + $this->assertSame(97, $throttler->getTokenTime(), 'Wrong token time'); + } + public function testIPSavesBucket() { $throttler = new Throttler($this->cache); From 10f772a4b93f2d18cbee03cb6ccd6cccda9a8636 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 15 Dec 2021 16:39:44 +0900 Subject: [PATCH 367/407] docs: update sample code in comment --- system/Throttle/Throttler.php | 5 ++--- tests/system/Throttle/ThrottleTest.php | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/system/Throttle/Throttler.php b/system/Throttle/Throttler.php index 28d08739e123..239abd0d6d20 100644 --- a/system/Throttle/Throttler.php +++ b/system/Throttle/Throttler.php @@ -79,10 +79,9 @@ public function getTokenTime(): int * * Example: * - * if (! $throttler->check($request->ipAddress(), 60, MINUTE)) - * { + * if (! $throttler->check($request->ipAddress(), 60, MINUTE)) { * die('You submitted over 60 requests within a minute.'); - * } + * } * * @param string $key The name to use as the "bucket" name. * @param int $capacity The number of requests the "bucket" can hold diff --git a/tests/system/Throttle/ThrottleTest.php b/tests/system/Throttle/ThrottleTest.php index 930e34c5e184..8da9e6fe4396 100644 --- a/tests/system/Throttle/ThrottleTest.php +++ b/tests/system/Throttle/ThrottleTest.php @@ -56,7 +56,7 @@ public function testTokenTimeCalculation() $throttler->setTestTime($time); $capacity = 2; - $seconds = 200; + $seconds = 200; // refresh = 200 / 2 = 100 seconds // refresh rate = 2 / 200 = 0.01 token per second From 47c4c9cdc7041725a6a911aabc77b1a1ed9f011a Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 15 Dec 2021 21:49:28 +0900 Subject: [PATCH 368/407] fix: tokenTime calcuration When check() returns false, tokenTime is 0. --- system/Throttle/Throttler.php | 4 ++-- tests/system/Throttle/ThrottleTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/system/Throttle/Throttler.php b/system/Throttle/Throttler.php index 239abd0d6d20..89c32981a841 100644 --- a/system/Throttle/Throttler.php +++ b/system/Throttle/Throttler.php @@ -107,7 +107,7 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): $this->cache->save($tokenName, $tokens, $seconds); $this->cache->save($tokenName . 'Time', $this->time(), $seconds); - $this->tokenTime = max(1, (int) $refresh); + $this->tokenTime = 0; return true; } @@ -130,7 +130,7 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): $this->cache->save($tokenName, $tokens, $seconds); $this->cache->save($tokenName . 'Time', $this->time(), $seconds); - $this->tokenTime = max(1, (int) ($refresh - $elapsed)); + $this->tokenTime = 0; return true; } diff --git a/tests/system/Throttle/ThrottleTest.php b/tests/system/Throttle/ThrottleTest.php index 8da9e6fe4396..cc8ccb82856d 100644 --- a/tests/system/Throttle/ThrottleTest.php +++ b/tests/system/Throttle/ThrottleTest.php @@ -36,11 +36,11 @@ public function testTokenTime() // set $rate $rate = 1; // allow 1 request per minute - // first check just creates a bucket, so tokenTime should be 0 + // When the first check you have a token, so tokenTime should be 0 $throttler->check('127.0.0.1', $rate, MINUTE); $this->assertSame(0, $throttler->getTokenTime()); - // additional check affects tokenTime, so tokenTime should be 1 or greater + // When additional check you don't have one token, so tokenTime should be 1 or greater $throttler->check('127.0.0.1', $rate, MINUTE); $this->assertGreaterThanOrEqual(1, $throttler->getTokenTime()); } @@ -64,7 +64,7 @@ public function testTokenTimeCalculation() // token should be 2 $this->assertTrue($throttler->check('test', $capacity, $seconds)); // token should be 2 - 1 = 1 - $this->assertSame(100, $throttler->getTokenTime(), 'Wrong token time'); + $this->assertSame(0, $throttler->getTokenTime(), 'Wrong token time'); // do nothing for 3 seconds $throttler = $throttler->setTestTime($time + 3); @@ -72,7 +72,7 @@ public function testTokenTimeCalculation() // token should be 1 + 3 * 0.01 = 1.03 $this->assertTrue($throttler->check('test', $capacity, $seconds)); // token should be 1.03 - 1 = 0.03 - $this->assertSame(97, $throttler->getTokenTime(), 'Wrong token time'); + $this->assertSame(0, $throttler->getTokenTime(), 'Wrong token time'); $this->assertFalse($throttler->check('test', $capacity, $seconds)); // token should still be 0.03 because check failed From cc901dbd138f3e866760d2ca77b602f8a5535845 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 19 Dec 2021 16:14:04 +0900 Subject: [PATCH 369/407] docs: add views()'s option `cache` --- user_guide_src/source/general/common_functions.rst | 3 ++- user_guide_src/source/outgoing/views.rst | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index f4b61548f4da..b9b21e29ba38 100755 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -179,9 +179,10 @@ Service Accessors a convenience method that can be used in Controllers, libraries, and routed closures. - Currently, only two options are available for use within the ``$options`` array: + Currently, these options are available for use within the ``$options`` array: - ``saveData`` specifies that data will persistent between multiple calls to ``view()`` within the same request. If you do not want the data to be persisted, specify false. + - ``cache`` specifies the number of seconds to cache the view for. See :ref:`caching-views` for the details. - ``debug`` can be set to false to disable the addition of debug code for :ref:`Debug Toolbar `. The ``$option`` array is provided primarily to facilitate third-party integrations with diff --git a/user_guide_src/source/outgoing/views.rst b/user_guide_src/source/outgoing/views.rst index 5cc77d05a3a4..96e350216ce7 100644 --- a/user_guide_src/source/outgoing/views.rst +++ b/user_guide_src/source/outgoing/views.rst @@ -113,6 +113,8 @@ example, you could load the **blog_view.php** file from **example/blog/Views** b echo view('Example\Blog\Views\blog_view'); +.. _caching-views: + Caching Views ============= From 95bad7cb0464c22179e522063903ea59ffb25c1c Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 19 Dec 2021 16:24:07 +0900 Subject: [PATCH 370/407] chore: update Kint to ^4.0 --- composer.json | 2 +- system/ThirdParty/Kint/CallFinder.php | 124 ++++++--- system/ThirdParty/Kint/Kint.php | 256 ++++++++---------- .../Kint/Parser/ArrayLimitPlugin.php | 142 ++++++++++ .../Kint/Parser/ArrayObjectPlugin.php | 6 +- .../ThirdParty/Kint/Parser/Base64Plugin.php | 11 +- .../ThirdParty/Kint/Parser/BinaryPlugin.php | 10 +- .../Kint/Parser/BlacklistPlugin.php | 74 +---- .../Kint/Parser/ClassMethodsPlugin.php | 26 +- .../Kint/Parser/ClassStaticsPlugin.php | 46 ++-- .../ThirdParty/Kint/Parser/ClosurePlugin.php | 26 +- system/ThirdParty/Kint/Parser/ColorPlugin.php | 8 +- .../Kint/Parser/DOMDocumentPlugin.php | 107 ++++---- .../ThirdParty/Kint/Parser/DateTimePlugin.php | 10 +- .../ThirdParty/Kint/Parser/FsPathPlugin.php | 10 +- .../ThirdParty/Kint/Parser/IteratorPlugin.php | 25 +- system/ThirdParty/Kint/Parser/JsonPlugin.php | 10 +- .../Kint/Parser/MicrotimePlugin.php | 10 +- .../ThirdParty/Kint/Parser/MysqliPlugin.php | 98 +++++-- system/ThirdParty/Kint/Parser/Parser.php | 223 ++++++++------- system/ThirdParty/Kint/Parser/Plugin.php | 6 +- system/ThirdParty/Kint/Parser/ProxyPlugin.php | 6 +- .../Kint/Parser/SerializePlugin.php | 18 +- .../Kint/Parser/SimpleXMLElementPlugin.php | 189 ++++++++----- .../Kint/Parser/SplFileInfoPlugin.php | 8 +- .../Kint/Parser/SplObjectStoragePlugin.php | 6 +- .../ThirdParty/Kint/Parser/StreamPlugin.php | 23 +- system/ThirdParty/Kint/Parser/TablePlugin.php | 8 +- .../Kint/Parser/ThrowablePlugin.php | 12 +- .../Kint/Parser/TimestampPlugin.php | 12 +- .../ThirdParty/Kint/Parser/ToStringPlugin.php | 12 +- system/ThirdParty/Kint/Parser/TracePlugin.php | 46 +++- system/ThirdParty/Kint/Parser/XmlPlugin.php | 31 ++- .../ThirdParty/Kint/Renderer/CliRenderer.php | 18 +- .../Kint/Renderer/PlainRenderer.php | 34 +-- system/ThirdParty/Kint/Renderer/Renderer.php | 52 ++-- .../Kint/Renderer/Rich/ArrayLimitPlugin.php | 36 +++ .../Kint/Renderer/Rich/BinaryPlugin.php | 15 +- .../Kint/Renderer/Rich/BlacklistPlugin.php | 6 +- .../Kint/Renderer/Rich/CallablePlugin.php | 40 +-- .../Kint/Renderer/Rich/ClosurePlugin.php | 10 +- .../Kint/Renderer/Rich/ColorPlugin.php | 12 +- .../Kint/Renderer/Rich/DepthLimitPlugin.php | 6 +- .../Kint/Renderer/Rich/DocstringPlugin.php | 10 +- .../Kint/Renderer/Rich/MicrotimePlugin.php | 6 +- .../ThirdParty/Kint/Renderer/Rich/Plugin.php | 7 +- .../Kint/Renderer/Rich/RecursionPlugin.php | 6 +- .../Renderer/Rich/SimpleXMLElementPlugin.php | 20 +- .../Kint/Renderer/Rich/SourcePlugin.php | 6 +- .../Kint/Renderer/Rich/TabPluginInterface.php | 7 +- .../Kint/Renderer/Rich/TablePlugin.php | 8 +- .../Kint/Renderer/Rich/TimestampPlugin.php | 2 +- .../Kint/Renderer/Rich/TraceFramePlugin.php | 10 +- ...Interface.php => ValuePluginInterface.php} | 9 +- .../ThirdParty/Kint/Renderer/RichRenderer.php | 98 ++++--- .../Kint/Renderer/Text/ArrayLimitPlugin.php | 44 +++ .../Kint/Renderer/Text/BlacklistPlugin.php | 4 +- .../Kint/Renderer/Text/DepthLimitPlugin.php | 4 +- .../Kint/Renderer/Text/MicrotimePlugin.php | 8 +- .../ThirdParty/Kint/Renderer/Text/Plugin.php | 7 +- .../Kint/Renderer/Text/RecursionPlugin.php | 4 +- .../Kint/Renderer/Text/TracePlugin.php | 8 +- .../ThirdParty/Kint/Renderer/TextRenderer.php | 36 +-- system/ThirdParty/Kint/Utils.php | 69 +++-- .../BlobObject.php => Zval/BlobValue.php} | 14 +- .../ClosureValue.php} | 10 +- .../DateTimeValue.php} | 6 +- .../InstanceValue.php} | 14 +- .../MethodObject.php => Zval/MethodValue.php} | 32 +-- .../ParameterValue.php} | 7 +- .../Representation/ColorRepresentation.php | 31 +-- .../DocstringRepresentation.php | 4 +- .../MicrotimeRepresentation.php | 4 +- .../Representation/Representation.php | 6 +- .../Representation/SourceRepresentation.php | 6 +- .../SplFileInfoRepresentation.php | 16 +- .../ResourceValue.php} | 6 +- .../Kint/Zval/SimpleXMLElementValue.php | 48 ++++ .../StreamObject.php => Zval/StreamValue.php} | 4 +- .../ThrowableValue.php} | 8 +- .../TraceFrameValue.php} | 31 ++- .../TraceObject.php => Zval/TraceValue.php} | 6 +- .../BasicObject.php => Zval/Value.php} | 28 +- system/ThirdParty/Kint/init.php | 14 +- system/ThirdParty/Kint/init_helpers.php | 16 +- .../Kint/resources/compiled/aante-light.css | 2 +- .../Kint/resources/compiled/microtime.js | 2 +- .../Kint/resources/compiled/original.css | 2 +- .../Kint/resources/compiled/rich.js | 2 +- .../Kint/resources/compiled/shared.js | 2 +- .../resources/compiled/solarized-dark.css | 2 +- .../Kint/resources/compiled/solarized.css | 2 +- 92 files changed, 1511 insertions(+), 1017 deletions(-) create mode 100644 system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php create mode 100644 system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php rename system/ThirdParty/Kint/Renderer/Rich/{ObjectPluginInterface.php => ValuePluginInterface.php} (88%) create mode 100644 system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php rename system/ThirdParty/Kint/{Object/BlobObject.php => Zval/BlobValue.php} (95%) rename system/ThirdParty/Kint/{Object/ClosureObject.php => Zval/ClosureValue.php} (91%) rename system/ThirdParty/Kint/{Object/DateTimeObject.php => Zval/DateTimeValue.php} (93%) rename system/ThirdParty/Kint/{Object/InstanceObject.php => Zval/InstanceValue.php} (88%) rename system/ThirdParty/Kint/{Object/MethodObject.php => Zval/MethodValue.php} (90%) rename system/ThirdParty/Kint/{Object/ParameterObject.php => Zval/ParameterValue.php} (95%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/ColorRepresentation.php (96%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/DocstringRepresentation.php (97%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/MicrotimeRepresentation.php (96%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/Representation.php (95%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/SourceRepresentation.php (96%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/SplFileInfoRepresentation.php (95%) rename system/ThirdParty/Kint/{Object/ResourceObject.php => Zval/ResourceValue.php} (93%) create mode 100644 system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php rename system/ThirdParty/Kint/{Object/StreamObject.php => Zval/StreamValue.php} (96%) rename system/ThirdParty/Kint/{Object/ThrowableObject.php => Zval/ThrowableValue.php} (88%) rename system/ThirdParty/Kint/{Object/TraceFrameObject.php => Zval/TraceFrameValue.php} (81%) rename system/ThirdParty/Kint/{Object/TraceObject.php => Zval/TraceValue.php} (93%) rename system/ThirdParty/Kint/{Object/BasicObject.php => Zval/Value.php} (91%) diff --git a/composer.json b/composer.json index 38ddfd6ef3c7..330209cb21a6 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "ext-intl": "*", "ext-json": "*", "ext-mbstring": "*", - "kint-php/kint": "^3.3", + "kint-php/kint": "^4.0", "laminas/laminas-escaper": "^2.9", "psr/log": "^1.1" }, diff --git a/system/ThirdParty/Kint/CallFinder.php b/system/ThirdParty/Kint/CallFinder.php index e7192a815284..e77a6407f018 100644 --- a/system/ThirdParty/Kint/CallFinder.php +++ b/system/ThirdParty/Kint/CallFinder.php @@ -27,7 +27,7 @@ class CallFinder { - private static $ignore = array( + private static $ignore = [ T_CLOSE_TAG => true, T_COMMENT => true, T_DOC_COMMENT => true, @@ -35,7 +35,7 @@ class CallFinder T_OPEN_TAG => true, T_OPEN_TAG_WITH_ECHO => true, T_WHITESPACE => true, - ); + ]; /** * Things we need to do specially for operator tokens: @@ -43,17 +43,19 @@ class CallFinder * - Wrap the access path in parentheses if there * are any of these in the final short parameter. */ - private static $operator = array( + private static $operator = [ T_AND_EQUAL => true, T_BOOLEAN_AND => true, T_BOOLEAN_OR => true, T_ARRAY_CAST => true, T_BOOL_CAST => true, + T_CLASS => true, T_CLONE => true, T_CONCAT_EQUAL => true, T_DEC => true, T_DIV_EQUAL => true, T_DOUBLE_CAST => true, + T_FUNCTION => true, T_INC => true, T_INCLUDE => true, T_INCLUDE_ONCE => true, @@ -84,6 +86,9 @@ class CallFinder T_STRING_CAST => true, T_UNSET_CAST => true, T_XOR_EQUAL => true, + T_POW => true, + T_POW_EQUAL => true, + T_DOUBLE_ARROW => true, '!' => true, '%' => true, '&' => true, @@ -100,9 +105,9 @@ class CallFinder '^' => true, '|' => true, '~' => true, - ); + ]; - private static $strip = array( + private static $strip = [ '(' => true, ')' => true, '[' => true, @@ -112,39 +117,43 @@ class CallFinder T_OBJECT_OPERATOR => true, T_DOUBLE_COLON => true, T_NS_SEPARATOR => true, - ); + ]; + + private static $classcalls = [ + T_DOUBLE_COLON => true, + T_OBJECT_OPERATOR => true, + ]; + + private static $namespace = [ + T_STRING => true, + ]; public static function getFunctionCalls($source, $line, $function) { - static $up = array( + static $up = [ '(' => true, '[' => true, '{' => true, T_CURLY_OPEN => true, T_DOLLAR_OPEN_CURLY_BRACES => true, - ); - static $down = array( + ]; + static $down = [ ')' => true, ']' => true, '}' => true, - ); - static $modifiers = array( + ]; + static $modifiers = [ '!' => true, '@' => true, '~' => true, '+' => true, '-' => true, - ); - static $identifier = array( + ]; + static $identifier = [ T_DOUBLE_COLON => true, T_STRING => true, T_NS_SEPARATOR => true, - ); - - if (KINT_PHP56) { - self::$operator[T_POW] = true; - self::$operator[T_POW_EQUAL] = true; - } + ]; if (KINT_PHP70) { self::$operator[T_SPACESHIP] = true; @@ -154,11 +163,24 @@ public static function getFunctionCalls($source, $line, $function) self::$operator[T_COALESCE_EQUAL] = true; } + if (KINT_PHP80) { + $up[T_ATTRIBUTE] = true; + self::$operator[T_MATCH] = true; + self::$strip[T_NULLSAFE_OBJECT_OPERATOR] = true; + self::$classcalls[T_NULLSAFE_OBJECT_OPERATOR] = true; + self::$namespace[T_NAME_FULLY_QUALIFIED] = true; + self::$namespace[T_NAME_QUALIFIED] = true; + self::$namespace[T_NAME_RELATIVE] = true; + $identifier[T_NAME_FULLY_QUALIFIED] = true; + $identifier[T_NAME_QUALIFIED] = true; + $identifier[T_NAME_RELATIVE] = true; + } + $tokens = \token_get_all($source); $cursor = 1; - $function_calls = array(); - /** @var array Performance optimization preventing backwards loops */ - $prev_tokens = array(null, null, null); + $function_calls = []; + // Performance optimization preventing backwards loops + $prev_tokens = [null, null, null]; if (\is_array($function)) { $class = \explode('\\', $function[0]); @@ -188,10 +210,16 @@ public static function getFunctionCalls($source, $line, $function) continue; } - $prev_tokens = array($prev_tokens[1], $prev_tokens[2], $token); + $prev_tokens = [$prev_tokens[1], $prev_tokens[2], $token]; // Check if it's the right type to be the function we're looking for - if (T_STRING !== $token[0] || \strtolower($token[1]) !== $function) { + if (!isset(self::$namespace[$token[0]])) { + continue; + } + + $ns = \explode('\\', \strtolower($token[1])); + + if (\end($ns) !== $function) { continue; } @@ -203,7 +231,7 @@ public static function getFunctionCalls($source, $line, $function) // Check if it matches the signature if (null === $class) { - if ($prev_tokens[1] && \in_array($prev_tokens[1][0], array(T_DOUBLE_COLON, T_OBJECT_OPERATOR), true)) { + if ($prev_tokens[1] && isset(self::$classcalls[$prev_tokens[1][0]])) { continue; } } else { @@ -211,7 +239,15 @@ public static function getFunctionCalls($source, $line, $function) continue; } - if (!$prev_tokens[0] || T_STRING !== $prev_tokens[0][0] || \strtolower($prev_tokens[0][1]) !== $class) { + if (!$prev_tokens[0] || !isset(self::$namespace[$prev_tokens[0][0]])) { + continue; + } + + /** @var array{int, string, int} $prev_tokens[0] */ + // All self::$namespace tokens are T_ constants + $ns = \explode('\\', \strtolower($prev_tokens[0][1])); + + if (\end($ns) !== $class) { continue; } } @@ -222,8 +258,8 @@ public static function getFunctionCalls($source, $line, $function) $instring = false; // Whether we're in a string or not $realtokens = false; // Whether the current scope contains anything meaningful or not $paramrealtokens = false; // Whether the current parameter contains anything meaningful - $params = array(); // All our collected parameters - $shortparam = array(); // The short version of the parameter + $params = []; // All our collected parameters + $shortparam = []; // The short version of the parameter $param_start = $offset; // The distance to the start of the parameter // Loop through the following tokens until the function call ends @@ -276,11 +312,11 @@ public static function getFunctionCalls($source, $line, $function) $shortparam[] = '"'; } elseif (1 === $depth) { if (',' === $token[0]) { - $params[] = array( + $params[] = [ 'full' => \array_slice($tokens, $param_start, $offset - $param_start), 'short' => $shortparam, - ); - $shortparam = array(); + ]; + $shortparam = []; $paramrealtokens = false; $param_start = $offset + 1; } elseif (T_CONSTANT_ENCAPSED_STRING === $token[0] && \strlen($token[1]) > 2) { @@ -293,10 +329,10 @@ public static function getFunctionCalls($source, $line, $function) // Depth has dropped to 0 (So we've hit the closing paren) if ($depth <= 0) { if ($paramrealtokens) { - $params[] = array( + $params[] = [ 'full' => \array_slice($tokens, $param_start, $offset - $param_start), 'short' => $shortparam, - ); + ]; } break; @@ -322,11 +358,11 @@ public static function getFunctionCalls($source, $line, $function) } } - $param = array( + $param = [ 'name' => self::tokensToString($name), 'path' => self::tokensToString(self::tokensTrim($param['full'])), 'expression' => $expression, - ); + ]; } // Get the modifiers @@ -340,7 +376,7 @@ public static function getFunctionCalls($source, $line, $function) --$index; } - $mods = array(); + $mods = []; while (isset($tokens[$index])) { if (isset(self::$ignore[$tokens[$index][0]])) { @@ -357,10 +393,10 @@ public static function getFunctionCalls($source, $line, $function) break; } - $function_calls[] = array( + $function_calls[] = [ 'parameters' => $params, 'modifiers' => $mods, - ); + ]; } return $function_calls; @@ -436,10 +472,11 @@ private static function tokensTrim(array $tokens) private static function tokensFormatted(array $tokens) { $space = false; + $attribute = false; $tokens = self::tokensTrim($tokens); - $output = array(); + $output = []; $last = null; foreach ($tokens as $index => $token) { @@ -450,7 +487,10 @@ private static function tokensFormatted(array $tokens) $next = $tokens[self::realTokenIndex($tokens, $index)]; - if (isset(self::$strip[$last[0]]) && !self::tokenIsOperator($next)) { + /** @var array|string $last */ + if ($attribute && ']' === $last[0]) { + $attribute = false; + } elseif (isset(self::$strip[$last[0]]) && !self::tokenIsOperator($next)) { continue; } @@ -461,6 +501,10 @@ private static function tokensFormatted(array $tokens) $token = ' '; $space = true; } else { + if (KINT_PHP80 && $last && T_ATTRIBUTE == $last[0]) { + $attribute = true; + } + $space = false; $last = $token; } diff --git a/system/ThirdParty/Kint/Kint.php b/system/ThirdParty/Kint/Kint.php index e0ce96337753..f11ed498c45f 100644 --- a/system/ThirdParty/Kint/Kint.php +++ b/system/ThirdParty/Kint/Kint.php @@ -26,11 +26,11 @@ namespace Kint; use InvalidArgumentException; -use Kint\Object\BasicObject; use Kint\Parser\Parser; use Kint\Parser\Plugin; use Kint\Renderer\Renderer; use Kint\Renderer\TextRenderer; +use Kint\Zval\Value; class Kint { @@ -102,12 +102,12 @@ class Kint * * Defaults to [$_SERVER['DOCUMENT_ROOT'] => ''] */ - public static $app_root_dirs = array(); + public static $app_root_dirs = []; /** - * @var int max array/object levels to go deep, if zero no limits are applied + * @var int depth limit for array/object traversal. 0 for no limit */ - public static $max_depth = 6; + public static $depth_limit = 7; /** * @var bool expand all trees by default for rich view @@ -124,23 +124,24 @@ class Kint /** * @var array Kint aliases. Add debug functions in Kint wrappers here to fix modifiers and backtraces */ - public static $aliases = array( - array('Kint\\Kint', 'dump'), - array('Kint\\Kint', 'trace'), - array('Kint\\Kint', 'dumpArray'), - ); + public static $aliases = [ + ['Kint\\Kint', 'dump'], + ['Kint\\Kint', 'trace'], + ['Kint\\Kint', 'dumpArray'], + ]; /** * @var array Array of modes to renderer class names */ - public static $renderers = array( + public static $renderers = [ self::MODE_RICH => 'Kint\\Renderer\\RichRenderer', self::MODE_PLAIN => 'Kint\\Renderer\\PlainRenderer', self::MODE_TEXT => 'Kint\\Renderer\\TextRenderer', self::MODE_CLI => 'Kint\\Renderer\\CliRenderer', - ); + ]; - public static $plugins = array( + public static $plugins = [ + 'Kint\\Parser\\ArrayLimitPlugin', 'Kint\\Parser\\ArrayObjectPlugin', 'Kint\\Parser\\Base64Plugin', 'Kint\\Parser\\BlacklistPlugin', @@ -162,9 +163,9 @@ class Kint 'Kint\\Parser\\TimestampPlugin', 'Kint\\Parser\\TracePlugin', 'Kint\\Parser\\XmlPlugin', - ); + ]; - protected static $plugin_pool = array(); + protected static $plugin_pool = []; protected $parser; protected $renderer; @@ -199,24 +200,25 @@ public function setStatesFromStatics(array $statics) { $this->renderer->setStatics($statics); - $this->parser->setDepthLimit(isset($statics['max_depth']) ? $statics['max_depth'] : false); + $this->parser->setDepthLimit(isset($statics['depth_limit']) ? $statics['depth_limit'] : 0); $this->parser->clearPlugins(); if (!isset($statics['plugins'])) { return; } - $plugins = array(); + $plugins = []; foreach ($statics['plugins'] as $plugin) { if ($plugin instanceof Plugin) { $plugins[] = $plugin; - } elseif (\is_string($plugin) && \is_subclass_of($plugin, 'Kint\\Parser\\Plugin')) { - if (!isset(self::$plugin_pool[$plugin])) { + } elseif (\is_string($plugin) && \is_subclass_of($plugin, Plugin::class)) { + if (!isset(static::$plugin_pool[$plugin])) { + /** @psalm-suppress UnsafeInstantiation */ $p = new $plugin(); - self::$plugin_pool[$plugin] = $p; + static::$plugin_pool[$plugin] = $p; } - $plugins[] = self::$plugin_pool[$plugin]; + $plugins[] = static::$plugin_pool[$plugin]; } } @@ -232,7 +234,7 @@ public function setStatesFromCallInfo(array $info) $this->renderer->setCallInfo($info); if (isset($info['modifiers']) && \is_array($info['modifiers']) && \in_array('+', $info['modifiers'], true)) { - $this->parser->setDepthLimit(false); + $this->parser->setDepthLimit(0); } $this->parser->setCallerClass(isset($info['caller']['class']) ? $info['caller']['class'] : null); @@ -241,8 +243,8 @@ public function setStatesFromCallInfo(array $info) /** * Renders a list of vars including the pre and post renders. * - * @param array $vars Data to dump - * @param BasicObject[] $base Base objects + * @param array $vars Data to dump + * @param array $base Base Zval\Value objects * * @return string */ @@ -254,13 +256,13 @@ public function dumpAll(array $vars, array $base) $output = $this->renderer->preRender(); - if ($vars === array()) { + if ([] === $vars) { $output .= $this->renderer->renderNothing(); } foreach ($vars as $key => $arg) { - if (!$base[$key] instanceof BasicObject) { - throw new InvalidArgumentException('Kint::dumpAll requires all elements of the second argument to be BasicObject instances'); + if (!$base[$key] instanceof Value) { + throw new InvalidArgumentException('Kint::dumpAll requires all elements of the second argument to be Value instances'); } $output .= $this->dumpVar($arg, $base[$key]); } @@ -273,12 +275,12 @@ public function dumpAll(array $vars, array $base) /** * Dumps and renders a var. * - * @param mixed $var Data to dump - * @param BasicObject $base Base object + * @param mixed $var Data to dump + * @param Value $base Base object * * @return string */ - public function dumpVar(&$var, BasicObject $base) + public function dumpVar(&$var, Value $base) { return $this->renderer->render( $this->parser->parse($var, $base) @@ -292,21 +294,21 @@ public function dumpVar(&$var, BasicObject $base) */ public static function getStatics() { - return array( - 'aliases' => self::$aliases, - 'app_root_dirs' => self::$app_root_dirs, - 'cli_detection' => self::$cli_detection, - 'display_called_from' => self::$display_called_from, - 'enabled_mode' => self::$enabled_mode, - 'expanded' => self::$expanded, - 'file_link_format' => self::$file_link_format, - 'max_depth' => self::$max_depth, - 'mode_default' => self::$mode_default, - 'mode_default_cli' => self::$mode_default_cli, - 'plugins' => self::$plugins, - 'renderers' => self::$renderers, - 'return' => self::$return, - ); + return [ + 'aliases' => static::$aliases, + 'app_root_dirs' => static::$app_root_dirs, + 'cli_detection' => static::$cli_detection, + 'depth_limit' => static::$depth_limit, + 'display_called_from' => static::$display_called_from, + 'enabled_mode' => static::$enabled_mode, + 'expanded' => static::$expanded, + 'file_link_format' => static::$file_link_format, + 'mode_default' => static::$mode_default, + 'mode_default_cli' => static::$mode_default_cli, + 'plugins' => static::$plugins, + 'renderers' => static::$renderers, + 'return' => static::$return, + ]; } /** @@ -325,7 +327,7 @@ public static function createFromStatics(array $statics) if (isset($statics['enabled_mode'])) { $mode = $statics['enabled_mode']; - if (true === $statics['enabled_mode'] && isset($statics['mode_default'])) { + if (true === $mode && isset($statics['mode_default'])) { $mode = $statics['mode_default']; if (PHP_SAPI === 'cli' && !empty($statics['cli_detection']) && isset($statics['mode_default_cli'])) { @@ -334,7 +336,7 @@ public static function createFromStatics(array $statics) } } - if (!$mode) { + if (false === $mode) { return null; } @@ -345,7 +347,8 @@ public static function createFromStatics(array $statics) $renderer = new $statics['renderers'][$mode](); } - return new self(new Parser(), $renderer); + /** @psalm-suppress UnsafeInstantiation */ + return new static(new Parser(), $renderer); } /** @@ -354,11 +357,11 @@ public static function createFromStatics(array $statics) * @param array $params Parameters as returned from getCallInfo * @param int $argc Number of arguments the helper was called with * - * @return BasicObject[] Base objects for the arguments + * @return Value[] Base objects for the arguments */ public static function getBasesFromParamInfo(array $params, $argc) { - static $blacklist = array( + static $blacklist = [ 'null', 'true', 'false', @@ -372,10 +375,10 @@ public static function getBasesFromParamInfo(array $params, $argc) 'b"..."', "'...'", "b'...'", - ); + ]; $params = \array_values($params); - $bases = array(); + $bases = []; for ($i = 0; $i < $argc; ++$i) { if (isset($params[$i])) { @@ -402,7 +405,7 @@ public static function getBasesFromParamInfo(array $params, $argc) $access_path = '$'.$i; } - $bases[] = BasicObject::blank($name, $access_path); + $bases[] = Value::blank($name, $access_path); } return $bases; @@ -424,23 +427,21 @@ public static function getCallInfo(array $aliases, array $trace, $argc) $found = false; $callee = null; $caller = null; - $miniTrace = array(); + $miniTrace = []; foreach ($trace as $index => $frame) { if (Utils::traceFrameIsListed($frame, $aliases)) { $found = true; - $miniTrace = array(); + $miniTrace = []; } - if (!Utils::traceFrameIsListed($frame, array('spl_autoload_call'))) { + if (!Utils::traceFrameIsListed($frame, ['spl_autoload_call'])) { $miniTrace[] = $frame; } } if ($found) { $callee = \reset($miniTrace) ?: null; - - /** @var null|array Psalm bug workaround */ $caller = \next($miniTrace) ?: null; } @@ -455,15 +456,15 @@ public static function getCallInfo(array $aliases, array $trace, $argc) $miniTrace = \array_values($miniTrace); - $call = self::getSingleCall($callee ?: array(), $argc); + $call = static::getSingleCall($callee ?: [], $argc); - $ret = array( + $ret = [ 'params' => null, - 'modifiers' => array(), + 'modifiers' => [], 'callee' => $callee, 'caller' => $caller, 'trace' => $miniTrace, - ); + ]; if ($call) { $ret['params'] = $call['parameters']; @@ -482,23 +483,21 @@ public static function getCallInfo(array $aliases, array $trace, $argc) */ public static function trace() { - if (!self::$enabled_mode) { + if (false === static::$enabled_mode) { return 0; } - Utils::normalizeAliases(self::$aliases); - - $args = \func_get_args(); + Utils::normalizeAliases(static::$aliases); - $call_info = self::getCallInfo(self::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); + $call_info = static::getCallInfo(static::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \func_num_args()); - $statics = self::getStatics(); + $statics = static::getStatics(); if (\in_array('~', $call_info['modifiers'], true)) { - $statics['enabled_mode'] = self::MODE_TEXT; + $statics['enabled_mode'] = static::MODE_TEXT; } - $kintstance = self::createFromStatics($statics); + $kintstance = static::createFromStatics($statics); if (!$kintstance) { // Should never happen return 0; // @codeCoverageIgnore @@ -513,23 +512,25 @@ public static function trace() $kintstance->setStatesFromStatics($statics); $kintstance->setStatesFromCallInfo($call_info); - $trimmed_trace = array(); - $trace = \debug_backtrace(true); + $trimmed_trace = []; + $trace = \debug_backtrace(); foreach ($trace as $frame) { - if (Utils::traceFrameIsListed($frame, self::$aliases)) { - $trimmed_trace = array(); + if (Utils::traceFrameIsListed($frame, static::$aliases)) { + $trimmed_trace = []; } $trimmed_trace[] = $frame; } + \array_shift($trimmed_trace); + $output = $kintstance->dumpAll( - array($trimmed_trace), - array(BasicObject::blank('Kint\\Kint::trace()', 'debug_backtrace(true)')) + [$trimmed_trace], + [Value::blank('Kint\\Kint::trace()', 'debug_backtrace()')] ); - if (self::$return || \in_array('@', $call_info['modifiers'], true)) { + if (static::$return || \in_array('@', $call_info['modifiers'], true)) { return $output; } @@ -545,29 +546,29 @@ public static function trace() /** * Dumps some data. * - * Functionally equivalent to Kint::dump(1) or Kint::dump(debug_backtrace(true)) + * Functionally equivalent to Kint::dump(1) or Kint::dump(debug_backtrace()) * * @return int|string */ public static function dump() { - if (!self::$enabled_mode) { + if (false === static::$enabled_mode) { return 0; } - Utils::normalizeAliases(self::$aliases); + Utils::normalizeAliases(static::$aliases); $args = \func_get_args(); - $call_info = self::getCallInfo(self::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); + $call_info = static::getCallInfo(static::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); - $statics = self::getStatics(); + $statics = static::getStatics(); if (\in_array('~', $call_info['modifiers'], true)) { - $statics['enabled_mode'] = self::MODE_TEXT; + $statics['enabled_mode'] = static::MODE_TEXT; } - $kintstance = self::createFromStatics($statics); + $kintstance = static::createFromStatics($statics); if (!$kintstance) { // Should never happen return 0; // @codeCoverageIgnore @@ -582,40 +583,13 @@ public static function dump() $kintstance->setStatesFromStatics($statics); $kintstance->setStatesFromCallInfo($call_info); - // If the call is Kint::dump(1) then dump a backtrace instead - if ($args === array(1) && (!isset($call_info['params'][0]['name']) || '1' === $call_info['params'][0]['name'])) { - $args = \debug_backtrace(true); - $trace = array(); - - foreach ($args as $index => $frame) { - if (Utils::traceFrameIsListed($frame, self::$aliases)) { - $trace = array(); - } - - $trace[] = $frame; - } - - if (isset($call_info['callee']['function'])) { - $tracename = $call_info['callee']['function'].'(1)'; - if (isset($call_info['callee']['class'], $call_info['callee']['type'])) { - $tracename = $call_info['callee']['class'].$call_info['callee']['type'].$tracename; - } - } else { - $tracename = 'Kint\\Kint::dump(1)'; - } - - $tracebase = BasicObject::blank($tracename, 'debug_backtrace(true)'); - - $output = $kintstance->dumpAll(array($trace), array($tracebase)); - } else { - $bases = self::getBasesFromParamInfo( - isset($call_info['params']) ? $call_info['params'] : array(), - \count($args) - ); - $output = $kintstance->dumpAll($args, $bases); - } + $bases = static::getBasesFromParamInfo( + isset($call_info['params']) ? $call_info['params'] : [], + \count($args) + ); + $output = $kintstance->dumpAll($args, $bases); - if (self::$return || \in_array('@', $call_info['modifiers'], true)) { + if (static::$return || \in_array('@', $call_info['modifiers'], true)) { return $output; } @@ -643,7 +617,7 @@ public static function shortenPath($file) $longest_match = 0; $match = '/'; - foreach (self::$app_root_dirs as $path => $alias) { + foreach (static::$app_root_dirs as $path => $alias) { if (empty($path)) { continue; } @@ -657,7 +631,7 @@ public static function shortenPath($file) } if ($longest_match) { - $file = \array_merge(array($match), \array_slice($file, $longest_match)); + $file = \array_merge([$match], \array_slice($file, $longest_match)); return \implode('/', $file); } @@ -676,7 +650,7 @@ public static function shortenPath($file) public static function getIdeLink($file, $line) { - return \str_replace(array('%f', '%l'), array($file, $line), self::$file_link_format); + return \str_replace(['%f', '%l'], [$file, $line], static::$file_link_format); } /** @@ -696,7 +670,7 @@ protected static function getSingleCall(array $frame, $argc) if (empty($frame['class'])) { $callfunc = $frame['function']; } else { - $callfunc = array($frame['class'], $frame['function']); + $callfunc = [$frame['class'], $frame['function']]; } $calls = CallFinder::getFunctionCalls( @@ -711,32 +685,30 @@ protected static function getSingleCall(array $frame, $argc) $is_unpack = false; // Handle argument unpacking as a last resort - if (KINT_PHP56) { - foreach ($call['parameters'] as $i => &$param) { - if (0 === \strpos($param['name'], '...')) { - if ($i < $argc && $i === \count($call['parameters']) - 1) { - for ($j = 1; $j + $i < $argc; ++$j) { - $call['parameters'][] = array( - 'name' => 'array_values('.\substr($param['name'], 3).')['.$j.']', - 'path' => 'array_values('.\substr($param['path'], 3).')['.$j.']', - 'expression' => false, - ); - } - - $param['name'] = 'reset('.\substr($param['name'], 3).')'; - $param['path'] = 'reset('.\substr($param['path'], 3).')'; - $param['expression'] = false; - } else { - $call['parameters'] = \array_slice($call['parameters'], 0, $i); + foreach ($call['parameters'] as $i => &$param) { + if (0 === \strpos($param['name'], '...')) { + if ($i < $argc && $i === \count($call['parameters']) - 1) { + for ($j = 1; $j + $i < $argc; ++$j) { + $call['parameters'][] = [ + 'name' => 'array_values('.\substr($param['name'], 3).')['.$j.']', + 'path' => 'array_values('.\substr($param['path'], 3).')['.$j.']', + 'expression' => false, + ]; } - $is_unpack = true; - break; + $param['name'] = 'reset('.\substr($param['name'], 3).')'; + $param['path'] = 'reset('.\substr($param['path'], 3).')'; + $param['expression'] = false; + } else { + $call['parameters'] = \array_slice($call['parameters'], 0, $i); } - if ($i >= $argc) { - continue 2; - } + $is_unpack = true; + break; + } + + if ($i >= $argc) { + continue 2; } } diff --git a/system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php b/system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php new file mode 100644 index 000000000000..4fa94c63c3b9 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php @@ -0,0 +1,142 @@ += self::$trigger) { + throw new InvalidArgumentException('ArrayLimitPlugin::$limit can not be lower than ArrayLimitPlugin::$trigger'); + } + + $depth = $this->parser->getDepthLimit(); + + if (!$depth) { + return; + } + + if ($o->depth >= $depth - 1) { + return; + } + + if (\count($var) < self::$trigger) { + return; + } + + if (self::$numeric_only && Utils::isAssoc($var)) { + return; + } + + $base = clone $o; + $base->depth = $depth - 1; + $obj = $this->parser->parse($var, $base); + + if (!$obj instanceof Value || 'array' != $obj->type) { + return; // @codeCoverageIgnore + } + + $obj->depth = $o->depth; + $i = 0; + + foreach ($obj->value->contents as $child) { + // We only bother setting the correct depth for the first child, + // any deeper children should be cancelled by the depth limit + $child->depth = $o->depth + 1; + $this->recalcDepthLimit($child); + } + + $var2 = \array_slice($var, 0, self::$limit, true); + $base = clone $o; + $slice = $this->parser->parse($var2, $base); + + \array_splice($obj->value->contents, 0, self::$limit, $slice->value->contents); + + $o = $obj; + + $this->parser->haltParse(); + } + + protected function recalcDepthLimit(Value $o) + { + $hintkey = \array_search('depth_limit', $o->hints, true); + if (false !== $hintkey) { + $o->hints[$hintkey] = 'array_limit'; + } + + $reps = $o->getRepresentations(); + if ($o->value) { + $reps[] = $o->value; + } + + foreach ($reps as $rep) { + if ($rep->contents instanceof Value) { + $this->recalcDepthLimit($rep->contents); + } elseif (\is_array($rep->contents)) { + foreach ($rep->contents as $child) { + if ($child instanceof Value) { + $this->recalcDepthLimit($child); + } + } + } + } + } +} diff --git a/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php b/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php index 286d255b16b9..f32b4fada23a 100644 --- a/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php +++ b/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php @@ -26,13 +26,13 @@ namespace Kint\Parser; use ArrayObject; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class ArrayObjectPlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_BEGIN; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof ArrayObject) { return; diff --git a/system/ThirdParty/Kint/Parser/Base64Plugin.php b/system/ThirdParty/Kint/Parser/Base64Plugin.php index 3d7d6bc29011..5208d7ddef4a 100644 --- a/system/ThirdParty/Kint/Parser/Base64Plugin.php +++ b/system/ThirdParty/Kint/Parser/Base64Plugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class Base64Plugin extends Plugin { @@ -46,7 +46,7 @@ class Base64Plugin extends Plugin public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -54,7 +54,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\strlen($var) < self::$min_length_hard || \strlen($var) % 4) { return; @@ -68,14 +68,13 @@ public function parse(&$var, BasicObject &$o, $trigger) return; } - /** @var false|string */ $data = \base64_decode($var, true); if (false === $data) { return; } - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = 'base64_decode('.$o->name.')'; diff --git a/system/ThirdParty/Kint/Parser/BinaryPlugin.php b/system/ThirdParty/Kint/Parser/BinaryPlugin.php index 327c297cd560..9a6b117ba50e 100644 --- a/system/ThirdParty/Kint/Parser/BinaryPlugin.php +++ b/system/ThirdParty/Kint/Parser/BinaryPlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; +use Kint\Zval\BlobValue; +use Kint\Zval\Value; class BinaryPlugin extends Plugin { public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -40,9 +40,9 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - if (!$o instanceof BlobObject || !\in_array($o->encoding, array('ASCII', 'UTF-8'), true)) { + if (!$o instanceof BlobValue || !\in_array($o->encoding, ['ASCII', 'UTF-8'], true)) { $o->value->hints[] = 'binary'; } } diff --git a/system/ThirdParty/Kint/Parser/BlacklistPlugin.php b/system/ThirdParty/Kint/Parser/BlacklistPlugin.php index b37e45ff6fbf..9c472d43e798 100644 --- a/system/ThirdParty/Kint/Parser/BlacklistPlugin.php +++ b/system/ThirdParty/Kint/Parser/BlacklistPlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; +use Kint\Zval\InstanceValue; +use Kint\Zval\Value; class BlacklistPlugin extends Plugin { @@ -35,32 +35,18 @@ class BlacklistPlugin extends Plugin * * @var array */ - public static $blacklist = array(); + public static $blacklist = []; /** * List of classes and interfaces to blacklist except when dumped directly. * * @var array */ - public static $shallow_blacklist = array(); - - /** - * Maximum size of arrays before blacklisting. - * - * @var int - */ - public static $array_limit = 10000; - - /** - * Maximum size of arrays before blacklisting except when dumped directly. - * - * @var int - */ - public static $shallow_array_limit = 1000; + public static $shallow_blacklist = ['Psr\\Container\\ContainerInterface']; public function getTypes() { - return array('object', 'array'); + return ['object']; } public function getTriggers() @@ -68,21 +54,11 @@ public function getTriggers() return Parser::TRIGGER_BEGIN; } - public function parse(&$var, BasicObject &$o, $trigger) - { - if (\is_object($var)) { - return $this->parseObject($var, $o); - } - if (\is_array($var)) { - return $this->parseArray($var, $o); - } - } - - protected function parseObject(&$var, BasicObject &$o) + public function parse(&$var, Value &$o, $trigger) { foreach (self::$blacklist as $class) { if ($var instanceof $class) { - return $this->blacklistObject($var, $o); + return $this->blacklistValue($var, $o); } } @@ -92,17 +68,17 @@ protected function parseObject(&$var, BasicObject &$o) foreach (self::$shallow_blacklist as $class) { if ($var instanceof $class) { - return $this->blacklistObject($var, $o); + return $this->blacklistValue($var, $o); } } } - protected function blacklistObject(&$var, BasicObject &$o) + protected function blacklistValue(&$var, Value &$o) { - $object = new InstanceObject(); + $object = new InstanceValue(); $object->transplant($o); $object->classname = \get_class($var); - $object->hash = \spl_object_hash($var); + $object->spl_object_hash = \spl_object_hash($var); $object->clearRepresentations(); $object->value = null; $object->size = null; @@ -112,32 +88,4 @@ protected function blacklistObject(&$var, BasicObject &$o) $this->parser->haltParse(); } - - protected function parseArray(array &$var, BasicObject &$o) - { - if (\count($var) > self::$array_limit) { - return $this->blacklistArray($var, $o); - } - - if ($o->depth <= 0) { - return; - } - - if (\count($var) > self::$shallow_array_limit) { - return $this->blacklistArray($var, $o); - } - } - - protected function blacklistArray(array &$var, BasicObject &$o) - { - $object = new BasicObject(); - $object->transplant($o); - $object->value = null; - $object->size = \count($var); - $object->hints[] = 'blacklist'; - - $o = $object; - - $this->parser->haltParse(); - } } diff --git a/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php b/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php index e4c23716186a..152e59d9c762 100644 --- a/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php +++ b/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php @@ -25,19 +25,19 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; -use Kint\Object\MethodObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\InstanceValue; +use Kint\Zval\MethodValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionClass; class ClassMethodsPlugin extends Plugin { - private static $cache = array(); + private static $cache = []; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -45,21 +45,21 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $class = \get_class($var); // assuming class definition will not change inside one request if (!isset(self::$cache[$class])) { - $methods = array(); + $methods = []; $reflection = new ReflectionClass($class); foreach ($reflection->getMethods() as $method) { - $methods[] = new MethodObject($method); + $methods[] = new MethodValue($method); } - \usort($methods, array('Kint\\Parser\\ClassMethodsPlugin', 'sort')); + \usort($methods, ['Kint\\Parser\\ClassMethodsPlugin', 'sort']); self::$cache[$class] = $methods; } @@ -91,19 +91,19 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - private static function sort(MethodObject $a, MethodObject $b) + private static function sort(MethodValue $a, MethodValue $b) { $sort = ((int) $a->static) - ((int) $b->static); if ($sort) { return $sort; } - $sort = BasicObject::sortByAccess($a, $b); + $sort = Value::sortByAccess($a, $b); if ($sort) { return $sort; } - $sort = InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + $sort = InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class); if ($sort) { return $sort; } diff --git a/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php b/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php index 0ba58ca24874..89601af2f9f7 100644 --- a/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php +++ b/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php @@ -25,19 +25,19 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionClass; use ReflectionProperty; class ClassStaticsPlugin extends Plugin { - private static $cache = array(); + private static $cache = []; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -45,7 +45,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $class = \get_class($var); $reflection = new ReflectionClass($class); @@ -53,14 +53,14 @@ public function parse(&$var, BasicObject &$o, $trigger) // Constants // TODO: PHP 7.1 allows private consts but reflection doesn't have a way to check them yet if (!isset(self::$cache[$class])) { - $consts = array(); + $consts = []; foreach ($reflection->getConstants() as $name => $val) { - $const = BasicObject::blank($name, '\\'.$class.'::'.$name); + $const = Value::blank($name, '\\'.$class.'::'.$name); $const->const = true; $const->depth = $o->depth + 1; $const->owner_class = $class; - $const->operator = BasicObject::OPERATOR_STATIC; + $const->operator = Value::OPERATOR_STATIC; $const = $this->parser->parse($val, $const); $consts[] = $const; @@ -73,18 +73,18 @@ public function parse(&$var, BasicObject &$o, $trigger) $statics->contents = self::$cache[$class]; foreach ($reflection->getProperties(ReflectionProperty::IS_STATIC) as $static) { - $prop = new BasicObject(); + $prop = new Value(); $prop->name = '$'.$static->getName(); $prop->depth = $o->depth + 1; $prop->static = true; - $prop->operator = BasicObject::OPERATOR_STATIC; + $prop->operator = Value::OPERATOR_STATIC; $prop->owner_class = $static->getDeclaringClass()->name; - $prop->access = BasicObject::ACCESS_PUBLIC; + $prop->access = Value::ACCESS_PUBLIC; if ($static->isProtected()) { - $prop->access = BasicObject::ACCESS_PROTECTED; + $prop->access = Value::ACCESS_PROTECTED; } elseif ($static->isPrivate()) { - $prop->access = BasicObject::ACCESS_PRIVATE; + $prop->access = Value::ACCESS_PRIVATE; } if ($this->parser->childHasPath($o, $prop)) { @@ -92,31 +92,37 @@ public function parse(&$var, BasicObject &$o, $trigger) } $static->setAccessible(true); - $static = $static->getValue(); - $statics->contents[] = $this->parser->parse($static, $prop); + + if (KINT_PHP74 && !$static->isInitialized()) { + $prop->type = 'uninitialized'; + $statics->contents[] = $prop; + } else { + $static = $static->getValue(); + $statics->contents[] = $this->parser->parse($static, $prop); + } } if (empty($statics->contents)) { return; } - \usort($statics->contents, array('Kint\\Parser\\ClassStaticsPlugin', 'sort')); + \usort($statics->contents, ['Kint\\Parser\\ClassStaticsPlugin', 'sort']); $o->addRepresentation($statics); } - private static function sort(BasicObject $a, BasicObject $b) + private static function sort(Value $a, Value $b) { $sort = ((int) $a->const) - ((int) $b->const); if ($sort) { return $sort; } - $sort = BasicObject::sortByAccess($a, $b); + $sort = Value::sortByAccess($a, $b); if ($sort) { return $sort; } - return InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + return InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class); } } diff --git a/system/ThirdParty/Kint/Parser/ClosurePlugin.php b/system/ThirdParty/Kint/Parser/ClosurePlugin.php index 73e367b22b03..f4a68f5db737 100644 --- a/system/ThirdParty/Kint/Parser/ClosurePlugin.php +++ b/system/ThirdParty/Kint/Parser/ClosurePlugin.php @@ -26,17 +26,17 @@ namespace Kint\Parser; use Closure; -use Kint\Object\BasicObject; -use Kint\Object\ClosureObject; -use Kint\Object\ParameterObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\ClosureValue; +use Kint\Zval\ParameterValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionFunction; class ClosurePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -44,13 +44,13 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Closure) { return; } - $object = new ClosureObject(); + $object = new ClosureValue(); $object->transplant($o); $o = $object; $object->removeRepresentation('properties'); @@ -61,24 +61,24 @@ public function parse(&$var, BasicObject &$o, $trigger) $o->startline = $closure->getStartLine(); foreach ($closure->getParameters() as $param) { - $o->parameters[] = new ParameterObject($param); + $o->parameters[] = new ParameterValue($param); } $p = new Representation('Parameters'); $p->contents = &$o->parameters; $o->addRepresentation($p, 0); - $statics = array(); + $statics = []; - if (\method_exists($closure, 'getClosureThis') && $v = $closure->getClosureThis()) { - $statics = array('this' => $v); + if ($v = $closure->getClosureThis()) { + $statics = ['this' => $v]; } if (\count($statics = $statics + $closure->getStaticVariables())) { - $statics_parsed = array(); + $statics_parsed = []; foreach ($statics as $name => &$static) { - $obj = BasicObject::blank('$'.$name); + $obj = Value::blank('$'.$name); $obj->depth = $o->depth + 1; $statics_parsed[$name] = $this->parser->parse($static, $obj); if (null === $statics_parsed[$name]->value) { diff --git a/system/ThirdParty/Kint/Parser/ColorPlugin.php b/system/ThirdParty/Kint/Parser/ColorPlugin.php index 0d748f2c35f2..a00b338c4708 100644 --- a/system/ThirdParty/Kint/Parser/ColorPlugin.php +++ b/system/ThirdParty/Kint/Parser/ColorPlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\ColorRepresentation; +use Kint\Zval\Representation\ColorRepresentation; +use Kint\Zval\Value; class ColorPlugin extends Plugin { public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\strlen($var) > 32) { return; diff --git a/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php b/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php index ec08d311ffef..53329820f787 100644 --- a/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php +++ b/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php @@ -28,9 +28,10 @@ use DOMNamedNodeMap; use DOMNode; use DOMNodeList; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\BlobValue; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; /** * The DOMDocument parser plugin is particularly useful as it is both the only @@ -63,14 +64,14 @@ class DOMDocumentPlugin extends Plugin * * @var array */ - public static $blacklist = array( + public static $blacklist = [ 'parentNode' => 'DOMNode', 'firstChild' => 'DOMNode', 'lastChild' => 'DOMNode', 'previousSibling' => 'DOMNode', 'nextSibling' => 'DOMNode', 'ownerDocument' => 'DOMDocument', - ); + ]; /** * Show all properties and methods. @@ -81,7 +82,7 @@ class DOMDocumentPlugin extends Plugin public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -89,9 +90,9 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - if (!$o instanceof InstanceObject) { + if (!$o instanceof InstanceValue) { return; } @@ -104,10 +105,10 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - protected function parseList(&$var, InstanceObject &$o, $trigger) + protected function parseList(&$var, InstanceValue &$o, $trigger) { // Recursion should never happen, should always be stopped at the parent - // DOMNode. Depth limit on the other hand we're going to skip since + // DOMNode. Depth limit on the other hand we're going to skip since // that would show an empty iterator and rather useless. Let the depth // limit hit the children (DOMNodeList only has DOMNode as children) if ($trigger & Parser::TRIGGER_RECURSION) { @@ -125,36 +126,42 @@ protected function parseList(&$var, InstanceObject &$o, $trigger) // Depth limit // Make empty iterator representation since we need it in DOMNode to point out depth limits if ($this->parser->getDepthLimit() && $o->depth + 1 >= $this->parser->getDepthLimit()) { - $b = new BasicObject(); + $b = new Value(); $b->name = $o->classname.' Iterator Contents'; $b->access_path = 'iterator_to_array('.$o->access_path.')'; $b->depth = $o->depth + 1; $b->hints[] = 'depth_limit'; $r = new Representation('Iterator'); - $r->contents = array($b); + $r->contents = [$b]; $o->replaceRepresentation($r, 0); return; } - $data = \iterator_to_array($var); - $r = new Representation('Iterator'); $o->replaceRepresentation($r, 0); - foreach ($data as $key => $item) { - $base_obj = new BasicObject(); + foreach ($var as $key => $item) { + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = $item->nodeName; if ($o->access_path) { if ($var instanceof DOMNamedNodeMap) { - $base_obj->access_path = $o->access_path.'->getNamedItem('.\var_export($key, true).')'; + // We can't use getNamedItem() for attributes without a + // namespace because it will pick the first matching + // attribute of *any* namespace. + // + // Contrary to the PHP docs, getNamedItemNS takes null + // as a namespace argument for an unnamespaced item. + $base_obj->access_path = $o->access_path.'->getNamedItemNS('; + $base_obj->access_path .= \var_export($item->namespaceURI, true); + $base_obj->access_path .= ', '; + $base_obj->access_path .= \var_export($item->name, true); + $base_obj->access_path .= ')'; } elseif ($var instanceof DOMNodeList) { $base_obj->access_path = $o->access_path.'->item('.\var_export($key, true).')'; - } else { - $base_obj->access_path = 'iterator_to_array('.$o->access_path.')'; } } @@ -162,19 +169,19 @@ protected function parseList(&$var, InstanceObject &$o, $trigger) } } - protected function parseNode(&$var, InstanceObject &$o) + protected function parseNode(&$var, InstanceValue &$o) { // Fill the properties // They can't be enumerated through reflection or casting, // so we have to trust the docs and try them one at a time - $known_properties = array( + $known_properties = [ 'nodeValue', 'childNodes', 'attributes', - ); + ]; if (self::$verbose) { - $known_properties = array( + $known_properties = [ 'nodeName', 'nodeValue', 'nodeType', @@ -191,11 +198,11 @@ protected function parseNode(&$var, InstanceObject &$o) 'localName', 'baseURI', 'textContent', - ); + ]; } - $childNodes = array(); - $attributes = array(); + $childNodes = null; + $attributes = null; $rep = $o->value; @@ -217,7 +224,9 @@ protected function parseNode(&$var, InstanceObject &$o) // Attributes and comments and text nodes don't // need children or attributes of their own - if (\in_array($o->classname, array('DOMAttr', 'DOMText', 'DOMComment'), true)) { + if (\in_array($o->classname, ['DOMAttr', 'DOMText', 'DOMComment'], true)) { + $o = self::textualNodeToString($o); + return; } @@ -225,7 +234,7 @@ protected function parseNode(&$var, InstanceObject &$o) if ($attributes) { $a = new Representation('Attributes'); foreach ($attributes->contents as $attribute) { - $a->contents[] = self::textualNodeToString($attribute); + $a->contents[] = $attribute; } $o->addRepresentation($a, 0); } @@ -235,21 +244,16 @@ protected function parseNode(&$var, InstanceObject &$o) $c = new Representation('Children'); if (1 === \count($childNodes->contents) && ($node = \reset($childNodes->contents)) && \in_array('depth_limit', $node->hints, true)) { - $n = new InstanceObject(); + $n = new InstanceValue(); $n->transplant($node); $n->name = 'childNodes'; $n->classname = 'DOMNodeList'; - $c->contents = array($n); + $c->contents = [$n]; } else { - foreach ($childNodes->contents as $index => $node) { - // Shortcircuit text nodes to plain strings - if ('DOMText' === $node->classname || 'DOMComment' === $node->classname) { - $node = self::textualNodeToString($node); - - // And remove them if they're empty - if (\ctype_space($node->value->contents) || '' === $node->value->contents) { - continue; - } + foreach ($childNodes->contents as $node) { + // Remove text nodes if theyre empty + if ($node instanceof BlobValue && '#text' === $node->name && (\ctype_space($node->value->contents) || '' === $node->value->contents)) { + continue; } $c->contents[] = $node; @@ -259,8 +263,8 @@ protected function parseNode(&$var, InstanceObject &$o) $o->addRepresentation($c, 0); } - if (isset($c) && \count($c->contents)) { - $o->size = \count($c->contents); + if ($childNodes) { + $o->size = \count($childNodes->contents); } if (!$o->size) { @@ -268,15 +272,15 @@ protected function parseNode(&$var, InstanceObject &$o) } } - protected function parseProperty(InstanceObject $o, $prop, &$var) + protected function parseProperty(InstanceValue $o, $prop, &$var) { // Duplicating (And slightly optimizing) the Parser::parseObject() code here - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->owner_class = $o->classname; $base_obj->name = $prop; - $base_obj->operator = BasicObject::OPERATOR_OBJECT; - $base_obj->access = BasicObject::ACCESS_PUBLIC; + $base_obj->operator = Value::OPERATOR_OBJECT; + $base_obj->access = Value::ACCESS_PUBLIC; if (null !== $o->access_path) { $base_obj->access_path = $o->access_path; @@ -291,14 +295,19 @@ protected function parseProperty(InstanceObject $o, $prop, &$var) if (!isset($var->{$prop})) { $base_obj->type = 'null'; } elseif (isset(self::$blacklist[$prop])) { - $b = new InstanceObject(); + $b = new InstanceValue(); $b->transplant($base_obj); $base_obj = $b; $base_obj->hints[] = 'blacklist'; $base_obj->classname = self::$blacklist[$prop]; } elseif ('attributes' === $prop) { - $base_obj = $this->parser->parseDeep($var->{$prop}, $base_obj); + // Attributes are strings. If we're too deep set the + // depth limit to enable parsing them, but no deeper. + if ($this->parser->getDepthLimit() && $this->parser->getDepthLimit() - 2 < $base_obj->depth) { + $base_obj->depth = $this->parser->getDepthLimit() - 2; + } + $base_obj = $this->parser->parse($var->{$prop}, $base_obj); } else { $base_obj = $this->parser->parse($var->{$prop}, $base_obj); } @@ -306,13 +315,13 @@ protected function parseProperty(InstanceObject $o, $prop, &$var) return $base_obj; } - protected static function textualNodeToString(InstanceObject $o) + protected static function textualNodeToString(InstanceValue $o) { if (empty($o->value) || empty($o->value->contents) || empty($o->classname)) { return; } - if (!\in_array($o->classname, array('DOMText', 'DOMAttr', 'DOMComment'), true)) { + if (!\in_array($o->classname, ['DOMText', 'DOMAttr', 'DOMComment'], true)) { return; } diff --git a/system/ThirdParty/Kint/Parser/DateTimePlugin.php b/system/ThirdParty/Kint/Parser/DateTimePlugin.php index f2cebb643cb9..1c546fd7d2a1 100644 --- a/system/ThirdParty/Kint/Parser/DateTimePlugin.php +++ b/system/ThirdParty/Kint/Parser/DateTimePlugin.php @@ -26,14 +26,14 @@ namespace Kint\Parser; use DateTime; -use Kint\Object\BasicObject; -use Kint\Object\DateTimeObject; +use Kint\Zval\DateTimeValue; +use Kint\Zval\Value; class DateTimePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -41,13 +41,13 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof DateTime) { return; } - $object = new DateTimeObject($var); + $object = new DateTimeValue($var); $object->transplant($o); $o = $object; diff --git a/system/ThirdParty/Kint/Parser/FsPathPlugin.php b/system/ThirdParty/Kint/Parser/FsPathPlugin.php index 3a8d1e0538c2..79ed3288ca9a 100644 --- a/system/ThirdParty/Kint/Parser/FsPathPlugin.php +++ b/system/ThirdParty/Kint/Parser/FsPathPlugin.php @@ -25,17 +25,17 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\SplFileInfoRepresentation; +use Kint\Zval\Representation\SplFileInfoRepresentation; +use Kint\Zval\Value; use SplFileInfo; class FsPathPlugin extends Plugin { - public static $blacklist = array('/', '.'); + public static $blacklist = ['/', '.']; public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -43,7 +43,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\strlen($var) > 2048) { return; diff --git a/system/ThirdParty/Kint/Parser/IteratorPlugin.php b/system/ThirdParty/Kint/Parser/IteratorPlugin.php index 0487a381f5b9..8aa1c342f5ce 100644 --- a/system/ThirdParty/Kint/Parser/IteratorPlugin.php +++ b/system/ThirdParty/Kint/Parser/IteratorPlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use Traversable; class IteratorPlugin extends Plugin @@ -40,17 +40,17 @@ class IteratorPlugin extends Plugin * * @var array */ - public static $blacklist = array( + public static $blacklist = [ 'DOMNamedNodeMap', 'DOMNodeList', 'mysqli_result', 'PDOStatement', 'SplFileObject', - ); + ]; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -58,7 +58,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Traversable) { return; @@ -66,14 +66,14 @@ public function parse(&$var, BasicObject &$o, $trigger) foreach (self::$blacklist as $class) { if ($var instanceof $class) { - $b = new BasicObject(); + $b = new Value(); $b->name = $class.' Iterator Contents'; $b->access_path = 'iterator_to_array('.$o->access_path.', true)'; $b->depth = $o->depth + 1; $b->hints[] = 'blacklist'; $r = new Representation('Iterator'); - $r->contents = array($b); + $r->contents = [$b]; $o->addRepresentation($r); @@ -81,14 +81,9 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - /** @var array|false */ $data = \iterator_to_array($var); - if (false === $data) { - return; - } - - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth; if ($o->access_path) { @@ -101,7 +96,7 @@ public function parse(&$var, BasicObject &$o, $trigger) $primary = $o->getRepresentations(); $primary = \reset($primary); - if ($primary && $primary === $o->value && $primary->contents === array()) { + if ($primary && $primary === $o->value && [] === $primary->contents) { $o->addRepresentation($r, 0); } else { $o->addRepresentation($r); diff --git a/system/ThirdParty/Kint/Parser/JsonPlugin.php b/system/ThirdParty/Kint/Parser/JsonPlugin.php index 84b251955383..a105b8fd6ff1 100644 --- a/system/ThirdParty/Kint/Parser/JsonPlugin.php +++ b/system/ThirdParty/Kint/Parser/JsonPlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class JsonPlugin extends Plugin { public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!isset($var[0]) || ('{' !== $var[0] && '[' !== $var[0])) { return; @@ -54,7 +54,7 @@ public function parse(&$var, BasicObject &$o, $trigger) $json = (array) $json; - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth; if ($o->access_path) { diff --git a/system/ThirdParty/Kint/Parser/MicrotimePlugin.php b/system/ThirdParty/Kint/Parser/MicrotimePlugin.php index 5062b59ad224..782c11f84f85 100644 --- a/system/ThirdParty/Kint/Parser/MicrotimePlugin.php +++ b/system/ThirdParty/Kint/Parser/MicrotimePlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\MicrotimeRepresentation; +use Kint\Zval\Representation\MicrotimeRepresentation; +use Kint\Zval\Value; class MicrotimePlugin extends Plugin { @@ -37,7 +37,7 @@ class MicrotimePlugin extends Plugin public function getTypes() { - return array('string', 'double'); + return ['string', 'double']; } public function getTriggers() @@ -45,7 +45,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (0 !== $o->depth) { return; @@ -79,7 +79,7 @@ public function parse(&$var, BasicObject &$o, $trigger) self::$start = $time; } - self::$last = array($sec, $usec); + self::$last = [$sec, $usec]; if (null !== $lap) { $total = $time - self::$start; diff --git a/system/ThirdParty/Kint/Parser/MysqliPlugin.php b/system/ThirdParty/Kint/Parser/MysqliPlugin.php index 265299bec6ee..4c95d790a772 100644 --- a/system/ThirdParty/Kint/Parser/MysqliPlugin.php +++ b/system/ThirdParty/Kint/Parser/MysqliPlugin.php @@ -25,8 +25,10 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; use Mysqli; +use ReflectionClass; +use Throwable; /** * Adds support for Mysqli object parsing. @@ -37,21 +39,21 @@ class MysqliPlugin extends Plugin { // These 'properties' are actually globals - protected $always_readable = array( + protected $always_readable = [ 'client_version' => true, 'connect_errno' => true, 'connect_error' => true, - ); + ]; // These are readable on empty mysqli objects, but not on failed connections - protected $empty_readable = array( + protected $empty_readable = [ 'client_info' => true, 'errno' => true, 'error' => true, - ); + ]; // These are only readable on connected mysqli objects - protected $connected_readable = array( + protected $connected_readable = [ 'affected_rows' => true, 'error_list' => true, 'field_count' => true, @@ -60,16 +62,15 @@ class MysqliPlugin extends Plugin 'insert_id' => true, 'server_info' => true, 'server_version' => true, - 'stat' => true, 'sqlstate' => true, 'protocol_version' => true, 'thread_id' => true, 'warning_count' => true, - ); + ]; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -77,19 +78,24 @@ public function getTriggers() return Parser::TRIGGER_COMPLETE; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Mysqli) { return; } - $connected = false; - $empty = false; + try { + $connected = \is_string(@$var->sqlstate); + } catch (Throwable $t) { + $connected = false; + } - if (\is_string(@$var->sqlstate)) { - $connected = true; - } elseif (\is_string(@$var->client_info)) { - $empty = true; + try { + $empty = !$connected && \is_string(@$var->client_info); + } catch (Throwable $t) { // @codeCoverageIgnore + // Only possible in PHP 8.0. Before 8.0 there's no exception, + // after 8.1 there are no failed connection objects + $empty = false; // @codeCoverageIgnore } foreach ($o->value->contents as $key => $obj) { @@ -98,8 +104,9 @@ public function parse(&$var, BasicObject &$o, $trigger) continue; } } elseif (isset($this->empty_readable[$obj->name])) { - if (!$connected && !$empty) { - continue; + // No failed connections after PHP 8.1 + if (!$connected && !$empty) { // @codeCoverageIgnore + continue; // @codeCoverageIgnore } } elseif (!isset($this->always_readable[$obj->name])) { continue; @@ -109,13 +116,17 @@ public function parse(&$var, BasicObject &$o, $trigger) continue; } + // @codeCoverageIgnoreStart + // All of this is irellevant after 8.1, + // we have separate logic for that below + $param = $var->{$obj->name}; if (null === $param) { continue; } - $base = BasicObject::blank($obj->name, $obj->access_path); + $base = Value::blank($obj->name, $obj->access_path); $base->depth = $obj->depth; $base->owner_class = $obj->owner_class; @@ -124,6 +135,55 @@ public function parse(&$var, BasicObject &$o, $trigger) $base->reference = $obj->reference; $o->value->contents[$key] = $this->parser->parse($param, $base); + + // @codeCoverageIgnoreEnd + } + + // PHP81 returns an empty array when casting a Mysqli instance + if (KINT_PHP81) { + $r = new ReflectionClass(Mysqli::class); + + $basepropvalues = []; + + foreach ($r->getProperties() as $prop) { + if ($prop->isStatic()) { + continue; // @codeCoverageIgnore + } + + $pname = $prop->getName(); + $param = null; + + if (isset($this->connected_readable[$pname])) { + if ($connected) { + $param = $var->{$pname}; + } + } else { + $param = $var->{$pname}; + } + + $child = new Value(); + $child->depth = $o->depth + 1; + $child->owner_class = Mysqli::class; + $child->operator = Value::OPERATOR_OBJECT; + $child->name = $pname; + + if ($prop->isPublic()) { + $child->access = Value::ACCESS_PUBLIC; + } elseif ($prop->isProtected()) { // @codeCoverageIgnore + $child->access = Value::ACCESS_PROTECTED; // @codeCoverageIgnore + } elseif ($prop->isPrivate()) { // @codeCoverageIgnore + $child->access = Value::ACCESS_PRIVATE; // @codeCoverageIgnore + } + + // We only do base Mysqli properties so we don't need to worry about complex names + if ($this->parser->childHasPath($o, $child)) { + $child->access_path .= $o->access_path.'->'.$child->name; + } + + $basepropvalues[] = $this->parser->parse($param, $child); + } + + $o->value->contents = \array_merge($basepropvalues, $o->value->contents); } } } diff --git a/system/ThirdParty/Kint/Parser/Parser.php b/system/ThirdParty/Kint/Parser/Parser.php index b7f81c62186f..d658b092479d 100644 --- a/system/ThirdParty/Kint/Parser/Parser.php +++ b/system/ThirdParty/Kint/Parser/Parser.php @@ -27,11 +27,11 @@ use DomainException; use Exception; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; -use Kint\Object\ResourceObject; +use Kint\Zval\BlobValue; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\ResourceValue; +use Kint\Zval\Value; use ReflectionObject; use stdClass; @@ -58,25 +58,22 @@ class Parser const TRIGGER_COMPLETE = 14; protected $caller_class; - protected $depth_limit = false; + protected $depth_limit = 0; protected $marker; - protected $object_hashes = array(); + protected $object_hashes = []; protected $parse_break = false; - protected $plugins = array(); + protected $plugins = []; /** - * @param false|int $depth_limit Maximum depth to parse data + * @param int $depth_limit Maximum depth to parse data * @param null|string $caller Caller class name */ - public function __construct($depth_limit = false, $caller = null) + public function __construct($depth_limit = 0, $caller = null) { $this->marker = \uniqid("kint\0", true); + $this->depth_limit = $depth_limit; $this->caller_class = $caller; - - if ($depth_limit) { - $this->depth_limit = $depth_limit; - } } /** @@ -99,9 +96,9 @@ public function getCallerClass() /** * Set the depth limit. * - * @param false|int $depth_limit Maximum depth to parse data + * @param int $depth_limit Maximum depth to parse data */ - public function setDepthLimit($depth_limit = false) + public function setDepthLimit($depth_limit = 0) { $this->noRecurseCall(); @@ -113,37 +110,15 @@ public function getDepthLimit() return $this->depth_limit; } - /** - * Disables the depth limit and parses a variable. - * - * This should not be used unless you know what you're doing! - * - * @param mixed $var The input variable - * @param BasicObject $o The base object - * - * @return BasicObject - */ - public function parseDeep(&$var, BasicObject $o) - { - $depth_limit = $this->depth_limit; - $this->depth_limit = false; - - $out = $this->parse($var, $o); - - $this->depth_limit = $depth_limit; - - return $out; - } - /** * Parses a variable into a Kint object structure. * - * @param mixed $var The input variable - * @param BasicObject $o The base object + * @param mixed $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - public function parse(&$var, BasicObject $o) + public function parse(&$var, Value $o) { $o->type = \strtolower(\gettype($var)); @@ -165,8 +140,10 @@ public function parse(&$var, BasicObject $o) return $this->parseResource($var, $o); case 'string': return $this->parseString($var, $o); + case 'unknown type': + case 'resource (closed)': default: - return $this->parseUnknown($var, $o); + return $this->parseResourceClosed($var, $o); } } @@ -184,12 +161,12 @@ public function addPlugin(Plugin $p) foreach ($types as $type) { if (!isset($this->plugins[$type])) { - $this->plugins[$type] = array( - self::TRIGGER_BEGIN => array(), - self::TRIGGER_SUCCESS => array(), - self::TRIGGER_RECURSION => array(), - self::TRIGGER_DEPTH_LIMIT => array(), - ); + $this->plugins[$type] = [ + self::TRIGGER_BEGIN => [], + self::TRIGGER_SUCCESS => [], + self::TRIGGER_RECURSION => [], + self::TRIGGER_DEPTH_LIMIT => [], + ]; } foreach ($this->plugins[$type] as $trigger => &$pool) { @@ -204,7 +181,7 @@ public function addPlugin(Plugin $p) public function clearPlugins() { - $this->plugins = array(); + $this->plugins = []; } public function haltParse() @@ -212,18 +189,18 @@ public function haltParse() $this->parse_break = true; } - public function childHasPath(InstanceObject $parent, BasicObject $child) + public function childHasPath(InstanceValue $parent, Value $child) { if ('object' === $parent->type && (null !== $parent->access_path || $child->static || $child->const)) { - if (BasicObject::ACCESS_PUBLIC === $child->access) { + if (Value::ACCESS_PUBLIC === $child->access) { return true; } - if (BasicObject::ACCESS_PRIVATE === $child->access && $this->caller_class) { + if (Value::ACCESS_PRIVATE === $child->access && $this->caller_class) { if ($this->caller_class === $child->owner_class) { return true; } - } elseif (BasicObject::ACCESS_PROTECTED === $child->access && $this->caller_class) { + } elseif (Value::ACCESS_PROTECTED === $child->access && $this->caller_class) { if ($this->caller_class === $child->owner_class) { return true; } @@ -262,9 +239,9 @@ protected function noRecurseCall() { $bt = \debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS); - $caller_frame = array( + $caller_frame = [ 'function' => __FUNCTION__, - ); + ]; while (isset($bt[0]['object']) && $bt[0]['object'] === $this) { $caller_frame = \array_shift($bt); @@ -277,7 +254,7 @@ protected function noRecurseCall() } } - private function parseGeneric(&$var, BasicObject $o) + private function parseGeneric(&$var, Value $o) { $rep = new Representation('Contents'); $rep->contents = $var; @@ -291,19 +268,19 @@ private function parseGeneric(&$var, BasicObject $o) } /** - * Parses a string into a Kint BlobObject structure. + * Parses a string into a Kint BlobValue structure. * - * @param string $var The input variable - * @param BasicObject $o The base object + * @param string $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseString(&$var, BasicObject $o) + private function parseString(&$var, Value $o) { - $string = new BlobObject(); + $string = new BlobValue(); $string->transplant($o); - $string->encoding = BlobObject::detectEncoding($var); - $string->size = BlobObject::strlen($var, $string->encoding); + $string->encoding = BlobValue::detectEncoding($var); + $string->size = \strlen($var); $rep = new Representation('Contents'); $rep->contents = $var; @@ -320,14 +297,14 @@ private function parseString(&$var, BasicObject $o) /** * Parses an array into a Kint object structure. * - * @param array $var The input variable - * @param BasicObject $o The base object + * @param array $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseArray(array &$var, BasicObject $o) + private function parseArray(array &$var, Value $o) { - $array = new BasicObject(); + $array = new Value(); $array->transplant($o); $array->size = \count($var); @@ -379,11 +356,11 @@ private function parseArray(array &$var, BasicObject $o) continue; } - $child = new BasicObject(); + $child = new Value(); $child->name = $key; $child->depth = $array->depth + 1; - $child->access = BasicObject::ACCESS_NONE; - $child->operator = BasicObject::OPERATOR_ARRAY; + $child->access = Value::ACCESS_NONE; + $child->operator = Value::OPERATOR_ARRAY; if (null !== $array->access_path) { if (\is_string($key) && (string) (int) $key === $key) { @@ -411,22 +388,22 @@ private function parseArray(array &$var, BasicObject $o) } /** - * Parses an object into a Kint InstanceObject structure. + * Parses an object into a Kint InstanceValue structure. * - * @param object $var The input variable - * @param BasicObject $o The base object + * @param object $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseObject(&$var, BasicObject $o) + private function parseObject(&$var, Value $o) { $hash = \spl_object_hash($var); $values = (array) $var; - $object = new InstanceObject(); + $object = new InstanceValue(); $object->transplant($o); $object->classname = \get_class($var); - $object->hash = $hash; + $object->spl_object_hash = $hash; $object->size = \count($values); if (isset($this->object_hashes[$hash])) { @@ -457,6 +434,48 @@ private function parseObject(&$var, BasicObject $o) $rep = new Representation('Properties'); + if (KINT_PHP74) { + $rprops = $reflector->getProperties(); + + foreach ($rprops as $rprop) { + if ($rprop->isStatic()) { + continue; + } + + $rprop->setAccessible(true); + if ($rprop->isInitialized($var)) { + continue; + } + + $undefined = null; + + $child = new Value(); + $child->type = 'undefined'; + $child->depth = $object->depth + 1; + $child->owner_class = $rprop->getDeclaringClass()->getName(); + $child->operator = Value::OPERATOR_OBJECT; + $child->name = $rprop->getName(); + + if ($rprop->isPublic()) { + $child->access = Value::ACCESS_PUBLIC; + } elseif ($rprop->isProtected()) { + $child->access = Value::ACCESS_PROTECTED; + } elseif ($rprop->isPrivate()) { + $child->access = Value::ACCESS_PRIVATE; + } + + // Can't dynamically add undefined properties, so no need to use var_export + if ($this->childHasPath($object, $child)) { + $child->access_path .= $object->access_path.'->'.$child->name; + } + + if ($this->applyPlugins($undefined, $child, self::TRIGGER_BEGIN)) { + $this->applyPlugins($undefined, $child, self::TRIGGER_SUCCESS); + } + $rep->contents[] = $child; + } + } + $copy = \array_values($values); $refmarker = new stdClass(); $i = 0; @@ -470,20 +489,20 @@ private function parseObject(&$var, BasicObject $o) // public properties show in the form "$property_name"; // http://www.php.net/manual/en/language.types.array.php#language.types.array.casting - $child = new BasicObject(); + $child = new Value(); $child->depth = $object->depth + 1; $child->owner_class = $object->classname; - $child->operator = BasicObject::OPERATOR_OBJECT; - $child->access = BasicObject::ACCESS_PUBLIC; + $child->operator = Value::OPERATOR_OBJECT; + $child->access = Value::ACCESS_PUBLIC; $split_key = \explode("\0", $key, 3); if (3 === \count($split_key) && '' === $split_key[0]) { $child->name = $split_key[2]; if ('*' === $split_key[1]) { - $child->access = BasicObject::ACCESS_PROTECTED; + $child->access = Value::ACCESS_PROTECTED; } else { - $child->access = BasicObject::ACCESS_PRIVATE; + $child->access = Value::ACCESS_PRIVATE; $child->owner_class = $split_key[1]; } } elseif (KINT_PHP72) { @@ -524,16 +543,16 @@ private function parseObject(&$var, BasicObject $o) } /** - * Parses a resource into a Kint ResourceObject structure. + * Parses a resource into a Kint ResourceValue structure. * - * @param resource $var The input variable - * @param BasicObject $o The base object + * @param resource $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseResource(&$var, BasicObject $o) + private function parseResource(&$var, Value $o) { - $resource = new ResourceObject(); + $resource = new ResourceValue(); $resource->transplant($o); $resource->resource_type = \get_resource_type($var); @@ -543,16 +562,16 @@ private function parseResource(&$var, BasicObject $o) } /** - * Parses an unknown into a Kint object structure. + * Parses a closed resource into a Kint object structure. * - * @param mixed $var The input variable - * @param BasicObject $o The base object + * @param mixed $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseUnknown(&$var, BasicObject $o) + private function parseResourceClosed(&$var, Value $o) { - $o->type = 'unknown'; + $o->type = 'resource (closed)'; $this->applyPlugins($var, $o, self::TRIGGER_SUCCESS); return $o; @@ -561,20 +580,20 @@ private function parseUnknown(&$var, BasicObject $o) /** * Applies plugins for an object type. * - * @param mixed $var variable - * @param BasicObject $o Kint object parsed so far - * @param int $trigger The trigger to check for the plugins + * @param mixed $var variable + * @param Value $o Kint object parsed so far + * @param int $trigger The trigger to check for the plugins * * @return bool Continue parsing */ - private function applyPlugins(&$var, BasicObject &$o, $trigger) + private function applyPlugins(&$var, Value &$o, $trigger) { $break_stash = $this->parse_break; /** @var bool Psalm bug workaround */ $this->parse_break = false; - $plugins = array(); + $plugins = []; if (isset($this->plugins[$o->type][$trigger])) { $plugins = $this->plugins[$o->type][$trigger]; diff --git a/system/ThirdParty/Kint/Parser/Plugin.php b/system/ThirdParty/Kint/Parser/Plugin.php index 51d5f0b1440b..981d2aa56e1b 100644 --- a/system/ThirdParty/Kint/Parser/Plugin.php +++ b/system/ThirdParty/Kint/Parser/Plugin.php @@ -25,7 +25,7 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; abstract class Plugin { @@ -43,7 +43,7 @@ public function setParser(Parser $p) */ public function getTypes() { - return array(); + return []; } public function getTriggers() @@ -51,5 +51,5 @@ public function getTriggers() return Parser::TRIGGER_NONE; } - abstract public function parse(&$variable, BasicObject &$o, $trigger); + abstract public function parse(&$var, Value &$o, $trigger); } diff --git a/system/ThirdParty/Kint/Parser/ProxyPlugin.php b/system/ThirdParty/Kint/Parser/ProxyPlugin.php index 3376d3aa9016..116f3883dbdb 100644 --- a/system/ThirdParty/Kint/Parser/ProxyPlugin.php +++ b/system/ThirdParty/Kint/Parser/ProxyPlugin.php @@ -26,7 +26,7 @@ namespace Kint\Parser; use InvalidArgumentException; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class ProxyPlugin extends Plugin { @@ -59,8 +59,8 @@ public function getTriggers() return $this->triggers; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - return \call_user_func_array($this->callback, array(&$var, &$o, $trigger, $this->parser)); + return \call_user_func_array($this->callback, [&$var, &$o, $trigger, $this->parser]); } } diff --git a/system/ThirdParty/Kint/Parser/SerializePlugin.php b/system/ThirdParty/Kint/Parser/SerializePlugin.php index c5dadb88d9de..5924483fc50e 100644 --- a/system/ThirdParty/Kint/Parser/SerializePlugin.php +++ b/system/ThirdParty/Kint/Parser/SerializePlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class SerializePlugin extends Plugin { @@ -45,11 +45,11 @@ class SerializePlugin extends Plugin * @var bool */ public static $safe_mode = true; - public static $options = array(true); + public static $options = [true]; public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -57,7 +57,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $trimmed = \rtrim($var); @@ -65,7 +65,7 @@ public function parse(&$var, BasicObject &$o, $trigger) return; } - if (!self::$safe_mode || !\in_array($trimmed[0], array('C', 'O', 'a'), true)) { + if (!self::$safe_mode || !\in_array($trimmed[0], ['C', 'O', 'a'], true)) { // Second parameter only supported on PHP 7 if (KINT_PHP70) { // Suppress warnings on unserializeable variable @@ -79,15 +79,15 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = 'unserialize('.$o->name.')'; if ($o->access_path) { $base_obj->access_path = 'unserialize('.$o->access_path; - if (!KINT_PHP70 || self::$options === array(true)) { + if (!KINT_PHP70 || self::$options === [true]) { $base_obj->access_path .= ')'; - } elseif (self::$options === array(false)) { + } elseif (self::$options === [false]) { $base_obj->access_path .= ', false)'; } else { $base_obj->access_path .= ', Serialize::$options)'; diff --git a/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php b/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php index b90c863f8873..9e44e5388ec8 100644 --- a/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php +++ b/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php @@ -25,9 +25,10 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\BlobValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\SimpleXMLElementValue; +use Kint\Zval\Value; use SimpleXMLElement; class SimpleXMLElementPlugin extends Plugin @@ -41,7 +42,7 @@ class SimpleXMLElementPlugin extends Plugin public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -49,106 +50,168 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof SimpleXMLElement) { return; } - $o->hints[] = 'simplexml_element'; - if (!self::$verbose) { $o->removeRepresentation('properties'); $o->removeRepresentation('iterator'); $o->removeRepresentation('methods'); } + // An invalid SimpleXMLElement can gum up the works with + // warnings if we call stuff children/attributes on it. + if (!$var) { + $o->size = null; + + return; + } + + $x = new SimpleXMLElementValue(); + $x->transplant($o); + + $namespaces = \array_merge([null], $var->getDocNamespaces()); + // Attributes $a = new Representation('Attributes'); - $base_obj = new BasicObject(); - $base_obj->depth = $o->depth; + $base_obj = new Value(); + $base_obj->depth = $x->depth; - if ($o->access_path) { - $base_obj->access_path = '(string) '.$o->access_path; + if ($x->access_path) { + $base_obj->access_path = '(string) '.$x->access_path; } - if ($attribs = $var->attributes()) { - $attribs = \iterator_to_array($attribs); - $attribs = \array_map('strval', $attribs); - } else { - $attribs = array(); + // Attributes are strings. If we're too deep set the + // depth limit to enable parsing them, but no deeper. + if ($this->parser->getDepthLimit() && $this->parser->getDepthLimit() - 2 < $base_obj->depth) { + $base_obj->depth = $this->parser->getDepthLimit() - 2; } - // XML attributes are by definition strings and don't have children, - // so up the depth limit in case we're just below the limit since - // there won't be any recursive stuff anyway. - $a->contents = $this->parser->parseDeep($attribs, $base_obj)->value->contents; + $attribs = []; - $o->addRepresentation($a, 0); + foreach ($namespaces as $nsAlias => $nsUrl) { + if ($nsAttribs = $var->attributes($nsUrl)) { + $cleanAttribs = []; + foreach ($nsAttribs as $name => $attrib) { + $cleanAttribs[(string) $name] = $attrib; + } - // Children - // We need to check children() separately from the values we already parsed because - // text contents won't show up in children() but they will show up in properties. - // - // Why do we still need to check for attributes if we already have an attributes() - // method? Hell if I know! - $children = $var->children(); - - if ($o->value) { - $c = new Representation('Children'); - - foreach ($o->value->contents as $value) { - if ('@attributes' === $value->name) { - continue; + if (null === $nsUrl) { + $obj = clone $base_obj; + if ($obj->access_path) { + $obj->access_path .= '->attributes()'; + } + + $a->contents = $this->parser->parse($cleanAttribs, $obj)->value->contents; + } else { + $obj = clone $base_obj; + if ($obj->access_path) { + $obj->access_path .= '->attributes('.\var_export($nsAlias, true).', true)'; + } + + $cleanAttribs = $this->parser->parse($cleanAttribs, $obj)->value->contents; + + foreach ($cleanAttribs as $attribute) { + $attribute->name = $nsAlias.':'.$attribute->name; + $a->contents[] = $attribute; + } } + } + } + + $x->addRepresentation($a, 0); - if (isset($children->{$value->name})) { - $i = 0; + // Children + $c = new Representation('Children'); + + foreach ($namespaces as $nsAlias => $nsUrl) { + // This is doubling items because of the root namespace + // and the implicit namespace on its children. + $thisNs = $var->getNamespaces(); + if (isset($thisNs['']) && $thisNs[''] === $nsUrl) { + continue; + } - while (isset($children->{$value->name}[$i])) { - $base_obj = new BasicObject(); - $base_obj->depth = $o->depth + 1; - $base_obj->name = $value->name; - if ($value->access_path) { - $base_obj->access_path = $value->access_path.'['.$i.']'; + if ($nsChildren = $var->children($nsUrl)) { + $nsap = []; + foreach ($nsChildren as $name => $child) { + $obj = new Value(); + $obj->depth = $x->depth + 1; + $obj->name = (string) $name; + if ($x->access_path) { + if (null === $nsUrl) { + $obj->access_path = $x->access_path.'->children()->'; + } else { + $obj->access_path = $x->access_path.'->children('.\var_export($nsAlias, true).', true)->'; } - $value = $this->parser->parse($children->{$value->name}[$i], $base_obj); + if (\preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]+$/', (string) $name)) { + $obj->access_path .= (string) $name; + } else { + $obj->access_path .= '{'.\var_export((string) $name, true).'}'; + } - if ($value->access_path && 'string' === $value->type) { - $value->access_path = '(string) '.$value->access_path; + if (isset($nsap[$obj->access_path])) { + ++$nsap[$obj->access_path]; + $obj->access_path .= '['.$nsap[$obj->access_path].']'; + } else { + $nsap[$obj->access_path] = 0; } + } - $c->contents[] = $value; + $value = $this->parser->parse($child, $obj); - ++$i; + if ($value->access_path && 'string' === $value->type) { + $value->access_path = '(string) '.$value->access_path; } + + $c->contents[] = $value; } } + } - $o->size = \count($c->contents); + $x->size = \count($c->contents); - if (!$o->size) { - $o->size = null; + if ($x->size) { + $x->addRepresentation($c, 0); + } else { + $x->size = null; + + if (\strlen((string) $var)) { + $base_obj = new BlobValue(); + $base_obj->depth = $x->depth + 1; + $base_obj->name = $x->name; + if ($x->access_path) { + $base_obj->access_path = '(string) '.$x->access_path; + } + + $value = (string) $var; + + $s = $this->parser->parse($value, $base_obj); + $srep = $s->getRepresentation('contents'); + $svalrep = $s->value && 'contents' == $s->value->getName() ? $s : null; - if (\strlen((string) $var)) { - $base_obj = new BlobObject(); - $base_obj->depth = $o->depth + 1; - $base_obj->name = $o->name; - if ($o->access_path) { - $base_obj->access_path = '(string) '.$o->access_path; + if ($srep || $svalrep) { + $x->setIsStringValue(true); + $x->value = $srep ?: $svalrep; + + if ($srep) { + $x->replaceRepresentation($x->value, 0); } + } - $value = (string) $var; + $reps = \array_reverse($s->getRepresentations()); - $c = new Representation('Contents'); - $c->implicit_label = true; - $c->contents = array($this->parser->parseDeep($value, $base_obj)); + foreach ($reps as $rep) { + $x->addRepresentation($rep, 0); } } - - $o->addRepresentation($c, 0); } + + $o = $x; } } diff --git a/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php b/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php index 8b72193bc369..ada3e1fb8e85 100644 --- a/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php +++ b/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\SplFileInfoRepresentation; +use Kint\Zval\Representation\SplFileInfoRepresentation; +use Kint\Zval\Value; use SplFileInfo; use SplFileObject; @@ -34,7 +34,7 @@ class SplFileInfoPlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -42,7 +42,7 @@ public function getTriggers() return Parser::TRIGGER_COMPLETE; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof SplFileInfo || $var instanceof SplFileObject) { return; diff --git a/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php b/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php index 03ff301d3477..359774d3bfff 100644 --- a/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php +++ b/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; use SplObjectStorage; class SplObjectStoragePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_COMPLETE; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof SplObjectStorage || !($r = $o->getRepresentation('iterator'))) { return; diff --git a/system/ThirdParty/Kint/Parser/StreamPlugin.php b/system/ThirdParty/Kint/Parser/StreamPlugin.php index 464a3fff12c5..76608d94a6a6 100644 --- a/system/ThirdParty/Kint/Parser/StreamPlugin.php +++ b/system/ThirdParty/Kint/Parser/StreamPlugin.php @@ -25,16 +25,16 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; -use Kint\Object\ResourceObject; -use Kint\Object\StreamObject; +use Kint\Zval\Representation\Representation; +use Kint\Zval\ResourceValue; +use Kint\Zval\StreamValue; +use Kint\Zval\Value; class StreamPlugin extends Plugin { public function getTypes() { - return array('resource'); + return ['resource']; } public function getTriggers() @@ -42,20 +42,23 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - if (!$o instanceof ResourceObject || 'stream' !== $o->resource_type) { + if (!$o instanceof ResourceValue || 'stream' !== $o->resource_type) { return; } - if (!$meta = \stream_get_meta_data($var)) { + // Doublecheck that the resource is open before we get the metadata + if (!\is_resource($var)) { return; } + $meta = \stream_get_meta_data($var); + $rep = new Representation('Stream'); $rep->implicit_label = true; - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth; if ($o->access_path) { @@ -71,7 +74,7 @@ public function parse(&$var, BasicObject &$o, $trigger) $o->addRepresentation($rep, 0); $o->value = $rep; - $stream = new StreamObject($meta); + $stream = new StreamValue($meta); $stream->transplant($o); $o = $stream; } diff --git a/system/ThirdParty/Kint/Parser/TablePlugin.php b/system/ThirdParty/Kint/Parser/TablePlugin.php index 510c4ff0ef86..c6ca6e248d68 100644 --- a/system/ThirdParty/Kint/Parser/TablePlugin.php +++ b/system/ThirdParty/Kint/Parser/TablePlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class TablePlugin extends Plugin { public function getTypes() { - return array('array'); + return ['array']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (empty($o->value->contents)) { return; diff --git a/system/ThirdParty/Kint/Parser/ThrowablePlugin.php b/system/ThirdParty/Kint/Parser/ThrowablePlugin.php index 8490d1d41a1a..ea343e96ee78 100644 --- a/system/ThirdParty/Kint/Parser/ThrowablePlugin.php +++ b/system/ThirdParty/Kint/Parser/ThrowablePlugin.php @@ -26,16 +26,16 @@ namespace Kint\Parser; use Exception; -use Kint\Object\BasicObject; -use Kint\Object\Representation\SourceRepresentation; -use Kint\Object\ThrowableObject; +use Kint\Zval\Representation\SourceRepresentation; +use Kint\Zval\ThrowableValue; +use Kint\Zval\Value; use Throwable; class ThrowablePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -43,13 +43,13 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Exception && (!KINT_PHP70 || !$var instanceof Throwable)) { return; } - $throw = new ThrowableObject($var); + $throw = new ThrowableValue($var); $throw->transplant($o); $r = new SourceRepresentation($var->getFile(), $var->getLine()); $r->showfilename = true; diff --git a/system/ThirdParty/Kint/Parser/TimestampPlugin.php b/system/ThirdParty/Kint/Parser/TimestampPlugin.php index 72958d6465c0..fa8d743dea89 100644 --- a/system/ThirdParty/Kint/Parser/TimestampPlugin.php +++ b/system/ThirdParty/Kint/Parser/TimestampPlugin.php @@ -25,20 +25,20 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class TimestampPlugin extends Plugin { - public static $blacklist = array( + public static $blacklist = [ 2147483648, 2147483647, 1073741824, 1073741823, - ); + ]; public function getTypes() { - return array('string', 'integer'); + return ['string', 'integer']; } public function getTriggers() @@ -46,7 +46,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\is_string($var) && !\ctype_digit($var)) { return; @@ -56,7 +56,7 @@ public function parse(&$var, BasicObject &$o, $trigger) return; } - $len = \strlen($var); + $len = \strlen((string) $var); // Guess for anything between March 1973 and November 2286 if (9 === $len || 10 === $len) { diff --git a/system/ThirdParty/Kint/Parser/ToStringPlugin.php b/system/ThirdParty/Kint/Parser/ToStringPlugin.php index 8b7a65fe60f5..d13cb29cc93b 100644 --- a/system/ThirdParty/Kint/Parser/ToStringPlugin.php +++ b/system/ThirdParty/Kint/Parser/ToStringPlugin.php @@ -25,20 +25,20 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionClass; class ToStringPlugin extends Plugin { - public static $blacklist = array( + public static $blacklist = [ 'SimpleXMLElement', 'SplFileObject', - ); + ]; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -46,7 +46,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $reflection = new ReflectionClass($var); if (!$reflection->hasMethod('__toString')) { diff --git a/system/ThirdParty/Kint/Parser/TracePlugin.php b/system/ThirdParty/Kint/Parser/TracePlugin.php index 3554993dd2e1..ccdcadec59a8 100644 --- a/system/ThirdParty/Kint/Parser/TracePlugin.php +++ b/system/ThirdParty/Kint/Parser/TracePlugin.php @@ -25,18 +25,19 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\TraceFrameObject; -use Kint\Object\TraceObject; use Kint\Utils; +use Kint\Zval\TraceFrameValue; +use Kint\Zval\TraceValue; +use Kint\Zval\Value; class TracePlugin extends Plugin { - public static $blacklist = array('spl_autoload_call'); + public static $blacklist = ['spl_autoload_call']; + public static $path_blacklist = []; public function getTypes() { - return array('array'); + return ['array']; } public function getTriggers() @@ -44,27 +45,29 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$o->value) { return; } + /** @var array[] $trace Psalm workaround */ $trace = $this->parser->getCleanArray($var); if (\count($trace) !== \count($o->value->contents) || !Utils::isTrace($trace)) { return; } - $traceobj = new TraceObject(); + $traceobj = new TraceValue(); $traceobj->transplant($o); $rep = $traceobj->value; $old_trace = $rep->contents; Utils::normalizeAliases(self::$blacklist); + $path_blacklist = self::normalizePaths(self::$path_blacklist); - $rep->contents = array(); + $rep->contents = []; foreach ($old_trace as $frame) { $index = $frame->name; @@ -78,7 +81,16 @@ public function parse(&$var, BasicObject &$o, $trigger) continue; } - $rep->contents[$index] = new TraceFrameObject($frame, $trace[$index]); + if (isset($trace[$index]['file'])) { + $realfile = \realpath($trace[$index]['file']); + foreach ($path_blacklist as $path) { + if (0 === \strpos($realfile, $path)) { + continue 2; + } + } + } + + $rep->contents[$index] = new TraceFrameValue($frame, $trace[$index]); } \ksort($rep->contents); @@ -89,4 +101,20 @@ public function parse(&$var, BasicObject &$o, $trigger) $traceobj->size = \count($rep->contents); $o = $traceobj; } + + protected static function normalizePaths(array $paths) + { + $normalized = []; + + foreach ($paths as $path) { + $realpath = \realpath($path); + if (\is_dir($realpath)) { + $realpath .= DIRECTORY_SEPARATOR; + } + + $normalized[] = $realpath; + } + + return $normalized; + } } diff --git a/system/ThirdParty/Kint/Parser/XmlPlugin.php b/system/ThirdParty/Kint/Parser/XmlPlugin.php index 0947e9a6cb14..a4fa2b0c21c8 100644 --- a/system/ThirdParty/Kint/Parser/XmlPlugin.php +++ b/system/ThirdParty/Kint/Parser/XmlPlugin.php @@ -27,8 +27,8 @@ use DOMDocument; use Exception; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class XmlPlugin extends Plugin { @@ -45,7 +45,7 @@ class XmlPlugin extends Plugin public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -53,7 +53,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if ('access_path); + $xml = \call_user_func([\get_class($this), 'xmlTo'.self::$parse_method], $var, $o->access_path); if (empty($xml)) { return; @@ -71,7 +71,7 @@ public function parse(&$var, BasicObject &$o, $trigger) list($xml, $access_path, $name) = $xml; - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = $name; $base_obj->access_path = $access_path; @@ -96,7 +96,7 @@ protected static function xmlToSimpleXML($var, $parent_path) return; } - if (!$xml) { + if (false === $xml) { return; } @@ -108,7 +108,7 @@ protected static function xmlToSimpleXML($var, $parent_path) $name = $xml->getName(); - return array($xml, $access_path, $name); + return [$xml, $access_path, $name]; } /** @@ -135,16 +135,23 @@ protected static function xmlToDOMDocument($var, $parent_path) $xml = new DOMDocument(); $xml->loadXML($var); - $xml = $xml->firstChild; + + if ($xml->childNodes->count() > 1) { + $xml = $xml->childNodes; + $access_path = 'childNodes'; + } else { + $xml = $xml->firstChild; + $access_path = 'firstChild'; + } if (null === $parent_path) { $access_path = null; } else { - $access_path = '@\\DOMDocument::loadXML('.$parent_path.')->firstChild'; + $access_path = '(function($s){$x = new \\DomDocument(); $x->loadXML($s); return $x;})('.$parent_path.')->'.$access_path; } - $name = $xml->nodeName; + $name = isset($xml->nodeName) ? $xml->nodeName : null; - return array($xml, $access_path, $name); + return [$xml, $access_path, $name]; } } diff --git a/system/ThirdParty/Kint/Renderer/CliRenderer.php b/system/ThirdParty/Kint/Renderer/CliRenderer.php index 0d0846a411c3..f86671ff1cf3 100644 --- a/system/ThirdParty/Kint/Renderer/CliRenderer.php +++ b/system/ThirdParty/Kint/Renderer/CliRenderer.php @@ -25,7 +25,9 @@ namespace Kint\Renderer; -use Kint\Object\BasicObject; +use Exception; +use Kint\Zval\Value; +use Throwable; class CliRenderer extends TextRenderer { @@ -73,7 +75,13 @@ public function __construct() if (!self::$terminal_width) { if (!KINT_WIN && self::$detect_width) { - self::$terminal_width = \exec('tput cols'); + try { + self::$terminal_width = \exec('tput cols'); + } catch (Exception $e) { + self::$terminal_width = self::$default_width; + } catch (Throwable $t) { + self::$terminal_width = self::$default_width; + } } if (self::$terminal_width < self::$min_terminal_width) { @@ -113,7 +121,7 @@ public function colorTitle($string) return "\x1b[36m".\str_replace("\n", "\x1b[0m\n\x1b[36m", $string)."\x1b[0m"; } - public function renderTitle(BasicObject $o) + public function renderTitle(Value $o) { if ($this->windows_output) { return $this->utf8ToWindows(parent::renderTitle($o)); @@ -144,8 +152,8 @@ public function escape($string, $encoding = false) protected function utf8ToWindows($string) { return \str_replace( - array('┌', '═', '┐', '│', '└', '─', '┘'), - array("\xda", "\xdc", "\xbf", "\xb3", "\xc0", "\xc4", "\xd9"), + ['┌', '═', '┐', '│', '└', '─', '┘'], + ["\xda", "\xdc", "\xbf", "\xb3", "\xc0", "\xc4", "\xd9"], $string ); } diff --git a/system/ThirdParty/Kint/Renderer/PlainRenderer.php b/system/ThirdParty/Kint/Renderer/PlainRenderer.php index 493a7743bed4..4b8102a4750f 100644 --- a/system/ThirdParty/Kint/Renderer/PlainRenderer.php +++ b/system/ThirdParty/Kint/Renderer/PlainRenderer.php @@ -26,21 +26,21 @@ namespace Kint\Renderer; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; +use Kint\Zval\BlobValue; +use Kint\Zval\Value; class PlainRenderer extends TextRenderer { - public static $pre_render_sources = array( - 'script' => array( - array('Kint\\Renderer\\PlainRenderer', 'renderJs'), - array('Kint\\Renderer\\Text\\MicrotimePlugin', 'renderJs'), - ), - 'style' => array( - array('Kint\\Renderer\\PlainRenderer', 'renderCss'), - ), - 'raw' => array(), - ); + public static $pre_render_sources = [ + 'script' => [ + ['Kint\\Renderer\\PlainRenderer', 'renderJs'], + ['Kint\\Renderer\\Text\\MicrotimePlugin', 'renderJs'], + ], + 'style' => [ + ['Kint\\Renderer\\PlainRenderer', 'renderCss'], + ], + 'raw' => [], + ]; /** * Path to the CSS file to load by default. @@ -118,7 +118,7 @@ public function colorTitle($string) return ''.$string.''; } - public function renderTitle(BasicObject $o) + public function renderTitle(Value $o) { if (self::$disable_utf8) { return $this->utf8ToHtmlentity(parent::renderTitle($o)); @@ -193,7 +193,7 @@ public function ideLink($file, $line) public function escape($string, $encoding = false) { if (false === $encoding) { - $encoding = BlobObject::detectEncoding($string); + $encoding = BlobValue::detectEncoding($string); } $original_encoding = $encoding; @@ -206,7 +206,7 @@ public function escape($string, $encoding = false) // this call converts all non-ASCII characters into numeirc htmlentities if (\function_exists('mb_encode_numericentity') && 'ASCII' !== $original_encoding) { - $string = \mb_encode_numericentity($string, array(0x80, 0xffff, 0, 0xffff), $encoding); + $string = \mb_encode_numericentity($string, [0x80, 0xFFFF, 0, 0xFFFF], $encoding); } return $string; @@ -215,8 +215,8 @@ public function escape($string, $encoding = false) protected function utf8ToHtmlentity($string) { return \str_replace( - array('┌', '═', '┐', '│', '└', '─', '┘'), - array('┌', '═', '┐', '│', '└', '─', '┘'), + ['┌', '═', '┐', '│', '└', '─', '┘'], + ['┌', '═', '┐', '│', '└', '─', '┘'], $string ); } diff --git a/system/ThirdParty/Kint/Renderer/Renderer.php b/system/ThirdParty/Kint/Renderer/Renderer.php index cf8b0a781179..0ed7ce0895b5 100644 --- a/system/ThirdParty/Kint/Renderer/Renderer.php +++ b/system/ThirdParty/Kint/Renderer/Renderer.php @@ -25,8 +25,8 @@ namespace Kint\Renderer; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; +use Kint\Zval\InstanceValue; +use Kint\Zval\Value; abstract class Renderer { @@ -34,11 +34,11 @@ abstract class Renderer const SORT_VISIBILITY = 1; const SORT_FULL = 2; - protected $call_info = array(); - protected $statics = array(); + protected $call_info = []; + protected $statics = []; protected $show_trace = true; - abstract public function render(BasicObject $o); + abstract public function render(Value $o); abstract public function renderNothing(); @@ -49,7 +49,7 @@ public function setCallInfo(array $info) } if (!isset($info['modifiers']) || !\is_array($info['modifiers'])) { - $info['modifiers'] = array(); + $info['modifiers'] = []; } if (!isset($info['callee'])) { @@ -61,16 +61,16 @@ public function setCallInfo(array $info) } if (!isset($info['trace']) || !\is_array($info['trace'])) { - $info['trace'] = array(); + $info['trace'] = []; } - $this->call_info = array( + $this->call_info = [ 'params' => $info['params'], 'modifiers' => $info['modifiers'], 'callee' => $info['callee'], 'caller' => $info['caller'], 'trace' => $info['trace'], - ); + ]; } public function getCallInfo() @@ -109,7 +109,7 @@ public function getShowTrace() */ public function matchPlugins(array $plugins, array $hints) { - $out = array(); + $out = []; foreach ($hints as $key) { if (isset($plugins[$key])) { @@ -135,40 +135,40 @@ public function postRender() return ''; } - public static function sortPropertiesFull(BasicObject $a, BasicObject $b) + public static function sortPropertiesFull(Value $a, Value $b) { - $sort = BasicObject::sortByAccess($a, $b); + $sort = Value::sortByAccess($a, $b); if ($sort) { return $sort; } - $sort = BasicObject::sortByName($a, $b); + $sort = Value::sortByName($a, $b); if ($sort) { return $sort; } - return InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + return InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class); } /** - * Sorts an array of BasicObject. + * Sorts an array of Value. * - * @param BasicObject[] $contents Object properties to sort - * @param int $sort + * @param Value[] $contents Object properties to sort + * @param int $sort * - * @return BasicObject[] + * @return Value[] */ public static function sortProperties(array $contents, $sort) { switch ($sort) { case self::SORT_VISIBILITY: - /** @var array Containers to quickly stable sort by type */ - $containers = array( - BasicObject::ACCESS_PUBLIC => array(), - BasicObject::ACCESS_PROTECTED => array(), - BasicObject::ACCESS_PRIVATE => array(), - BasicObject::ACCESS_NONE => array(), - ); + // Containers to quickly stable sort by type + $containers = [ + Value::ACCESS_PUBLIC => [], + Value::ACCESS_PROTECTED => [], + Value::ACCESS_PRIVATE => [], + Value::ACCESS_NONE => [], + ]; foreach ($contents as $item) { $containers[$item->access][] = $item; @@ -176,7 +176,7 @@ public static function sortProperties(array $contents, $sort) return \call_user_func_array('array_merge', $containers); case self::SORT_FULL: - \usort($contents, array('Kint\\Renderer\\Renderer', 'sortPropertiesFull')); + \usort($contents, ['Kint\\Renderer\\Renderer', 'sortPropertiesFull']); // no break default: return $contents; diff --git a/system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php new file mode 100644 index 000000000000..e6ebe569b85e --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php @@ -0,0 +1,36 @@ +'.$this->renderLockedHeader($o, 'Array Limit').''; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php index 5b4d613fdce6..b12690a49969 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php @@ -25,7 +25,7 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; class BinaryPlugin extends Plugin implements TabPluginInterface { @@ -36,12 +36,17 @@ public function renderTab(Representation $r) { $out = '
    ';
     
    -        $chunks = \str_split($r->contents, self::$line_length);
    +        /** @var string[] Psalm bug workaround */
    +        $lines = \str_split($r->contents, self::$line_length);
     
    -        foreach ($chunks as $index => $chunk) {
    +        foreach ($lines as $index => $line) {
                 $out .= \sprintf('%08X', $index * self::$line_length).":\t";
    -            $out .= \implode(' ', \str_split(\str_pad(\bin2hex($chunk), 2 * self::$line_length, ' '), self::$chunk_length));
    -            $out .= "\t".\preg_replace('/[^\\x20-\\x7E]/', '.', $chunk)."\n";
    +
    +            /** @var string[] Psalm bug workaround */
    +            $chunks = \str_split(\str_pad(\bin2hex($line), 2 * self::$line_length, ' '), self::$chunk_length);
    +
    +            $out .= \implode(' ', $chunks);
    +            $out .= "\t".\preg_replace('/[^\\x20-\\x7E]/', '.', $line)."\n";
             }
     
             $out .= '
    '; diff --git a/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php index fcfedc1a00be..ed7f4ec96495 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -class BlacklistPlugin extends Plugin implements ObjectPluginInterface +class BlacklistPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { return '
    '.$this->renderLockedHeader($o, 'Blacklisted').'
    '; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php index 5834017ba550..b28b56a07ad1 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php @@ -25,30 +25,30 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\ClosureObject; -use Kint\Object\MethodObject; use Kint\Renderer\RichRenderer; +use Kint\Utils; +use Kint\Zval\ClosureValue; +use Kint\Zval\MethodValue; +use Kint\Zval\Value; -class CallablePlugin extends Plugin implements ObjectPluginInterface +class CallablePlugin extends Plugin implements ValuePluginInterface { - protected static $method_cache = array(); + protected static $method_cache = []; - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { - if ($o instanceof MethodObject) { + if ($o instanceof MethodValue) { return $this->renderMethod($o); } - if ($o instanceof ClosureObject) { + if ($o instanceof ClosureValue) { return $this->renderClosure($o); } return $this->renderCallable($o); } - protected function renderClosure(ClosureObject $o) + protected function renderClosure(ClosureValue $o) { $children = $this->renderer->renderChildren($o); @@ -63,8 +63,8 @@ protected function renderClosure(ClosureObject $o) } if (null !== ($s = $o->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } $header .= ' '.$this->renderer->escape($s); } @@ -72,7 +72,7 @@ protected function renderClosure(ClosureObject $o) return '
    '.$this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header).$children.'
    '; } - protected function renderCallable(BasicObject $o) + protected function renderCallable(Value $o) { $children = $this->renderer->renderChildren($o); @@ -87,8 +87,8 @@ protected function renderCallable(BasicObject $o) } if (null !== ($s = $o->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } $header .= ' '.$this->renderer->escape($s); } @@ -96,7 +96,7 @@ protected function renderCallable(BasicObject $o) return '
    '.$this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header).$children.'
    '; } - protected function renderMethod(MethodObject $o) + protected function renderMethod(MethodValue $o) { if (!empty(self::$method_cache[$o->owner_class][$o->name])) { $children = self::$method_cache[$o->owner_class][$o->name]['children']; @@ -154,17 +154,17 @@ protected function renderMethod(MethodObject $o) } if (null !== ($s = $o->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } $header .= ' '.$this->renderer->escape($s); } if (\strlen($o->owner_class) && \strlen($o->name)) { - self::$method_cache[$o->owner_class][$o->name] = array( + self::$method_cache[$o->owner_class][$o->name] = [ 'header' => $header, 'children' => $children, - ); + ]; } $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); diff --git a/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php index 79a9926cab7f..44813e3ef89f 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php @@ -26,16 +26,16 @@ namespace Kint\Renderer\Rich; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\ClosureObject; +use Kint\Zval\ClosureValue; +use Kint\Zval\Value; -class ClosurePlugin extends Plugin implements ObjectPluginInterface +class ClosurePlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { $children = $this->renderer->renderChildren($o); - if (!($o instanceof ClosureObject)) { + if (!($o instanceof ClosureValue)) { $header = $this->renderer->renderHeader($o); } else { $header = ''; diff --git a/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php index 241a8154f430..ebd02cb59e24 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php @@ -25,13 +25,13 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\Representation\ColorRepresentation; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\ColorRepresentation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; -class ColorPlugin extends Plugin implements TabPluginInterface, ObjectPluginInterface +class ColorPlugin extends Plugin implements TabPluginInterface, ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { $r = $o->getRepresentation('color'); @@ -92,7 +92,7 @@ public function renderTab(Representation $r) } if (!\strlen($out)) { - return false; + return; } return '
    '.$out.'
    '; diff --git a/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php index cd92b417985c..69808c7c3e1d 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -class DepthLimitPlugin extends Plugin implements ObjectPluginInterface +class DepthLimitPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { return '
    '.$this->renderLockedHeader($o, 'Depth Limit').'
    '; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php index 19c530951c4d..cb53a74fb182 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php @@ -26,25 +26,25 @@ namespace Kint\Renderer\Rich; use Kint\Kint; -use Kint\Object\Representation\DocstringRepresentation; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\DocstringRepresentation; +use Kint\Zval\Representation\Representation; class DocstringPlugin extends Plugin implements TabPluginInterface { public function renderTab(Representation $r) { if (!($r instanceof DocstringRepresentation)) { - return false; + return; } - $docstring = array(); + $docstring = []; foreach (\explode("\n", $r->contents) as $line) { $docstring[] = \trim($line); } $docstring = \implode("\n", $docstring); - $location = array(); + $location = []; if ($r->class) { $location[] = 'Inherited from '.$this->renderer->escape($r->class); diff --git a/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php index a56bb23ef53a..3d06b529252b 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php @@ -25,16 +25,16 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\MicrotimeRepresentation; -use Kint\Object\Representation\Representation; use Kint\Utils; +use Kint\Zval\Representation\MicrotimeRepresentation; +use Kint\Zval\Representation\Representation; class MicrotimePlugin extends Plugin implements TabPluginInterface { public function renderTab(Representation $r) { if (!($r instanceof MicrotimeRepresentation)) { - return false; + return; } $out = $r->getDateTime()->format('Y-m-d H:i:s.u'); diff --git a/system/ThirdParty/Kint/Renderer/Rich/Plugin.php b/system/ThirdParty/Kint/Renderer/Rich/Plugin.php index 06710bcc45c2..58e22cb276f4 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/Plugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/Plugin.php @@ -25,8 +25,8 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; use Kint\Renderer\RichRenderer; +use Kint\Zval\Value; abstract class Plugin implements PluginInterface { @@ -40,10 +40,9 @@ public function __construct(RichRenderer $r) /** * Renders a locked header. * - * @param BasicObject $o - * @param string $content + * @param string $content */ - public function renderLockedHeader(BasicObject $o, $content) + public function renderLockedHeader(Value $o, $content) { $header = '
    '; diff --git a/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php index 618d2176d917..baad2ecb57b8 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -class RecursionPlugin extends Plugin implements ObjectPluginInterface +class RecursionPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { return '
    '.$this->renderLockedHeader($o, 'Recursion').'
    '; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php index 6c18931ee7af..718cd67aace3 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php @@ -25,13 +25,13 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; use Kint\Renderer\RichRenderer; +use Kint\Utils; +use Kint\Zval\Value; -class SimpleXMLElementPlugin extends Plugin implements ObjectPluginInterface +class SimpleXMLElementPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { $children = $this->renderer->renderChildren($o); @@ -63,15 +63,11 @@ public function renderObject(BasicObject $o) $header .= '('.$this->renderer->escape($s).') '; } - if (null === $s && $c = $o->getRepresentation('contents')) { - $c = \reset($c->contents); - - if ($c && null !== ($s = $c->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; - } - $header .= $this->renderer->escape($s); + if (null !== ($s = $o->getValueShort())) { + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } + $header .= $this->renderer->escape($s); } $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); diff --git a/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php index 5443dbfd9a8e..4be024b627b2 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php @@ -25,15 +25,15 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\Representation; -use Kint\Object\Representation\SourceRepresentation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Representation\SourceRepresentation; class SourcePlugin extends Plugin implements TabPluginInterface { public function renderTab(Representation $r) { if (!($r instanceof SourceRepresentation) || empty($r->source)) { - return false; + return; } $source = $r->source; diff --git a/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php b/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php index 7cdbde72d2ad..779e13acd3a9 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php @@ -25,9 +25,12 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; interface TabPluginInterface extends PluginInterface { - public function renderTab(Representation $o); + /** + * @return null|string + */ + public function renderTab(Representation $r); } diff --git a/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php index cc3ee0f05da7..ac345a167f9d 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php @@ -25,9 +25,9 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BlobObject; -use Kint\Object\Representation\Representation; use Kint\Renderer\RichRenderer; +use Kint\Utils; +use Kint\Zval\Representation\Representation; class TablePlugin extends Plugin implements TabPluginInterface { @@ -89,8 +89,8 @@ public function renderTab(Representation $r) case 'string': if ($field->encoding) { $val = $field->value->contents; - if (RichRenderer::$strlen_max && self::$respect_str_length && BlobObject::strlen($val) > RichRenderer::$strlen_max) { - $val = \substr($val, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max && self::$respect_str_length) { + $val = Utils::truncateString($val, RichRenderer::$strlen_max); } $out .= $this->renderer->escape($val); diff --git a/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php index 6e3a2f8c5c83..f0c58e67a3cc 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php @@ -27,7 +27,7 @@ use DateTime; use DateTimeZone; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; class TimestampPlugin extends Plugin implements TabPluginInterface { diff --git a/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php index 6ca19bb67157..ea7048bcdd09 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php @@ -25,14 +25,14 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\TraceFrameObject; +use Kint\Zval\TraceFrameValue; +use Kint\Zval\Value; -class TraceFramePlugin extends Plugin implements ObjectPluginInterface +class TraceFramePlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { - if (!$o instanceof TraceFrameObject) { + if (!$o instanceof TraceFrameValue) { return; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php b/system/ThirdParty/Kint/Renderer/Rich/ValuePluginInterface.php similarity index 88% rename from system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php rename to system/ThirdParty/Kint/Renderer/Rich/ValuePluginInterface.php index f46aa2946ea3..8f750eda6bad 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php +++ b/system/ThirdParty/Kint/Renderer/Rich/ValuePluginInterface.php @@ -25,9 +25,12 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -interface ObjectPluginInterface extends PluginInterface +interface ValuePluginInterface extends PluginInterface { - public function renderObject(BasicObject $o); + /** + * @return null|string + */ + public function renderValue(Value $o); } diff --git a/system/ThirdParty/Kint/Renderer/RichRenderer.php b/system/ThirdParty/Kint/Renderer/RichRenderer.php index dcd39eec8c53..94b7f98ab71f 100644 --- a/system/ThirdParty/Kint/Renderer/RichRenderer.php +++ b/system/ThirdParty/Kint/Renderer/RichRenderer.php @@ -26,18 +26,19 @@ namespace Kint\Renderer; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; use Kint\Utils; +use Kint\Zval\BlobValue; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class RichRenderer extends Renderer { /** - * RichRenderer object plugins should implement Kint\Renderer\Rich\ObjectPluginInterface. + * RichRenderer value plugins should implement Kint\Renderer\Rich\ValuePluginInterface. */ - public static $object_plugins = array( + public static $value_plugins = [ + 'array_limit' => 'Kint\\Renderer\\Rich\\ArrayLimitPlugin', 'blacklist' => 'Kint\\Renderer\\Rich\\BlacklistPlugin', 'callable' => 'Kint\\Renderer\\Rich\\CallablePlugin', 'closure' => 'Kint\\Renderer\\Rich\\ClosurePlugin', @@ -46,12 +47,12 @@ class RichRenderer extends Renderer 'recursion' => 'Kint\\Renderer\\Rich\\RecursionPlugin', 'simplexml_element' => 'Kint\\Renderer\\Rich\\SimpleXMLElementPlugin', 'trace_frame' => 'Kint\\Renderer\\Rich\\TraceFramePlugin', - ); + ]; /** * RichRenderer tab plugins should implement Kint\Renderer\Rich\TabPluginInterface. */ - public static $tab_plugins = array( + public static $tab_plugins = [ 'binary' => 'Kint\\Renderer\\Rich\\BinaryPlugin', 'color' => 'Kint\\Renderer\\Rich\\ColorPlugin', 'docstring' => 'Kint\\Renderer\\Rich\\DocstringPlugin', @@ -59,18 +60,18 @@ class RichRenderer extends Renderer 'source' => 'Kint\\Renderer\\Rich\\SourcePlugin', 'table' => 'Kint\\Renderer\\Rich\\TablePlugin', 'timestamp' => 'Kint\\Renderer\\Rich\\TimestampPlugin', - ); - - public static $pre_render_sources = array( - 'script' => array( - array('Kint\\Renderer\\RichRenderer', 'renderJs'), - array('Kint\\Renderer\\Rich\\MicrotimePlugin', 'renderJs'), - ), - 'style' => array( - array('Kint\\Renderer\\RichRenderer', 'renderCss'), - ), - 'raw' => array(), - ); + ]; + + public static $pre_render_sources = [ + 'script' => [ + ['Kint\\Renderer\\RichRenderer', 'renderJs'], + ['Kint\\Renderer\\Rich\\MicrotimePlugin', 'renderJs'], + ], + 'style' => [ + ['Kint\\Renderer\\RichRenderer', 'renderCss'], + ], + 'raw' => [], + ]; /** * Whether or not to render access paths. @@ -118,7 +119,7 @@ class RichRenderer extends Renderer * * @var bool */ - public static $folder = true; + public static $folder = false; /** * Sort mode for object properties. @@ -132,7 +133,7 @@ class RichRenderer extends Renderer public static $always_pre_render = false; - protected $plugin_objs = array(); + protected $plugin_objs = []; protected $expand = false; protected $force_pre_render = false; protected $pre_render; @@ -193,7 +194,6 @@ public function setForcePreRender() public function setPreRender($pre_render) { - $this->setForcePreRender(); // TODO: Remove line in next major version $this->pre_render = $pre_render; } @@ -212,10 +212,11 @@ public function getUseFolder() return $this->use_folder; } - public function render(BasicObject $o) + public function render(Value $o) { - if ($plugin = $this->getPlugin(self::$object_plugins, $o->hints)) { - if (\strlen($output = $plugin->renderObject($o))) { + if ($plugin = $this->getPlugin(self::$value_plugins, $o->hints)) { + $output = $plugin->renderValue($o); + if (null !== $output && \strlen($output)) { return $output; } } @@ -231,7 +232,7 @@ public function renderNothing() return '
    No argument
    '; } - public function renderHeaderWrapper(BasicObject $o, $has_children, $contents) + public function renderHeaderWrapper(Value $o, $has_children, $contents) { $out = ''; } - public function renderHeader(BasicObject $o) + public function renderHeader(Value $o) { $output = ''; @@ -319,10 +320,10 @@ public function renderHeader(BasicObject $o) return \trim($output); } - public function renderChildren(BasicObject $o) + public function renderChildren(Value $o) { - $contents = array(); - $tabs = array(); + $contents = []; + $tabs = []; foreach ($o->getRepresentations() as $rep) { $result = $this->renderTab($o, $rep); @@ -353,10 +354,16 @@ public function renderChildren(BasicObject $o) $output .= $this->escape($tab->getLabel()).'
  • '; } - $output .= '
      '; + $output .= '
      '; - foreach ($contents as $tab) { - $output .= '
    • '.$tab.'
    • '; + foreach ($contents as $i => $tab) { + if (0 === $i) { + $output .= '
    • '; + } else { + $output .= '
    • '; + } + + $output .= $tab.'
    • '; } $output .= '
    '; @@ -441,7 +448,7 @@ public function postRender() !empty($this->call_info['callee']['class']) || !\in_array( $this->call_info['callee']['function'], - array('include', 'include_once', 'require', 'require_once'), + ['include', 'include_once', 'require', 'require_once'], true ) ) @@ -465,7 +472,7 @@ public function postRender() $output .= '
  • '.$this->ideLink($step['file'], $step['line']); // closing tag not required if (isset($step['function']) - && !\in_array($step['function'], array('include', 'include_once', 'require', 'require_once'), true) + && !\in_array($step['function'], ['include', 'include_once', 'require', 'require_once'], true) ) { $output .= ' ['; if (isset($step['class'])) { @@ -488,7 +495,7 @@ public function postRender() public function escape($string, $encoding = false) { if (false === $encoding) { - $encoding = BlobObject::detectEncoding($string); + $encoding = BlobValue::detectEncoding($string); } $original_encoding = $encoding; @@ -501,7 +508,7 @@ public function escape($string, $encoding = false) // this call converts all non-ASCII characters into numeirc htmlentities if (\function_exists('mb_encode_numericentity') && 'ASCII' !== $original_encoding) { - $string = \mb_encode_numericentity($string, array(0x80, 0xffff, 0, 0xffff), $encoding); + $string = \mb_encode_numericentity($string, [0x80, 0xFFFF, 0, 0xFFFF], $encoding); } return $string; @@ -525,10 +532,11 @@ public function ideLink($file, $line) return ''.$path.''; } - protected function renderTab(BasicObject $o, Representation $rep) + protected function renderTab(Value $o, Representation $rep) { if ($plugin = $this->getPlugin(self::$tab_plugins, $rep->hints)) { - if (\strlen($output = $plugin->renderTab($rep))) { + $output = $plugin->renderTab($rep); + if (null !== $output && \strlen($output)) { return $output; } } @@ -536,7 +544,7 @@ protected function renderTab(BasicObject $o, Representation $rep) if (\is_array($rep->contents)) { $output = ''; - if ($o instanceof InstanceObject && 'properties' === $rep->getName()) { + if ($o instanceof InstanceValue && 'properties' === $rep->getName()) { foreach (self::sortProperties($rep->contents, self::$sort) as $obj) { $output .= $this->render($obj); } @@ -559,7 +567,7 @@ protected function renderTab(BasicObject $o, Representation $rep) } else { if (\preg_match('/(:?[\\r\\n\\t\\f\\v]| {2})/', $rep->contents)) { $show_contents = true; - } elseif (self::$strlen_max && BlobObject::strlen($o->getValueShort()) > self::$strlen_max) { + } elseif (self::$strlen_max && null !== $o->getValueShort() && BlobValue::strlen($o->getValueShort()) > self::$strlen_max) { $show_contents = true; } @@ -573,9 +581,11 @@ protected function renderTab(BasicObject $o, Representation $rep) } } - if ($rep->contents instanceof BasicObject) { + if ($rep->contents instanceof Value) { return $this->render($rep->contents); } + + return ''; } protected function getPlugin(array $plugins, array $hints) @@ -607,6 +617,6 @@ protected static function renderCss() protected static function renderFolder() { - return '
    Kint
    '; + return '
    Kint
    '; } } diff --git a/system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php new file mode 100644 index 000000000000..12c16f397b1b --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php @@ -0,0 +1,44 @@ +depth) { + $out .= $this->renderer->colorTitle($this->renderer->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderer->renderHeader($o).' '.$this->renderer->colorValue('ARRAY LIMIT').PHP_EOL; + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php b/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php index 127d32a197f9..441368b10720 100644 --- a/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class BlacklistPlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php index 310b87e417b0..cea6cdf89a50 100644 --- a/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class DepthLimitPlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php b/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php index 9128032c4ae0..ce63a5447d87 100644 --- a/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php @@ -25,12 +25,12 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; -use Kint\Object\Representation\MicrotimeRepresentation; use Kint\Renderer\PlainRenderer; use Kint\Renderer\Rich\MicrotimePlugin as RichPlugin; use Kint\Renderer\TextRenderer; use Kint\Utils; +use Kint\Zval\Representation\MicrotimeRepresentation; +use Kint\Zval\Value; class MicrotimePlugin extends Plugin { @@ -45,12 +45,12 @@ public function __construct(TextRenderer $r) } } - public function render(BasicObject $o) + public function render(Value $o) { $r = $o->getRepresentation('microtime'); if (!$r instanceof MicrotimeRepresentation) { - return false; + return; } $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/Plugin.php b/system/ThirdParty/Kint/Renderer/Text/Plugin.php index 9de25c1a1147..61a1820f48c8 100644 --- a/system/ThirdParty/Kint/Renderer/Text/Plugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/Plugin.php @@ -25,8 +25,8 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; use Kint\Renderer\TextRenderer; +use Kint\Zval\Value; abstract class Plugin { @@ -37,5 +37,8 @@ public function __construct(TextRenderer $r) $this->renderer = $r; } - abstract public function render(BasicObject $o); + /** + * @return null|string + */ + abstract public function render(Value $o); } diff --git a/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php b/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php index 72c2257ca8fc..21956b6ec221 100644 --- a/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class RecursionPlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php b/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php index 5833840cdf8f..b25f113e040b 100644 --- a/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php @@ -25,12 +25,12 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; -use Kint\Object\MethodObject; +use Kint\Zval\MethodValue; +use Kint\Zval\Value; class TracePlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; @@ -66,7 +66,7 @@ public function render(BasicObject $o) if (\is_string($frame->trace['function'])) { $framedesc .= $this->renderer->escape($frame->trace['function']).'(...)'; - } elseif ($frame->trace['function'] instanceof MethodObject) { + } elseif ($frame->trace['function'] instanceof MethodValue) { $framedesc .= $this->renderer->escape($frame->trace['function']->getName()); $framedesc .= '('.$this->renderer->escape($frame->trace['function']->getParams()).')'; } diff --git a/system/ThirdParty/Kint/Renderer/TextRenderer.php b/system/ThirdParty/Kint/Renderer/TextRenderer.php index 43b6c40d63b8..0cfba527c78b 100644 --- a/system/ThirdParty/Kint/Renderer/TextRenderer.php +++ b/system/ThirdParty/Kint/Renderer/TextRenderer.php @@ -26,33 +26,36 @@ namespace Kint\Renderer; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; use Kint\Utils; +use Kint\Zval\InstanceValue; +use Kint\Zval\Value; class TextRenderer extends Renderer { /** * TextRenderer plugins should be instances of Kint\Renderer\Text\Plugin. */ - public static $plugins = array( + public static $plugins = [ + 'array_limit' => 'Kint\\Renderer\\Text\\ArrayLimitPlugin', 'blacklist' => 'Kint\\Renderer\\Text\\BlacklistPlugin', 'depth_limit' => 'Kint\\Renderer\\Text\\DepthLimitPlugin', 'microtime' => 'Kint\\Renderer\\Text\\MicrotimePlugin', 'recursion' => 'Kint\\Renderer\\Text\\RecursionPlugin', 'trace' => 'Kint\\Renderer\\Text\\TracePlugin', - ); + ]; /** * Parser plugins must be instanceof one of these or * it will be removed for performance reasons. */ - public static $parser_plugin_whitelist = array( + public static $parser_plugin_whitelist = [ + 'Kint\\Parser\\ArrayLimitPlugin', + 'Kint\\Parser\\ArrayObjectPlugin', 'Kint\\Parser\\BlacklistPlugin', 'Kint\\Parser\\MicrotimePlugin', 'Kint\\Parser\\StreamPlugin', 'Kint\\Parser\\TracePlugin', - ); + ]; /** * The maximum length of a string before it is truncated. @@ -94,7 +97,7 @@ class TextRenderer extends Renderer public $header_width = 80; public $indent_width = 4; - protected $plugin_objs = array(); + protected $plugin_objs = []; public function __construct() { @@ -102,10 +105,11 @@ public function __construct() $this->indent_width = self::$default_indent; } - public function render(BasicObject $o) + public function render(Value $o) { if ($plugin = $this->getPlugin(self::$plugins, $o->hints)) { - if (\strlen($output = $plugin->render($o))) { + $output = $plugin->render($o); + if (null !== $output && \strlen($output)) { return $output; } } @@ -149,7 +153,7 @@ public function boxText($text, $width) return $out; } - public function renderTitle(BasicObject $o) + public function renderTitle(Value $o) { $name = (string) $o->getName(); @@ -160,9 +164,9 @@ public function renderTitle(BasicObject $o) return Utils::truncateString($name, $this->header_width); } - public function renderHeader(BasicObject $o) + public function renderHeader(Value $o) { - $output = array(); + $output = []; if ($o->depth) { if (null !== ($s = $o->getModifiers())) { @@ -200,7 +204,7 @@ public function renderHeader(BasicObject $o) return \str_repeat(' ', $o->depth * $this->indent_width).\implode(' ', $output); } - public function renderChildren(BasicObject $o) + public function renderChildren(Value $o) { if ('array' === $o->type) { $output = ' ['; @@ -213,7 +217,7 @@ public function renderChildren(BasicObject $o) $children = ''; if ($o->value && \is_array($o->value->contents)) { - if ($o instanceof InstanceObject && 'properties' === $o->value->getName()) { + if ($o instanceof InstanceValue && 'properties' === $o->value->getName()) { foreach (self::sortProperties($o->value->contents, self::$sort) as $obj) { $children .= $this->render($obj); } @@ -274,7 +278,7 @@ public function postRender() public function filterParserPlugins(array $plugins) { - $return = array(); + $return = []; foreach ($plugins as $index => $plugin) { foreach (self::$parser_plugin_whitelist as $whitelist) { @@ -313,7 +317,7 @@ protected function calledFrom() !empty($this->call_info['callee']['class']) || !\in_array( $this->call_info['callee']['function'], - array('include', 'include_once', 'require', 'require_once'), + ['include', 'include_once', 'require', 'require_once'], true ) ) diff --git a/system/ThirdParty/Kint/Utils.php b/system/ThirdParty/Kint/Utils.php index 27a24913fdb1..5143731c75c4 100644 --- a/system/ThirdParty/Kint/Utils.php +++ b/system/ThirdParty/Kint/Utils.php @@ -25,8 +25,7 @@ namespace Kint; -use InvalidArgumentException; -use Kint\Object\BlobObject; +use Kint\Zval\BlobValue; use ReflectionNamedType; use ReflectionType; @@ -51,15 +50,36 @@ private function __construct() */ public static function getHumanReadableBytes($value) { - static $unit = array('B', 'KB', 'MB', 'GB', 'TB'); + static $unit = ['B', 'KB', 'MB', 'GB', 'TB']; + + $negative = $value < 0; + $value = \abs($value); + + if ($value < 1024) { + $i = 0; + $value = \floor($value); + } elseif ($value < 0xFFFCCCCCCCCCCCC >> 40) { + $i = 1; + } elseif ($value < 0xFFFCCCCCCCCCCCC >> 30) { + $i = 2; + } elseif ($value < 0xFFFCCCCCCCCCCCC >> 20) { + $i = 3; + } else { + $i = 4; + } - $i = \floor(\log($value, 1024)); - $i = \min($i, 4); // Only go up to TB + if ($i) { + $value = $value / \pow(1024, $i); + } + + if ($negative) { + $value *= -1; + } - return array( - 'value' => (float) ($value / \pow(1024, $i)), + return [ + 'value' => \round($value, 1), 'unit' => $unit[$i], - ); + ]; } public static function isSequential(array $array) @@ -67,9 +87,14 @@ public static function isSequential(array $array) return \array_keys($array) === \range(0, \count($array) - 1); } + public static function isAssoc(array $array) + { + return (bool) \count(\array_filter(\array_keys($array), 'is_string')); + } + public static function composerGetExtras($key = 'kint') { - $extras = array(); + $extras = []; if (0 === \strpos(KINT_DIR, 'phar://')) { // Only run inside phar file, so skip for code coverage @@ -131,7 +156,7 @@ public static function isTrace(array $trace) return false; } - static $bt_structure = array( + static $bt_structure = [ 'function' => 'string', 'line' => 'integer', 'file' => 'string', @@ -139,7 +164,7 @@ public static function isTrace(array $trace) 'object' => 'object', 'type' => 'string', 'args' => 'array', - ); + ]; $file_found = false; @@ -169,7 +194,7 @@ public static function isTrace(array $trace) public static function traceFrameIsListed(array $frame, array $matches) { if (isset($frame['class'])) { - $called = array(\strtolower($frame['class']), \strtolower($frame['function'])); + $called = [\strtolower($frame['class']), \strtolower($frame['function'])]; } else { $called = \strtolower($frame['function']); } @@ -189,10 +214,10 @@ public static function normalizeAliases(array &$aliases) \preg_match('/^'.$name_regex.'$/', $alias[1]) && \preg_match('/^\\\\?('.$name_regex.'\\\\)*'.$name_regex.'$/', $alias[0]) ) { - $alias = array( + $alias = [ \strtolower(\ltrim($alias[0], '\\')), \strtolower($alias[1]), - ); + ]; } else { unset($aliases[$index]); continue; @@ -216,14 +241,15 @@ public static function normalizeAliases(array &$aliases) public static function truncateString($input, $length = PHP_INT_MAX, $end = '...', $encoding = false) { $length = (int) $length; - $endlength = BlobObject::strlen($end); + $endlength = BlobValue::strlen($end); if ($endlength >= $length) { - throw new InvalidArgumentException('Can\'t truncate a string to '.$length.' characters if ending with string '.$endlength.' characters long'); + $endlength = 0; + $end = ''; } - if (BlobObject::strlen($input, $encoding) > $length) { - return BlobObject::substr($input, 0, $length - $endlength, $encoding).$end; + if (BlobValue::strlen($input, $encoding) > $length) { + return BlobValue::substr($input, 0, $length - $endlength, $encoding).$end; } return $input; @@ -232,7 +258,12 @@ public static function truncateString($input, $length = PHP_INT_MAX, $end = '... public static function getTypeString(ReflectionType $type) { if ($type instanceof ReflectionNamedType) { - return $type->getName(); + $name = $type->getName(); + if ($type->allowsNull() && false === \strpos($name, '|')) { + $name = '?'.$name; + } + + return $name; } return (string) $type; // @codeCoverageIgnore diff --git a/system/ThirdParty/Kint/Object/BlobObject.php b/system/ThirdParty/Kint/Zval/BlobValue.php similarity index 95% rename from system/ThirdParty/Kint/Object/BlobObject.php rename to system/ThirdParty/Kint/Zval/BlobValue.php index 66d508ff70db..c5ac53acb096 100644 --- a/system/ThirdParty/Kint/Object/BlobObject.php +++ b/system/ThirdParty/Kint/Zval/BlobValue.php @@ -23,9 +23,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class BlobObject extends BasicObject +class BlobValue extends Value { /** * @var array Character encodings to detect @@ -51,10 +51,10 @@ class BlobObject extends BasicObject * * This depends on the mbstring extension */ - public static $char_encodings = array( + public static $char_encodings = [ 'ASCII', 'UTF-8', - ); + ]; /** * @var array Legacy character encodings to detect @@ -74,11 +74,11 @@ class BlobObject extends BasicObject * * This depends on the iconv extension */ - public static $legacy_encodings = array(); + public static $legacy_encodings = []; public $type = 'string'; public $encoding = false; - public $hints = array('string'); + public $hints = ['string']; public function getType() { @@ -100,7 +100,7 @@ public function getValueShort() } } - public function transplant(BasicObject $old) + public function transplant(Value $old) { parent::transplant($old); diff --git a/system/ThirdParty/Kint/Object/ClosureObject.php b/system/ThirdParty/Kint/Zval/ClosureValue.php similarity index 91% rename from system/ThirdParty/Kint/Object/ClosureObject.php rename to system/ThirdParty/Kint/Zval/ClosureValue.php index 344eceb21e77..95dd3fea9e39 100644 --- a/system/ThirdParty/Kint/Object/ClosureObject.php +++ b/system/ThirdParty/Kint/Zval/ClosureValue.php @@ -23,12 +23,12 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class ClosureObject extends InstanceObject +class ClosureValue extends InstanceValue { - public $parameters = array(); - public $hints = array('object', 'callable', 'closure'); + public $parameters = []; + public $hints = ['object', 'callable', 'closure']; private $paramcache; @@ -49,7 +49,7 @@ public function getParams() return $this->paramcache; } - $out = array(); + $out = []; foreach ($this->parameters as $p) { $type = $p->getType(); diff --git a/system/ThirdParty/Kint/Object/DateTimeObject.php b/system/ThirdParty/Kint/Zval/DateTimeValue.php similarity index 93% rename from system/ThirdParty/Kint/Object/DateTimeObject.php rename to system/ThirdParty/Kint/Zval/DateTimeValue.php index f8b1b3fd164f..1a8084ec3b9f 100644 --- a/system/ThirdParty/Kint/Object/DateTimeObject.php +++ b/system/ThirdParty/Kint/Zval/DateTimeValue.php @@ -23,15 +23,15 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use DateTime; -class DateTimeObject extends InstanceObject +class DateTimeValue extends InstanceValue { public $dt; - public $hints = array('object', 'datetime'); + public $hints = ['object', 'datetime']; public function __construct(DateTime $dt) { diff --git a/system/ThirdParty/Kint/Object/InstanceObject.php b/system/ThirdParty/Kint/Zval/InstanceValue.php similarity index 88% rename from system/ThirdParty/Kint/Object/InstanceObject.php rename to system/ThirdParty/Kint/Zval/InstanceValue.php index 943b33d8eabb..1c26600ca47e 100644 --- a/system/ThirdParty/Kint/Object/InstanceObject.php +++ b/system/ThirdParty/Kint/Zval/InstanceValue.php @@ -23,29 +23,29 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class InstanceObject extends BasicObject +class InstanceValue extends Value { public $type = 'object'; public $classname; - public $hash; + public $spl_object_hash; public $filename; public $startline; - public $hints = array('object'); + public $hints = ['object']; public function getType() { return $this->classname; } - public function transplant(BasicObject $old) + public function transplant(Value $old) { parent::transplant($old); if ($old instanceof self) { $this->classname = $old->classname; - $this->hash = $old->hash; + $this->spl_object_hash = $old->spl_object_hash; $this->filename = $old->filename; $this->startline = $old->startline; } @@ -56,7 +56,7 @@ public static function sortByHierarchy($a, $b) if (\is_string($a) && \is_string($b)) { $aclass = $a; $bclass = $b; - } elseif (!($a instanceof BasicObject) || !($b instanceof BasicObject)) { + } elseif (!($a instanceof Value) || !($b instanceof Value)) { return 0; } elseif ($a instanceof self && $b instanceof self) { $aclass = $a->classname; diff --git a/system/ThirdParty/Kint/Object/MethodObject.php b/system/ThirdParty/Kint/Zval/MethodValue.php similarity index 90% rename from system/ThirdParty/Kint/Object/MethodObject.php rename to system/ThirdParty/Kint/Zval/MethodValue.php index 78d49de22264..5d59a50765f2 100644 --- a/system/ThirdParty/Kint/Object/MethodObject.php +++ b/system/ThirdParty/Kint/Zval/MethodValue.php @@ -23,27 +23,27 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -use Kint\Object\Representation\DocstringRepresentation; use Kint\Utils; +use Kint\Zval\Representation\DocstringRepresentation; use ReflectionFunctionAbstract; use ReflectionMethod; -class MethodObject extends BasicObject +class MethodValue extends Value { public $type = 'method'; public $filename; public $startline; public $endline; - public $parameters = array(); + public $parameters = []; public $abstract; public $final; public $internal; public $docstring; public $returntype; public $return_reference = false; - public $hints = array('callable', 'method'); + public $hints = ['callable', 'method']; public $showparams = true; private $paramcache; @@ -61,7 +61,7 @@ public function __construct(ReflectionFunctionAbstract $method) $this->return_reference = $method->returnsReference(); foreach ($method->getParameters() as $param) { - $this->parameters[] = new ParameterObject($param); + $this->parameters[] = new ParameterValue($param); } if (KINT_PHP70) { @@ -73,15 +73,15 @@ public function __construct(ReflectionFunctionAbstract $method) if ($method instanceof ReflectionMethod) { $this->static = $method->isStatic(); - $this->operator = $this->static ? BasicObject::OPERATOR_STATIC : BasicObject::OPERATOR_OBJECT; + $this->operator = $this->static ? Value::OPERATOR_STATIC : Value::OPERATOR_OBJECT; $this->abstract = $method->isAbstract(); $this->final = $method->isFinal(); $this->owner_class = $method->getDeclaringClass()->name; - $this->access = BasicObject::ACCESS_PUBLIC; + $this->access = Value::ACCESS_PUBLIC; if ($method->isProtected()) { - $this->access = BasicObject::ACCESS_PROTECTED; + $this->access = Value::ACCESS_PROTECTED; } elseif ($method->isPrivate()) { - $this->access = BasicObject::ACCESS_PRIVATE; + $this->access = Value::ACCESS_PRIVATE; } } @@ -100,9 +100,9 @@ public function __construct(ReflectionFunctionAbstract $method) $this->value = $docstring; } - public function setAccessPathFrom(InstanceObject $parent) + public function setAccessPathFrom(InstanceValue $parent) { - static $magic = array( + static $magic = [ '__call' => true, '__callstatic' => true, '__clone' => true, @@ -118,7 +118,7 @@ public function setAccessPathFrom(InstanceObject $parent) '__tostring' => true, '__unset' => true, '__wakeup' => true, - ); + ]; $name = \strtolower($this->name); @@ -172,12 +172,12 @@ public function getValueShort() public function getModifiers() { - $mods = array( + $mods = [ $this->abstract ? 'abstract' : null, $this->final ? 'final' : null, $this->getAccess(), $this->static ? 'static' : null, - ); + ]; $out = ''; @@ -209,7 +209,7 @@ public function getParams() return $this->paramcache; } - $out = array(); + $out = []; foreach ($this->parameters as $p) { $type = $p->getType(); diff --git a/system/ThirdParty/Kint/Object/ParameterObject.php b/system/ThirdParty/Kint/Zval/ParameterValue.php similarity index 95% rename from system/ThirdParty/Kint/Object/ParameterObject.php rename to system/ThirdParty/Kint/Zval/ParameterValue.php index 4bed551f548b..29bcbe72bb2b 100644 --- a/system/ThirdParty/Kint/Object/ParameterObject.php +++ b/system/ThirdParty/Kint/Zval/ParameterValue.php @@ -23,18 +23,18 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use Kint\Utils; use ReflectionException; use ReflectionParameter; -class ParameterObject extends BasicObject +class ParameterValue extends Value { public $type_hint; public $default; public $position; - public $hints = array('parameter'); + public $hints = ['parameter']; public function __construct(ReflectionParameter $param) { @@ -64,7 +64,6 @@ public function __construct(ReflectionParameter $param) $this->position = $param->getPosition(); if ($param->isDefaultValueAvailable()) { - /** @var mixed Psalm bug workaround */ $default = $param->getDefaultValue(); switch (\gettype($default)) { case 'NULL': diff --git a/system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/ColorRepresentation.php similarity index 96% rename from system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/ColorRepresentation.php index d6a072f50891..533ccb35d940 100644 --- a/system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/ColorRepresentation.php @@ -23,7 +23,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; use InvalidArgumentException; @@ -39,7 +39,7 @@ class ColorRepresentation extends Representation const COLOR_HEX_4 = 8; const COLOR_HEX_8 = 9; - public static $color_map = array( + public static $color_map = [ 'aliceblue' => 'f0f8ff', 'antiquewhite' => 'faebd7', 'aqua' => '00ffff', @@ -191,7 +191,7 @@ class ColorRepresentation extends Representation 'whitesmoke' => 'f5f5f5', 'yellow' => 'ffff00', 'yellowgreen' => '9acd32', - ); + ]; public $r = 0; public $g = 0; @@ -199,7 +199,7 @@ class ColorRepresentation extends Representation public $a = 1.0; public $variant; public $implicit_label = true; - public $hints = array('color'); + public $hints = ['color']; public function __construct($value) { @@ -254,7 +254,7 @@ public function getColor($variant = null) return \sprintf('hsla(%d, %d%%, %d%%, %s)', $val[0], $val[1], $val[2], \round($this->a, 4)); case self::COLOR_HEX_4: - if (0 === $this->r % 0x11 && 0 === $this->g % 0x11 && 0 === $this->b % 0x11 && 0 === ($this->a * 255) % 0x11) { + if (0 === $this->r % 0x11 && 0 === $this->g % 0x11 && 0 === $this->b % 0x11 && 0 === ((int) ($this->a * 255)) % 0x11) { return \sprintf( '#%1X%1X%1X%1X', \round($this->r / 0x11), @@ -413,21 +413,19 @@ protected function setValuesFromFunction($value) if (3 === $i) { $color = $color / 100; - } elseif (\in_array($variant, array(self::COLOR_RGB, self::COLOR_RGBA), true)) { + } elseif (\in_array($variant, [self::COLOR_RGB, self::COLOR_RGBA], true)) { $color = \round($color / 100 * 0xFF); } } $color = (float) $color; - if (0 === $i && \in_array($variant, array(self::COLOR_HSL, self::COLOR_HSLA), true)) { - $color = ($color % 360 + 360) % 360; + if (0 === $i && \in_array($variant, [self::COLOR_HSL, self::COLOR_HSLA], true)) { + $color = \fmod(\fmod($color, 360) + 360, 360); } } - /** @var float[] Psalm bug workaround */ - $params = \array_map('floatval', $params); - + /** @var non-empty-array $params Psalm bug workaround */ switch ($variant) { case self::COLOR_RGBA: case self::COLOR_RGB: @@ -486,11 +484,11 @@ public static function hslToRgb($h, $s, $l) $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l * $s; $m1 = $l * 2 - $m2; - return array( + return [ (int) \round(self::hueToRgb($m1, $m2, $h + 1 / 3) * 0xFF), (int) \round(self::hueToRgb($m1, $m2, $h) * 0xFF), (int) \round(self::hueToRgb($m1, $m2, $h - 1 / 3) * 0xFF), - ); + ]; } /** @@ -541,17 +539,16 @@ public static function rgbToHsl($red, $green, $blue) } } - return array( - (float) ($H * 360 % 360), + return [ + \fmod($H * 360, 360), (float) ($S * 100), (float) ($L * 100), - ); + ]; } /** * Helper function for hslToRgb. Even blacker magic. * - * * @param float $m1 * @param float $m2 * @param float $hue diff --git a/system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/DocstringRepresentation.php similarity index 97% rename from system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/DocstringRepresentation.php index 488d8d6e0748..8acdcc1e8583 100644 --- a/system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/DocstringRepresentation.php @@ -23,14 +23,14 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; class DocstringRepresentation extends Representation { public $file; public $line; public $class; - public $hints = array('docstring'); + public $hints = ['docstring']; public function __construct($docstring, $file, $line, $class = null) { diff --git a/system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/MicrotimeRepresentation.php similarity index 96% rename from system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/MicrotimeRepresentation.php index b9f4dacb314b..aedc2edffb6e 100644 --- a/system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/MicrotimeRepresentation.php @@ -23,7 +23,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; use DateTime; @@ -40,7 +40,7 @@ class MicrotimeRepresentation extends Representation public $mem_real = 0; public $mem_peak = 0; public $mem_peak_real = 0; - public $hints = array('microtime'); + public $hints = ['microtime']; public function __construct($seconds, $microseconds, $group, $lap = null, $total = null, $i = 0) { diff --git a/system/ThirdParty/Kint/Object/Representation/Representation.php b/system/ThirdParty/Kint/Zval/Representation/Representation.php similarity index 95% rename from system/ThirdParty/Kint/Object/Representation/Representation.php rename to system/ThirdParty/Kint/Zval/Representation/Representation.php index 0c911a4eaa98..2d649d077c13 100644 --- a/system/ThirdParty/Kint/Object/Representation/Representation.php +++ b/system/ThirdParty/Kint/Zval/Representation/Representation.php @@ -23,14 +23,14 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; class Representation { public $label; public $implicit_label = false; - public $hints = array(); - public $contents = array(); + public $hints = []; + public $contents = []; protected $name; diff --git a/system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/SourceRepresentation.php similarity index 96% rename from system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/SourceRepresentation.php index c2cf1204f1a9..65077d6218c6 100644 --- a/system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/SourceRepresentation.php @@ -23,12 +23,12 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; class SourceRepresentation extends Representation { - public $hints = array('source'); - public $source = array(); + public $hints = ['source']; + public $source = []; public $filename; public $line = 0; public $showfilename = false; diff --git a/system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php similarity index 95% rename from system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php index 3df50e6a1284..6208451b41ed 100644 --- a/system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php @@ -23,29 +23,29 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; use Kint\Utils; use SplFileInfo; class SplFileInfoRepresentation extends Representation { - public $perms; + public $perms = null; public $flags; public $path; - public $realpath; - public $linktarget; + public $realpath = null; + public $linktarget = null; public $size; public $is_dir = false; public $is_file = false; public $is_link = false; - public $owner; - public $group; + public $owner = null; + public $group = null; public $ctime; public $mtime; public $typename = 'Unknown file'; public $typeflag = '-'; - public $hints = array('fspath'); + public $hints = ['fspath']; public function __construct(SplFileInfo $fileInfo) { @@ -109,7 +109,7 @@ public function __construct(SplFileInfo $fileInfo) break; } - $this->flags = array($this->typeflag); + $this->flags = [$this->typeflag]; // User $this->flags[] = (($this->perms & 0400) ? 'r' : '-'); diff --git a/system/ThirdParty/Kint/Object/ResourceObject.php b/system/ThirdParty/Kint/Zval/ResourceValue.php similarity index 93% rename from system/ThirdParty/Kint/Object/ResourceObject.php rename to system/ThirdParty/Kint/Zval/ResourceValue.php index a43f85d900ee..ef1c5541e476 100644 --- a/system/ThirdParty/Kint/Object/ResourceObject.php +++ b/system/ThirdParty/Kint/Zval/ResourceValue.php @@ -23,9 +23,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class ResourceObject extends BasicObject +class ResourceValue extends Value { public $resource_type; @@ -38,7 +38,7 @@ public function getType() return 'resource'; } - public function transplant(BasicObject $old) + public function transplant(Value $old) { parent::transplant($old); diff --git a/system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php b/system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php new file mode 100644 index 000000000000..b385bc6daa2e --- /dev/null +++ b/system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php @@ -0,0 +1,48 @@ +is_string_value = $is_string_value; + } + + public function getValueShort() + { + if ($this->is_string_value && ($rep = $this->value) && 'contents' === $rep->getName() && 'string' === \gettype($rep->contents)) { + return '"'.$rep->contents.'"'; + } + } +} diff --git a/system/ThirdParty/Kint/Object/StreamObject.php b/system/ThirdParty/Kint/Zval/StreamValue.php similarity index 96% rename from system/ThirdParty/Kint/Object/StreamObject.php rename to system/ThirdParty/Kint/Zval/StreamValue.php index 358f2743e94f..af909c84f39a 100644 --- a/system/ThirdParty/Kint/Object/StreamObject.php +++ b/system/ThirdParty/Kint/Zval/StreamValue.php @@ -23,11 +23,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use Kint\Kint; -class StreamObject extends ResourceObject +class StreamValue extends ResourceValue { public $stream_meta; diff --git a/system/ThirdParty/Kint/Object/ThrowableObject.php b/system/ThirdParty/Kint/Zval/ThrowableValue.php similarity index 88% rename from system/ThirdParty/Kint/Object/ThrowableObject.php rename to system/ThirdParty/Kint/Zval/ThrowableValue.php index 2a86d57538df..26676481c26d 100644 --- a/system/ThirdParty/Kint/Object/ThrowableObject.php +++ b/system/ThirdParty/Kint/Zval/ThrowableValue.php @@ -23,21 +23,21 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use Exception; use InvalidArgumentException; use Throwable; -class ThrowableObject extends InstanceObject +class ThrowableValue extends InstanceValue { public $message; - public $hints = array('object', 'throwable'); + public $hints = ['object', 'throwable']; public function __construct($throw) { if (!$throw instanceof Exception && (!KINT_PHP70 || !$throw instanceof Throwable)) { - throw new InvalidArgumentException('ThrowableObject must be constructed with a Throwable'); + throw new InvalidArgumentException('ThrowableValue must be constructed with a Throwable'); } parent::__construct(); diff --git a/system/ThirdParty/Kint/Object/TraceFrameObject.php b/system/ThirdParty/Kint/Zval/TraceFrameValue.php similarity index 81% rename from system/ThirdParty/Kint/Object/TraceFrameObject.php rename to system/ThirdParty/Kint/Zval/TraceFrameValue.php index 4259aeeec1aa..62f7829192d2 100644 --- a/system/ThirdParty/Kint/Object/TraceFrameObject.php +++ b/system/ThirdParty/Kint/Zval/TraceFrameValue.php @@ -23,52 +23,57 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -use Kint\Object\Representation\Representation; -use Kint\Object\Representation\SourceRepresentation; +use InvalidArgumentException; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Representation\SourceRepresentation; use ReflectionFunction; use ReflectionMethod; -class TraceFrameObject extends BasicObject +class TraceFrameValue extends Value { public $trace; - public $hints = array('trace_frame'); + public $hints = ['trace_frame']; - public function __construct(BasicObject $base, array $raw_frame) + public function __construct(Value $base, array $raw_frame) { parent::__construct(); $this->transplant($base); - $this->trace = array( - 'function' => isset($raw_frame['function']) ? $raw_frame['function'] : null, + if (!isset($this->value)) { + throw new InvalidArgumentException('Tried to create TraceFrameValue from Value with no value representation'); + } + + $this->trace = [ + 'function' => $raw_frame['function'], 'line' => isset($raw_frame['line']) ? $raw_frame['line'] : null, 'file' => isset($raw_frame['file']) ? $raw_frame['file'] : null, 'class' => isset($raw_frame['class']) ? $raw_frame['class'] : null, 'type' => isset($raw_frame['type']) ? $raw_frame['type'] : null, 'object' => null, 'args' => null, - ); + ]; if ($this->trace['class'] && \method_exists($this->trace['class'], $this->trace['function'])) { $func = new ReflectionMethod($this->trace['class'], $this->trace['function']); - $this->trace['function'] = new MethodObject($func); + $this->trace['function'] = new MethodValue($func); } elseif (!$this->trace['class'] && \function_exists($this->trace['function'])) { $func = new ReflectionFunction($this->trace['function']); - $this->trace['function'] = new MethodObject($func); + $this->trace['function'] = new MethodValue($func); } foreach ($this->value->contents as $frame_prop) { if ('object' === $frame_prop->name) { $this->trace['object'] = $frame_prop; $this->trace['object']->name = null; - $this->trace['object']->operator = BasicObject::OPERATOR_NONE; + $this->trace['object']->operator = Value::OPERATOR_NONE; } if ('args' === $frame_prop->name) { $this->trace['args'] = $frame_prop->value->contents; - if ($this->trace['function'] instanceof MethodObject) { + if ($this->trace['function'] instanceof MethodValue) { foreach (\array_values($this->trace['function']->parameters) as $param) { if (isset($this->trace['args'][$param->position])) { $this->trace['args'][$param->position]->name = $param->getName(); diff --git a/system/ThirdParty/Kint/Object/TraceObject.php b/system/ThirdParty/Kint/Zval/TraceValue.php similarity index 93% rename from system/ThirdParty/Kint/Object/TraceObject.php rename to system/ThirdParty/Kint/Zval/TraceValue.php index a780b082bf9c..4d0edc42219a 100644 --- a/system/ThirdParty/Kint/Object/TraceObject.php +++ b/system/ThirdParty/Kint/Zval/TraceValue.php @@ -23,11 +23,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class TraceObject extends BasicObject +class TraceValue extends Value { - public $hints = array('trace'); + public $hints = ['trace']; public function getType() { diff --git a/system/ThirdParty/Kint/Object/BasicObject.php b/system/ThirdParty/Kint/Zval/Value.php similarity index 91% rename from system/ThirdParty/Kint/Object/BasicObject.php rename to system/ThirdParty/Kint/Zval/Value.php index d69347eb8dfc..747efb5f718f 100644 --- a/system/ThirdParty/Kint/Object/BasicObject.php +++ b/system/ThirdParty/Kint/Zval/Value.php @@ -23,11 +23,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; -class BasicObject +class Value { const ACCESS_NONE = null; const ACCESS_PUBLIC = 1; @@ -51,9 +51,9 @@ class BasicObject public $depth = 0; public $size; public $value; - public $hints = array(); + public $hints = []; - protected $representations = array(); + protected $representations = []; public function __construct() { @@ -70,7 +70,7 @@ public function addRepresentation(Representation $rep, $pos = null) } else { $this->representations = \array_merge( \array_slice($this->representations, 0, $pos), - array($rep->getName() => $rep), + [$rep->getName() => $rep], \array_slice($this->representations, $pos) ); } @@ -111,7 +111,7 @@ public function getRepresentations() public function clearRepresentations() { - $this->representations = array(); + $this->representations = []; } public function getType() @@ -131,7 +131,7 @@ public function getModifiers() $out .= ' static'; } - if (\strlen($out)) { + if (null !== $out && \strlen($out)) { return \ltrim($out); } } @@ -188,7 +188,7 @@ public function getAccessPath() return $this->access_path; } - public function transplant(BasicObject $old) + public function transplant(Value $old) { $this->name = $old->name; $this->size = $old->size; @@ -212,7 +212,7 @@ public function transplant(BasicObject $old) * @param null|string $name * @param null|string $access_path * - * @return \Kint\Object\BasicObject + * @return \Kint\Zval\Value */ public static function blank($name = null, $access_path = null) { @@ -223,19 +223,19 @@ public static function blank($name = null, $access_path = null) return $o; } - public static function sortByAccess(BasicObject $a, BasicObject $b) + public static function sortByAccess(Value $a, Value $b) { - static $sorts = array( + static $sorts = [ self::ACCESS_PUBLIC => 1, self::ACCESS_PROTECTED => 2, self::ACCESS_PRIVATE => 3, self::ACCESS_NONE => 4, - ); + ]; return $sorts[$a->access] - $sorts[$b->access]; } - public static function sortByName(BasicObject $a, BasicObject $b) + public static function sortByName(Value $a, Value $b) { $ret = \strnatcasecmp($a->name, $b->name); diff --git a/system/ThirdParty/Kint/init.php b/system/ThirdParty/Kint/init.php index 952e041400ff..2e7c62b4b1c9 100644 --- a/system/ThirdParty/Kint/init.php +++ b/system/ThirdParty/Kint/init.php @@ -30,31 +30,33 @@ return; } -if (\version_compare(PHP_VERSION, '5.3') < 0) { - throw new Exception('Kint 3.0 requires PHP 5.3 or higher'); +if (\version_compare(PHP_VERSION, '5.6') < 0) { + throw new Exception('Kint 4.0 requires PHP 5.6 or higher'); } \define('KINT_DIR', __DIR__); \define('KINT_WIN', DIRECTORY_SEPARATOR !== '/'); -\define('KINT_PHP56', (\version_compare(PHP_VERSION, '5.6') >= 0)); \define('KINT_PHP70', (\version_compare(PHP_VERSION, '7.0') >= 0)); +\define('KINT_PHP71', (\version_compare(PHP_VERSION, '7.1') >= 0)); \define('KINT_PHP72', (\version_compare(PHP_VERSION, '7.2') >= 0)); \define('KINT_PHP73', (\version_compare(PHP_VERSION, '7.3') >= 0)); \define('KINT_PHP74', (\version_compare(PHP_VERSION, '7.4') >= 0)); +\define('KINT_PHP80', (\version_compare(PHP_VERSION, '8.0') >= 0)); +\define('KINT_PHP81', (\version_compare(PHP_VERSION, '8.1') >= 0)); // Dynamic default settings Kint::$file_link_format = \ini_get('xdebug.file_link_format'); if (isset($_SERVER['DOCUMENT_ROOT'])) { - Kint::$app_root_dirs = array( + Kint::$app_root_dirs = [ $_SERVER['DOCUMENT_ROOT'] => '', \realpath($_SERVER['DOCUMENT_ROOT']) => '', - ); + ]; } Utils::composerSkipFlags(); if ((!\defined('KINT_SKIP_FACADE') || !KINT_SKIP_FACADE) && !\class_exists('Kint')) { - \class_alias('Kint\\Kint', 'Kint'); + \class_alias(Kint::class, 'Kint'); } if (!\defined('KINT_SKIP_HELPERS') || !KINT_SKIP_HELPERS) { diff --git a/system/ThirdParty/Kint/init_helpers.php b/system/ThirdParty/Kint/init_helpers.php index b961d67f1af5..3dca84c35f08 100644 --- a/system/ThirdParty/Kint/init_helpers.php +++ b/system/ThirdParty/Kint/init_helpers.php @@ -24,6 +24,7 @@ */ use Kint\Kint; +use Kint\Renderer\CliRenderer; if (!\function_exists('d')) { /** @@ -35,7 +36,7 @@ function d() { $args = \func_get_args(); - return \call_user_func_array(array('Kint', 'dump'), $args); + return \call_user_func_array(['Kint', 'dump'], $args); } Kint::$aliases[] = 'd'; @@ -59,23 +60,28 @@ function d() */ function s() { - if (!Kint::$enabled_mode) { + if (false === Kint::$enabled_mode) { return 0; } - $stash = Kint::$enabled_mode; + $kstash = Kint::$enabled_mode; + $cstash = CliRenderer::$cli_colors; if (Kint::MODE_TEXT !== Kint::$enabled_mode) { Kint::$enabled_mode = Kint::MODE_PLAIN; + if (PHP_SAPI === 'cli' && true === Kint::$cli_detection) { Kint::$enabled_mode = Kint::$mode_default_cli; } } + CliRenderer::$cli_colors = false; + $args = \func_get_args(); - $out = \call_user_func_array(array('Kint', 'dump'), $args); + $out = \call_user_func_array(['Kint', 'dump'], $args); - Kint::$enabled_mode = $stash; + Kint::$enabled_mode = $kstash; + CliRenderer::$cli_colors = $cstash; return $out; } diff --git a/system/ThirdParty/Kint/resources/compiled/aante-light.css b/system/ThirdParty/Kint/resources/compiled/aante-light.css index 2de17accf9a9..dc7a40a73489 100644 --- a/system/ThirdParty/Kint/resources/compiled/aante-light.css +++ b/system/ThirdParty/Kint/resources/compiled/aante-light.css @@ -1 +1 @@ -.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:none}.kint-rich.kint-folder.kint-show{display:block}.kint-rich.kint-folder dd.kint-folder{max-height:calc(100vh - 100px);padding-right:8px;overflow-y:scroll}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#aaa;color:#1d1e1e}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:8px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#f8f8f8;border:1px solid #d7d7d7;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#aaa}.kint-rich>dl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxwYXRoIGQ9Ik02IDdoMThsLTkgMTV6bTAgMzBoMThsLTkgMTV6bTAgNDVoMThsLTktMTV6bTAgMzBoMThsLTktMTV6bTAgMTJsMTggMThtLTE4IDBsMTgtMTgiIGZpbGw9IiM1NTUiLz48cGF0aCBkPSJNNiAxMjZsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSIjNTU1Ii8+PC9zdmc+") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #d7d7d7}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#06f;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:red}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #d7d7d7;background:#f8f8f8;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#f8f8f8;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#f8f8f8}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #d7d7d7;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#f8f8f8;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#f8f8f8;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f8f8f8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#f8f8f8;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #d7d7d7}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#f8f8f8;border:1px solid #d7d7d7;border-top:0}.kint-rich ul.kint-tabs>li{background:#f8f8f8;border:1px solid #d7d7d7;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#aaa;color:red}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#f8f8f8;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#aaa;color:red}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #d7d7d7;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#aaa}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #d7d7d7;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#f8f8f8;color:#1d1e1e}.kint-rich table td{background:#f8f8f8;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #aaa inset}.kint-rich table tr:hover var{color:red}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #f8f8f8}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #aaa;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#f8f8f8}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #aaa,0 1px #aaa,1px 0 #aaa,0 -1px #aaa;color:#f8f8f8;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich dt{font-weight:normal}.kint-rich dt.kint-parent{margin-top:4px}.kint-rich dl dl{margin-top:4px;padding-left:25px;border-left:none}.kint-rich>dl>dt{background:#f8f8f8}.kint-rich ul{margin:0;padding-left:0}.kint-rich ul:not(.kint-tabs)>li{border-left:0}.kint-rich ul.kint-tabs{background:#f8f8f8;border:1px solid #d7d7d7;border-width:0 1px 1px 1px;padding:4px 0 0 12px;margin-left:-1px;margin-top:-1px}.kint-rich ul.kint-tabs li,.kint-rich ul.kint-tabs li+li{margin:0 0 0 4px}.kint-rich ul.kint-tabs li{border-bottom-width:0;height:25px}.kint-rich ul.kint-tabs li:first-child{margin-left:0}.kint-rich ul.kint-tabs li.kint-active-tab{border-top:1px solid #d7d7d7;background:#fff;font-weight:bold;padding-top:0;border-bottom:1px solid #fff !important;margin-bottom:-1px}.kint-rich ul.kint-tabs li.kint-active-tab:hover{border-bottom:1px solid #fff}.kint-rich ul>li>pre{border:1px solid #d7d7d7}.kint-rich dt:hover+dd>ul{border-color:#aaa}.kint-rich pre{background:#fff;margin-top:4px;margin-left:25px}.kint-rich .kint-source{margin-left:-1px}.kint-rich .kint-source .kint-highlight{background:#cfc}.kint-rich .kint-parent.kint-show>.kint-search{border-bottom-width:1px}.kint-rich table td{background:#fff}.kint-rich table td>dl{padding:0;margin:0}.kint-rich table td>dl>dt.kint-parent{margin:0}.kint-rich table td:first-child,.kint-rich table td,.kint-rich table th{padding:2px 4px}.kint-rich table dd,.kint-rich table dt{background:#fff}.kint-rich table tr:hover>td{box-shadow:none;background:#cfc} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:8px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#aaa;color:#1d1e1e}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:8px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#f8f8f8;border:1px solid #d7d7d7;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#aaa}.kint-rich>dl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxwYXRoIGQ9Ik02IDdoMThsLTkgMTV6bTAgMzBoMThsLTkgMTV6bTAgNDVoMThsLTktMTV6bTAgMzBoMThsLTktMTV6bTAgMTJsMTggMThtLTE4IDBsMTgtMTgiIGZpbGw9IiM1NTUiLz48cGF0aCBkPSJNNiAxMjZsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSIjNTU1Ii8+PC9zdmc+") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #d7d7d7}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#06f;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:red}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #d7d7d7;background:#f8f8f8;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#f8f8f8;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#f8f8f8}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #d7d7d7;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#f8f8f8;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#f8f8f8;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f8f8f8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#f8f8f8;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #d7d7d7}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#f8f8f8;border:1px solid #d7d7d7;border-top:0}.kint-rich ul.kint-tabs>li{background:#f8f8f8;border:1px solid #d7d7d7;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#aaa;color:red}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#f8f8f8;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#aaa;color:red}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #d7d7d7;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#aaa}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #d7d7d7;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#f8f8f8;color:#1d1e1e}.kint-rich table td{background:#f8f8f8;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #aaa inset}.kint-rich table tr:hover var{color:red}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #f8f8f8}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #aaa;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#f8f8f8}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #aaa,0 1px #aaa,1px 0 #aaa,0 -1px #aaa;color:#f8f8f8;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich dt{font-weight:normal}.kint-rich dt.kint-parent{margin-top:4px}.kint-rich dl dl{margin-top:4px;padding-left:25px;border-left:none}.kint-rich>dl>dt{background:#f8f8f8}.kint-rich ul{margin:0;padding-left:0}.kint-rich ul:not(.kint-tabs)>li{border-left:0}.kint-rich ul.kint-tabs{background:#f8f8f8;border:1px solid #d7d7d7;border-width:0 1px 1px 1px;padding:4px 0 0 12px;margin-left:-1px;margin-top:-1px}.kint-rich ul.kint-tabs li,.kint-rich ul.kint-tabs li+li{margin:0 0 0 4px}.kint-rich ul.kint-tabs li{border-bottom-width:0;height:25px}.kint-rich ul.kint-tabs li:first-child{margin-left:0}.kint-rich ul.kint-tabs li.kint-active-tab{border-top:1px solid #d7d7d7;background:#fff;font-weight:bold;padding-top:0;border-bottom:1px solid #fff !important;margin-bottom:-1px}.kint-rich ul.kint-tabs li.kint-active-tab:hover{border-bottom:1px solid #fff}.kint-rich ul>li>pre{border:1px solid #d7d7d7}.kint-rich dt:hover+dd>ul{border-color:#aaa}.kint-rich pre{background:#fff;margin-top:4px;margin-left:25px}.kint-rich .kint-source{margin-left:-1px}.kint-rich .kint-source .kint-highlight{background:#cfc}.kint-rich .kint-parent.kint-show>.kint-search{border-bottom-width:1px}.kint-rich table td{background:#fff}.kint-rich table td>dl{padding:0;margin:0}.kint-rich table td>dl>dt.kint-parent{margin:0}.kint-rich table td:first-child,.kint-rich table td,.kint-rich table th{padding:2px 4px}.kint-rich table dd,.kint-rich table dt{background:#fff}.kint-rich table tr:hover>td{box-shadow:none;background:#cfc} diff --git a/system/ThirdParty/Kint/resources/compiled/microtime.js b/system/ThirdParty/Kint/resources/compiled/microtime.js index 20e3445b2b05..c9b8f00a58d7 100644 --- a/system/ThirdParty/Kint/resources/compiled/microtime.js +++ b/system/ThirdParty/Kint/resources/compiled/microtime.js @@ -1 +1 @@ -void 0===window.kintMicrotimeInitialized&&(window.kintMicrotimeInitialized=1,window.addEventListener("load",function(){"use strict";var c={},i=Array.prototype.slice.call(document.querySelectorAll("[data-kint-microtime-group]"),0);i.forEach(function(i){if(i.querySelector(".kint-microtime-lap")){var t=i.getAttribute("data-kint-microtime-group"),e=parseFloat(i.querySelector(".kint-microtime-lap").innerHTML),r=parseFloat(i.querySelector(".kint-microtime-avg").innerHTML);void 0===c[t]&&(c[t]={}),(void 0===c[t].min||c[t].min>e)&&(c[t].min=e),(void 0===c[t].max||c[t].maxe)&&(a[i].min=e),(void 0===a[i].max||a[i].maxdl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxnIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0iI0ZGRiI+PHBhdGggZD0iTTEgMWgyOHYyOEgxem01IDE0aDE4bS05IDlWNk0xIDYxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzM3OSIvPjxwYXRoIGQ9Ik0xIDMxaDI4djI4SDF6bTUgMTRoMThtLTkgOVYzNk0xIDkxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzVBMyIvPjxwYXRoIGQ9Ik0xIDEyMWgyOHYyOEgxem01IDVsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZT0iI0NDQyIvPjwvZz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #b6cedb}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#0092db;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#5cb730}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#e0eaef;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#e0eaef}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #b6cedb;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#c1d4df;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#d0d0d0;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#e8e8e8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#c1d4df;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #b6cedb}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}.kint-rich ul.kint-tabs>li{background:#c1d4df;border:1px solid #b6cedb;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#0092db;color:#5cb730}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#e0eaef;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#0092db;color:#5cb730}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #b6cedb;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#0092db}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #b6cedb;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#c1d4df;color:#1d1e1e}.kint-rich table td{background:#e0eaef;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}.kint-rich table tr:hover var{color:#5cb730}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #c1d4df}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #0092db;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#c1d4df}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #0092db,0 1px #0092db,1px 0 #0092db,0 -1px #0092db;color:#e0eaef;font-weight:bold}.kint-rich>dl>dt{background:linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%)}.kint-rich ul.kint-tabs{background:linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%)}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li{background:#e0eaef}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li.kint-active-tab{background:#c1d4df}.kint-rich>dl.kint-trace>dt{background:linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%)}.kint-rich .kint-source .kint-highlight{background:#f0eb96} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:8px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#0092db;color:#1d1e1e}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #5cb730}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:8px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#e0eaef;border:1px solid #b6cedb;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#0092db}.kint-rich>dl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxnIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0iI0ZGRiI+PHBhdGggZD0iTTEgMWgyOHYyOEgxem01IDE0aDE4bS05IDlWNk0xIDYxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzM3OSIvPjxwYXRoIGQ9Ik0xIDMxaDI4djI4SDF6bTUgMTRoMThtLTkgOVYzNk0xIDkxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzVBMyIvPjxwYXRoIGQ9Ik0xIDEyMWgyOHYyOEgxem01IDVsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZT0iI0NDQyIvPjwvZz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #b6cedb}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#0092db;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#5cb730}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#e0eaef;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#e0eaef}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #b6cedb;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#c1d4df;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#d0d0d0;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#e8e8e8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#c1d4df;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #b6cedb}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}.kint-rich ul.kint-tabs>li{background:#c1d4df;border:1px solid #b6cedb;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#0092db;color:#5cb730}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#e0eaef;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#0092db;color:#5cb730}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #b6cedb;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#0092db}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #b6cedb;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#c1d4df;color:#1d1e1e}.kint-rich table td{background:#e0eaef;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}.kint-rich table tr:hover var{color:#5cb730}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #c1d4df}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #0092db;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#c1d4df}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #0092db,0 1px #0092db,1px 0 #0092db,0 -1px #0092db;color:#e0eaef;font-weight:bold}.kint-rich>dl>dt{background:linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%)}.kint-rich ul.kint-tabs{background:linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%)}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li{background:#e0eaef}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li.kint-active-tab{background:#c1d4df}.kint-rich>dl.kint-trace>dt{background:linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%)}.kint-rich .kint-source .kint-highlight{background:#f0eb96} diff --git a/system/ThirdParty/Kint/resources/compiled/rich.js b/system/ThirdParty/Kint/resources/compiled/rich.js index 18fb072ead95..5648cda6de9e 100644 --- a/system/ThirdParty/Kint/resources/compiled/rich.js +++ b/system/ThirdParty/Kint/resources/compiled/rich.js @@ -1 +1 @@ -void 0===window.kintRich&&(window.kintRich=function(){"use strict";var n={selectText:function(e){var t=window.getSelection(),a=document.createRange();a.selectNodeContents(e),t.removeAllRanges(),t.addRange(a)},each:function(e,t){Array.prototype.slice.call(document.querySelectorAll(e),0).forEach(t)},hasClass:function(e,t){return!!e.classList&&(void 0===t&&(t="kint-show"),e.classList.contains(t))},addClass:function(e,t){void 0===t&&(t="kint-show"),e.classList.add(t)},removeClass:function(e,t){return void 0===t&&(t="kint-show"),e.classList.remove(t),e},toggle:function(e,t){var a=n.getChildren(e);a&&(void 0===t&&(t=n.hasClass(e)),t?n.removeClass(e):n.addClass(e),1===a.childNodes.length&&(a=a.childNodes[0].childNodes[0])&&n.hasClass(a,"kint-parent")&&n.toggle(a,t))},toggleChildren:function(e,t){var a=n.getChildren(e);if(a){var r=a.getElementsByClassName("kint-parent"),o=r.length;for(void 0===t&&(t=!n.hasClass(e));o--;)n.toggle(r[o],t)}},toggleAll:function(e){for(var t=document.getElementsByClassName("kint-parent"),a=t.length,r=!n.hasClass(e.parentNode);a--;)n.toggle(t[a],r)},switchTab:function(e){var t,a=e.previousSibling,r=0;for(n.removeClass(e.parentNode.getElementsByClassName("kint-active-tab")[0],"kint-active-tab"),n.addClass(e,"kint-active-tab");a;)1===a.nodeType&&r++,a=a.previousSibling;t=e.parentNode.nextSibling.childNodes;for(var o=0;o"},openInNewWindow:function(e){var t=window.open();t&&(t.document.open(),t.document.write(n.mktag("html")+n.mktag("head")+n.mktag("title")+"Kint ("+(new Date).toISOString()+")"+n.mktag("/title")+n.mktag('meta charset="utf-8"')+document.getElementsByClassName("kint-rich-script")[0].outerHTML+document.getElementsByClassName("kint-rich-style")[0].outerHTML+n.mktag("/head")+n.mktag("body")+'
    '+e.parentNode.outerHTML+"
    "+n.mktag("/body")),t.document.close())},sortTable:function(e,a){var t=e.tBodies[0];[].slice.call(e.tBodies[0].rows).sort(function(e,t){if(e=e.cells[a].textContent.trim().toLocaleLowerCase(),t=t.cells[a].textContent.trim().toLocaleLowerCase(),isNaN(e)||isNaN(t)){if(isNaN(e)&&!isNaN(t))return 1;if(isNaN(t)&&!isNaN(e))return-1}else e=parseFloat(e),t=parseFloat(t);return eli:not(.kint-active-tab)",function(e){0===e.offsetWidth&&0===e.offsetHeight||n.keyboardNav.targets.push(e)})},sync:function(e){var t=document.querySelector(".kint-focused");if(t&&n.removeClass(t,"kint-focused"),n.keyboardNav.active){var a=n.keyboardNav.targets[n.keyboardNav.target];n.addClass(a,"kint-focused"),e||n.keyboardNav.scroll(a)}},scroll:function(e){var t=function(e){return e.offsetTop+(e.offsetParent?t(e.offsetParent):0)},a=t(e);if(n.folder){var r=n.folder.querySelector("dd.kint-folder");r.scrollTo(0,a-r.clientHeight/2)}else window.scrollTo(0,a-window.innerHeight/2)},moveCursor:function(e){for(n.keyboardNav.target+=e;n.keyboardNav.target<0;)n.keyboardNav.target+=n.keyboardNav.targets.length;for(;n.keyboardNav.target>=n.keyboardNav.targets.length;)n.keyboardNav.target-=n.keyboardNav.targets.length;n.keyboardNav.sync()},setCursor:function(e){n.keyboardNav.fetchTargets();for(var t=0;t"},openInNewWindow:function(e){var t=window.open();t&&(t.document.open(),t.document.write(i.mktag("html")+i.mktag("head")+i.mktag("title")+"Kint ("+(new Date).toISOString()+")"+i.mktag("/title")+i.mktag('meta charset="utf-8"')+document.getElementsByClassName("kint-rich-script")[0].outerHTML+document.getElementsByClassName("kint-rich-style")[0].outerHTML+i.mktag("/head")+i.mktag("body")+'
    '+e.parentNode.outerHTML+"
    "+i.mktag("/body")),t.document.close())},sortTable:function(e,a){var t=e.tBodies[0];[].slice.call(e.tBodies[0].rows).sort(function(e,t){if(e=e.cells[a].textContent.trim().toLocaleLowerCase(),t=t.cells[a].textContent.trim().toLocaleLowerCase(),isNaN(e)||isNaN(t)){if(isNaN(e)&&!isNaN(t))return 1;if(isNaN(t)&&!isNaN(e))return-1}else e=parseFloat(e),t=parseFloat(t);return eli:not(.kint-active-tab)",function(e){i.isFolderOpen()&&!i.folder.contains(e)||0===e.offsetWidth&&0===e.offsetHeight||i.keyboardNav.targets.push(e)}),e&&-1!==i.keyboardNav.targets.indexOf(e)&&(i.keyboardNav.target=i.keyboardNav.targets.indexOf(e))},sync:function(e){var t=document.querySelector(".kint-focused");t&&i.removeClass(t,"kint-focused"),i.keyboardNav.active&&(t=i.keyboardNav.targets[i.keyboardNav.target],i.addClass(t,"kint-focused"),e||i.keyboardNav.scroll(t))},scroll:function(e){var t,a;e!==i.folder.querySelector("dt > nav")&&(a=(t=function(e){return e.offsetTop+(e.offsetParent?t(e.offsetParent):0)})(e),i.isFolderOpen()?(e=i.folder.querySelector("dd.kint-foldout")).scrollTo(0,a-e.clientHeight/2):window.scrollTo(0,a-window.innerHeight/2))},moveCursor:function(e){for(i.keyboardNav.target+=e;i.keyboardNav.target<0;)i.keyboardNav.target+=i.keyboardNav.targets.length;for(;i.keyboardNav.target>=i.keyboardNav.targets.length;)i.keyboardNav.target-=i.keyboardNav.targets.length;i.keyboardNav.sync()},setCursor:function(e){if(i.isFolderOpen()&&!i.folder.contains(e))return!1;i.keyboardNav.fetchTargets();for(var t=0;tdl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #586e75}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint-rich pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(131,148,150,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#002b36;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#839496;background:#002b36}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #586e75;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#93a1a1;background:#073642;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#252525;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#1b1b1b}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#073642;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#839496}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#839496;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #586e75}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint-rich ul.kint-tabs>li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #586e75;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #586e75;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#073642;color:#93a1a1}.kint-rich table td{background:#002b36;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #073642}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#073642}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#002b36;font-weight:bold}body{background:#073642;color:#fff}.kint-rich{box-shadow:0 0 5px 3px #073642}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}.kint-rich footer li{color:#ddd} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:#073642}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#839496}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#839496;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#002b36;border:1px solid #586e75;color:#839496;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #586e75}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint-rich pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(131,148,150,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#002b36;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#839496;background:#002b36}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #586e75;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#93a1a1;background:#073642;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#252525;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#1b1b1b}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#073642;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#839496}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#839496;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #586e75}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint-rich ul.kint-tabs>li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #586e75;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #586e75;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#073642;color:#93a1a1}.kint-rich table td{background:#002b36;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #073642}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#073642}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#002b36;font-weight:bold}body{background:#073642;color:#fff}.kint-rich{box-shadow:0 0 5px 3px #073642}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}.kint-rich footer li{color:#ddd} diff --git a/system/ThirdParty/Kint/resources/compiled/solarized.css b/system/ThirdParty/Kint/resources/compiled/solarized.css index db5da0d2d3b7..fa04f2de8f4d 100644 --- a/system/ThirdParty/Kint/resources/compiled/solarized.css +++ b/system/ThirdParty/Kint/resources/compiled/solarized.css @@ -1 +1 @@ -.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:none}.kint-rich.kint-folder.kint-show{display:block}.kint-rich.kint-folder dd.kint-folder{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#657b83}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#657b83;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #93a1a1}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#586e75}.kint-rich pre{color:#657b83;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(101,123,131,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#fdf6e3;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#657b83;background:#fdf6e3}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #93a1a1;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#586e75;background:#eee8d5;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#e2e2e2;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f0f0f0}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#eee8d5;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#657b83}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#657b83;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#586e75;border-bottom:1px dotted #586e75}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #93a1a1}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}.kint-rich ul.kint-tabs>li{background:#eee8d5;border:1px solid #93a1a1;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#fdf6e3;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #93a1a1;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #93a1a1;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#eee8d5;color:#586e75}.kint-rich table td{background:#fdf6e3;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #eee8d5}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#eee8d5}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#fdf6e3;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#657b83}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#657b83;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #93a1a1}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#586e75}.kint-rich pre{color:#657b83;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(101,123,131,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#fdf6e3;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#657b83;background:#fdf6e3}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #93a1a1;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#586e75;background:#eee8d5;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#e2e2e2;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f0f0f0}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#eee8d5;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#657b83}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#657b83;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#586e75;border-bottom:1px dotted #586e75}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #93a1a1}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}.kint-rich ul.kint-tabs>li{background:#eee8d5;border:1px solid #93a1a1;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#fdf6e3;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #93a1a1;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #93a1a1;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#eee8d5;color:#586e75}.kint-rich table td{background:#fdf6e3;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #eee8d5}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#eee8d5}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#fdf6e3;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px} From d542514edb6c05b6fbc6a9039de5dce9d4f84ca8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 19 Dec 2021 16:28:11 +0900 Subject: [PATCH 371/407] chore: rename changed property names in Kint --- system/CodeIgniter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 41e775dbf58d..d309ca81c27a 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -249,7 +249,7 @@ protected function initializeKint() */ $config = config('Config\Kint'); - Kint::$max_depth = $config->maxDepth; + Kint::$depth_limit = $config->maxDepth; Kint::$display_called_from = $config->displayCalledFrom; Kint::$expanded = $config->expanded; @@ -261,7 +261,7 @@ protected function initializeKint() RichRenderer::$folder = $config->richFolder; RichRenderer::$sort = $config->richSort; if (! empty($config->richObjectPlugins) && is_array($config->richObjectPlugins)) { - RichRenderer::$object_plugins = $config->richObjectPlugins; + RichRenderer::$value_plugins = $config->richObjectPlugins; } if (! empty($config->richTabPlugins) && is_array($config->richTabPlugins)) { RichRenderer::$tab_plugins = $config->richTabPlugins; From 67ce1b025511a16271caea5dbb37058f9aab190f Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 19 Dec 2021 21:40:46 +0900 Subject: [PATCH 372/407] docs: fix by proof reading Co-authored-by: MGatner --- user_guide_src/source/incoming/filters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index b8b16bb1c9ce..8677f1925dee 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -207,7 +207,7 @@ The filters bundled with CodeIgniter4 are: :doc:`Honeypot <../libraries/honeypot InvalidChars ============= -This filter checks if user input data (``$_GET``, ``$_POST``, ``$_COOKIE``, ``php://input``) do not contain the following characters: +This filter prohibits user input data (``$_GET``, ``$_POST``, ``$_COOKIE``, ``php://input``) from containing the following characters: - invalid UTF-8 characters - control characters except line break and tab code From 37fe5bb223faa6303c14303023fe9bbf53d21de3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 20 Dec 2021 13:48:34 +0900 Subject: [PATCH 373/407] docs: fix incorrect sample code --- user_guide_src/source/general/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/logging.rst b/user_guide_src/source/general/logging.rst index 761500ac722a..08e60d60988c 100644 --- a/user_guide_src/source/general/logging.rst +++ b/user_guide_src/source/general/logging.rst @@ -97,7 +97,7 @@ into the message string:: // Generates a message like: User 123 logged into the system from 127.0.0.1 $info = [ 'id' => $user->id, - 'ip_address' => $this->request->ip_address() + 'ip_address' => $this->request->getIPAddress() ]; log_message('info', 'User {id} logged into the system from {ip_address}', $info); From a2df301abae87d308c4c501f4c65b1b06f50f612 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 20 Dec 2021 17:30:24 +0900 Subject: [PATCH 374/407] docs: change text decoration --- user_guide_src/source/general/environments.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/environments.rst b/user_guide_src/source/general/environments.rst index 6abd709a00a9..ae9c877c81fd 100644 --- a/user_guide_src/source/general/environments.rst +++ b/user_guide_src/source/general/environments.rst @@ -99,7 +99,7 @@ Error Reporting Setting the ENVIRONMENT constant to a value of ``development`` will cause all PHP errors to be rendered to the browser when they occur. -Conversely, setting the constant to 'production' will disable all error +Conversely, setting the constant to ``production`` will disable all error output. Disabling error reporting in production is a :doc:`good security practice `. From 499f4a031f7ba8a076afa58a0f8b3b3c86d80283 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 21 Dec 2021 16:36:32 +0900 Subject: [PATCH 375/407] test: fix doc comment --- tests/system/API/ResponseTraitTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/system/API/ResponseTraitTest.php b/tests/system/API/ResponseTraitTest.php index 1db28686eafe..abff4ce0c1a9 100644 --- a/tests/system/API/ResponseTraitTest.php +++ b/tests/system/API/ResponseTraitTest.php @@ -11,6 +11,7 @@ namespace CodeIgniter\API; +use CodeIgniter\Format\FormatterInterface; use CodeIgniter\Format\JSONFormatter; use CodeIgniter\Format\XMLFormatter; use CodeIgniter\HTTP\URI; @@ -30,7 +31,7 @@ final class ResponseTraitTest extends CIUnitTestCase protected $response; /** - * @var Response formatter + * @var FormatterInterface|null */ protected $formatter; From b75b9aff45d381e134348cc29eadc49051f98bf7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 21 Dec 2021 17:38:19 +0900 Subject: [PATCH 376/407] docs: depreacted Seeder::faker() See #5456 --- system/Database/Seeder.php | 4 +++ tests/system/Database/DatabaseSeederTest.php | 3 ++ user_guide_src/source/changelogs/v4.1.6.rst | 2 ++ user_guide_src/source/dbmgmt/seeds.rst | 35 -------------------- 4 files changed, 9 insertions(+), 35 deletions(-) diff --git a/system/Database/Seeder.php b/system/Database/Seeder.php index b6127af2cd91..92d281965c7e 100644 --- a/system/Database/Seeder.php +++ b/system/Database/Seeder.php @@ -68,6 +68,8 @@ class Seeder * Faker Generator instance. * * @var Generator|null + * + * @deprecated */ private static $faker; @@ -98,6 +100,8 @@ public function __construct(Database $config, ?BaseConnection $db = null) /** * Gets the Faker Generator instance. + * + * @deprecated */ public static function faker(): ?Generator { diff --git a/tests/system/Database/DatabaseSeederTest.php b/tests/system/Database/DatabaseSeederTest.php index d17ff71fe61a..7e08d6648508 100644 --- a/tests/system/Database/DatabaseSeederTest.php +++ b/tests/system/Database/DatabaseSeederTest.php @@ -38,6 +38,9 @@ public function testInstantiateNotDirSeedPath() new Seeder($config); } + /** + * @TODO remove this when Seeder::faker() is removed + */ public function testFakerGet() { $this->assertInstanceOf(Generator::class, Seeder::faker()); diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 82b03127cda2..d53378a6b624 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -42,6 +42,8 @@ Changes Deprecations ************ +- ``Seeder::faker()`` and ``Seeder::$faker`` are deprecated. + Sending Cookies =============== diff --git a/user_guide_src/source/dbmgmt/seeds.rst b/user_guide_src/source/dbmgmt/seeds.rst index 95afc23104b7..e79496efbffb 100644 --- a/user_guide_src/source/dbmgmt/seeds.rst +++ b/user_guide_src/source/dbmgmt/seeds.rst @@ -67,41 +67,6 @@ anywhere the autoloader can find them. This is great for more modular code bases $this->call('My\Database\Seeds\CountrySeeder'); } -Using Faker -=========== - -If you want to automate the generation of seed data, you can use -the `Faker library `_. - -To install Faker into your project:: - - > composer require --dev fakerphp/faker - -After installation, an instance of ``Faker\Generator`` is available in the main ``Seeder`` -class and is accessible by all child seeders. You must use the static method ``faker()`` -to access the instance. - -:: - - insert([ - 'email' => static::faker()->email, - 'ip_address' => static::faker()->ipv4, - ]); - } - } - Using Seeders ============= From 2591d65c091f8f5b95353bc2ed82cd5f2e0e9d7a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 21 Dec 2021 19:48:22 +0900 Subject: [PATCH 377/407] docs: fix sample code --- user_guide_src/source/extending/core_classes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/extending/core_classes.rst b/user_guide_src/source/extending/core_classes.rst index a51c9e825b34..9ef3330e23bc 100644 --- a/user_guide_src/source/extending/core_classes.rst +++ b/user_guide_src/source/extending/core_classes.rst @@ -68,7 +68,7 @@ Then you would add the ``routes`` service in **app/Config/Services.php** to load return static::getSharedInstance('routes'); } - return new RouteCollection(static::locator(), config('Modules')); + return new \App\Libraries\RouteCollection(static::locator(), config('Modules')); } Extending Core Classes From 39ce053fbb018b6afcb2d6aaffdb0df61a616832 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 22 Dec 2021 09:08:13 +0900 Subject: [PATCH 378/407] fix: directory_mirror() throws an error if destination directory exists Fixes #5478 --- system/Helpers/filesystem_helper.php | 4 ++- tests/system/Helpers/FilesystemHelperTest.php | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/system/Helpers/filesystem_helper.php b/system/Helpers/filesystem_helper.php index 52341b848e06..89d4d507f961 100644 --- a/system/Helpers/filesystem_helper.php +++ b/system/Helpers/filesystem_helper.php @@ -91,7 +91,9 @@ function directory_mirror(string $originDir, string $targetDir, bool $overwrite $target = $targetDir . substr($origin, $dirLen); if ($file->isDir()) { - mkdir($target, 0755); + if (! is_dir($target)) { + mkdir($target, 0755); + } } elseif (! is_file($target) || ($overwrite && is_file($target))) { copy($origin, $target); } diff --git a/tests/system/Helpers/FilesystemHelperTest.php b/tests/system/Helpers/FilesystemHelperTest.php index c48ccd1ff328..7b837064a410 100644 --- a/tests/system/Helpers/FilesystemHelperTest.php +++ b/tests/system/Helpers/FilesystemHelperTest.php @@ -14,6 +14,7 @@ use CodeIgniter\Test\CIUnitTestCase; use InvalidArgumentException; use org\bovigo\vfs\vfsStream; +use org\bovigo\vfs\visitor\vfsStreamStructureVisitor; /** * @internal @@ -161,6 +162,34 @@ public function testDirectoryMirrorNotOverwrites() $this->assertSame($this->structure['boo']['faz'], $result); } + public function testDirectoryMirrorSkipExistingFolder() + { + $this->assertTrue(function_exists('directory_mirror')); + + $this->structure = [ + 'src' => [ + 'AnEmptyFolder' => [], + ], + 'dest' => [ + 'AnEmptyFolder' => [], + ], + ]; + vfsStream::setup('root', null, $this->structure); + $root = rtrim(vfsStream::url('root') . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + + // skips the existing folder + directory_mirror($root . 'src', $root . 'dest'); + + $structure = vfsStream::inspect(new vfsStreamStructureVisitor())->getStructure(); + $this->assertSame([], $structure['root']['dest']['AnEmptyFolder']); + + // skips the existing folder (the same as overwrite = true) + directory_mirror($root . 'src', $root . 'dest', false); + + $structure = vfsStream::inspect(new vfsStreamStructureVisitor())->getStructure(); + $this->assertSame([], $structure['root']['dest']['AnEmptyFolder']); + } + public function testWriteFileSuccess() { $vfs = vfsStream::setup('root'); From 66bc13d94c5f6a3d18af620bc650db4f37b63576 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 22 Dec 2021 08:47:05 +0700 Subject: [PATCH 379/407] Update rector to 0.12.9 and clean up skip config --- composer.json | 2 +- rector.php | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 330209cb21a6..984520972a46 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.12.8" + "rector/rector": "0.12.9" }, "suggest": { "ext-fileinfo": "Improves mime type detection for files" diff --git a/rector.php b/rector.php index 92636b0bfdd5..8be24cd7024d 100644 --- a/rector.php +++ b/rector.php @@ -42,7 +42,6 @@ use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; -use Rector\PHPUnit\Rector\MethodCall\AssertIssetToSpecificMethodRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\LevelSetList; use Rector\Set\ValueObject\SetList; @@ -113,15 +112,6 @@ // use mt_rand instead of random_int on purpose on non-cryptographically random RandomFunctionRector::class, - - // $this->assertTrue(isset($bar['foo'])) - // and $this->assertArrayHasKey('foo', $bar) - // or $this->assertObjectHasAttribute('foo', $bar); - // are not the same - AssertIssetToSpecificMethodRector::class => [ - __DIR__ . '/tests/system/Entity/EntityTest.php', - __DIR__ . '/tests/system/Session/SessionTest.php', - ], ]); // auto import fully qualified class names From f7151ab591ef36055aee25cae7082b191ae24c14 Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Mon, 20 Dec 2021 17:51:36 +0800 Subject: [PATCH 380/407] BaseBuilder instance as subquery. --- system/Database/BaseBuilder.php | 58 ++++++++---- tests/system/Database/Builder/WhereTest.php | 81 ++++++++++++++-- .../source/database/query_builder.rst | 94 ++++++++++++++----- 3 files changed, 182 insertions(+), 51 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index fecf3e10718f..6d97db101cbb 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -693,9 +693,8 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $op = ' ='; } - if ($v instanceof Closure) { - $builder = $this->cleanClone(); - $v = ' (' . strtr($v($builder)->getCompiledSelect(), "\n", ' ') . ')'; + if ($this->isSubQuery($v)) { + $v = $this->buildSubQuery($v, true); } else { $bind = $this->setBind($k, $v, $escape); $v = " :{$bind}:"; @@ -723,7 +722,7 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type * Generates a WHERE field IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -736,7 +735,7 @@ public function whereIn(?string $key = null, $values = null, ?bool $escape = nul * Generates a WHERE field IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -749,7 +748,7 @@ public function orWhereIn(?string $key = null, $values = null, ?bool $escape = n * Generates a WHERE field NOT IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -762,7 +761,7 @@ public function whereNotIn(?string $key = null, $values = null, ?bool $escape = * Generates a WHERE field NOT IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -775,7 +774,7 @@ public function orWhereNotIn(?string $key = null, $values = null, ?bool $escape * Generates a HAVING field IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -788,7 +787,7 @@ public function havingIn(?string $key = null, $values = null, ?bool $escape = nu * Generates a HAVING field IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -801,7 +800,7 @@ public function orHavingIn(?string $key = null, $values = null, ?bool $escape = * Generates a HAVING field NOT IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -814,7 +813,7 @@ public function havingNotIn(?string $key = null, $values = null, ?bool $escape = * Generates a HAVING field NOT IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -829,7 +828,7 @@ public function orHavingNotIn(?string $key = null, $values = null, ?bool $escape * @used-by whereNotIn() * @used-by orWhereNotIn() * - * @param array|Closure|null $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|null $values The values searched on, or anonymous function with subquery * * @throws InvalidArgumentException * @@ -845,7 +844,7 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal return $this; // @codeCoverageIgnore } - if ($values === null || (! is_array($values) && ! ($values instanceof Closure))) { + if ($values === null || (! is_array($values) && ! $this->isSubQuery($values))) { if (CI_DEBUG) { throw new InvalidArgumentException(sprintf('%s() expects $values to be of type array or closure', debug_backtrace(0, 2)[1]['function'])); } @@ -865,9 +864,8 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal $not = ($not) ? ' NOT' : ''; - if ($values instanceof Closure) { - $builder = $this->cleanClone(); - $ok = strtr($values($builder)->getCompiledSelect(), "\n", ' '); + if ($this->isSubQuery($values)) { + $ok = $this->buildSubQuery($values); } else { $whereIn = array_values($values); $ok = $this->setBind($ok, $whereIn, $escape); @@ -876,7 +874,7 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal $prefix = empty($this->{$clause}) ? $this->groupGetType('') : $this->groupGetType($type); $whereIn = [ - 'condition' => $prefix . $key . $not . ($values instanceof Closure ? " IN ({$ok})" : " IN :{$ok}:"), + 'condition' => $prefix . $key . $not . ($this->isSubQuery($values) ? " IN ({$ok})" : " IN :{$ok}:"), 'escape' => false, ]; @@ -2724,9 +2722,35 @@ protected function setBind(string $key, $value = null, bool $escape = true): str * Returns a clone of a Base Builder with reset query builder values. * * @return $this + * + * @deprecated */ protected function cleanClone() { return (clone $this)->from([], true)->resetQuery(); } + + /** + * @param mixed $value + */ + protected function isSubQuery($value): bool + { + return $value instanceof BaseBuilder || $value instanceof Closure; + } + + /** + * @param BaseBuilder|Closure $builder + * @param bool $wrapped Wrap the subquery in brackets + */ + protected function buildSubQuery($builder, bool $wrapped = false): string + { + if ($builder instanceof Closure) { + $instance = (clone $this)->from([], true)->resetQuery(); + $builder = $builder($instance); + } + + $subQuery = strtr($builder->getCompiledSelect(), "\n", ' '); + + return $wrapped ? '(' . $subQuery . ')' : $subQuery; + } } diff --git a/tests/system/Database/Builder/WhereTest.php b/tests/system/Database/Builder/WhereTest.php index e58af53cadab..70463776a3ac 100644 --- a/tests/system/Database/Builder/WhereTest.php +++ b/tests/system/Database/Builder/WhereTest.php @@ -141,14 +141,27 @@ public function testWhereCustomString() $this->assertSame($expectedBinds, $builder->getBinds()); } - public function testWhereValueClosure() + public function testWhereValueSubQuery() { + $expectedSQL = 'SELECT * FROM "neworder" WHERE "advance_amount" < (SELECT MAX(advance_amount) FROM "orders" WHERE "id" > 2)'; + + // Closure $builder = $this->db->table('neworder'); $builder->where('advance_amount <', static function (BaseBuilder $builder) { return $builder->select('MAX(advance_amount)', false)->from('orders')->where('id >', 2); }); - $expectedSQL = 'SELECT * FROM "neworder" WHERE "advance_amount" < (SELECT MAX(advance_amount) FROM "orders" WHERE "id" > 2)'; + + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); + + // Builder + $builder = $this->db->table('neworder'); + + $subQuery = $this->db->table('orders') + ->select('MAX(advance_amount)', false) + ->where('id >', 2); + + $builder->where('advance_amount <', $subQuery); $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); } @@ -218,15 +231,27 @@ public function testWhereIn() $this->assertSame($expectedBinds, $builder->getBinds()); } - public function testWhereInClosure() + public function testWhereInSubQuery() { + $expectedSQL = 'SELECT * FROM "jobs" WHERE "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + + // Closure $builder = $this->db->table('jobs'); $builder->whereIn('id', static function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); - $expectedSQL = 'SELECT * FROM "jobs" WHERE "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); + + // Builder + $builder = $this->db->table('jobs'); + + $subQuery = $this->db->table('users_jobs') + ->select('job_id') + ->where('user_id', 3); + + $builder->whereIn('id', $subQuery); $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); } @@ -295,15 +320,27 @@ public function testWhereNotIn() $this->assertSame($expectedBinds, $builder->getBinds()); } - public function testWhereNotInClosure() + public function testWhereNotInSubQuery() { + $expectedSQL = 'SELECT * FROM "jobs" WHERE "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + + // Closure $builder = $this->db->table('jobs'); $builder->whereNotIn('id', static function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); - $expectedSQL = 'SELECT * FROM "jobs" WHERE "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); + + // Builder + $builder = $this->db->table('jobs'); + + $subQuery = $this->db->table('users_jobs') + ->select('job_id') + ->where('user_id', 3); + + $builder->whereNotIn('id', $subQuery); $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); } @@ -333,15 +370,27 @@ public function testOrWhereIn() $this->assertSame($expectedBinds, $builder->getBinds()); } - public function testOrWhereInClosure() + public function testOrWhereInSubQuery() { + $expectedSQL = 'SELECT * FROM "jobs" WHERE "deleted_at" IS NULL OR "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + + // Closure $builder = $this->db->table('jobs'); $builder->where('deleted_at', null)->orWhereIn('id', static function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); - $expectedSQL = 'SELECT * FROM "jobs" WHERE "deleted_at" IS NULL OR "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); + + // Builder + $builder = $this->db->table('jobs'); + + $subQuery = $this->db->table('users_jobs') + ->select('job_id') + ->where('user_id', 3); + + $builder->where('deleted_at', null)->orWhereIn('id', $subQuery); $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); } @@ -371,15 +420,27 @@ public function testOrWhereNotIn() $this->assertSame($expectedBinds, $builder->getBinds()); } - public function testOrWhereNotInClosure() + public function testOrWhereNotInSubQuery() { + $expectedSQL = 'SELECT * FROM "jobs" WHERE "deleted_at" IS NULL OR "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + + // Closure $builder = $this->db->table('jobs'); $builder->where('deleted_at', null)->orWhereNotIn('id', static function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); - $expectedSQL = 'SELECT * FROM "jobs" WHERE "deleted_at" IS NULL OR "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3)'; + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); + + // Builder + $builder = $this->db->table('jobs'); + + $subQuery = $this->db->table('users_jobs') + ->select('job_id') + ->where('user_id', 3); + + $builder->where('deleted_at', null)->orWhereNotIn('id', $subQuery); $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect())); } diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index 7aa8cf69dcdb..63d9c25f501b 100755 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -306,13 +306,22 @@ methods: #. **Subqueries:** - You can use an anonymous function to create a subquery:: + :: + + // With closure $builder->where('advance_amount <', function (BaseBuilder $builder) { return $builder->select('MAX(advance_amount)', false)->from('orders')->where('id >', 2); }); + // Produces: WHERE "advance_amount" < (SELECT MAX(advance_amount) FROM "orders" WHERE "id" > 2) + // With builder directly + $subQuery = $db->table('orders')->select('MAX(advance_amount)', false)->where('id >', 2) + + $builder->where('advance_amount <', $subQuery); + + **$builder->orWhere()** This function is identical to the one above, except that multiple @@ -333,11 +342,17 @@ appropriate:: You can use subqueries instead of an array of values:: + // With closure $builder->whereIn('id', function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); // Produces: WHERE "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); + + $builder->whereIn('id', $subQuery); + **$builder->orWhereIn()** Generates a ``WHERE field IN ('item', 'item')`` SQL query joined with OR if @@ -349,12 +364,18 @@ appropriate:: You can use subqueries instead of an array of values:: + // With closure $builder->orWhereIn('id', function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); // Produces: OR "id" IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); + + $builder->orWhereIn('id', $subQuery); + **$builder->whereNotIn()** Generates a WHERE field NOT IN ('item', 'item') SQL query joined with @@ -366,12 +387,18 @@ AND if appropriate:: You can use subqueries instead of an array of values:: + // With closure $builder->whereNotIn('id', function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); // Produces: WHERE "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); + + $builder->whereNotIn('id', $subQuery); + **$builder->orWhereNotIn()** Generates a ``WHERE field NOT IN ('item', 'item')`` SQL query joined with OR @@ -383,12 +410,18 @@ if appropriate:: You can use subqueries instead of an array of values:: + // With closure $builder->orWhereNotIn('id', function (BaseBuilder $builder) { return $builder->select('job_id')->from('users_jobs')->where('user_id', 3); }); // Produces: OR "id" NOT IN (SELECT "job_id" FROM "users_jobs" WHERE "user_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); + + $builder->orWhereNotIn('id', $subQuery); + ************************ Looking for Similar Data ************************ @@ -512,23 +545,25 @@ Identical to ``having()``, only separates multiple clauses with "OR". **$builder->havingIn()** Generates a ``HAVING field IN ('item', 'item')`` SQL query joined with AND if -appropriate - -:: +appropriate:: $groups = [1, 2, 3]; $builder->havingIn('group_id', $groups); // Produces: HAVING group_id IN (1, 2, 3) -You can use subqueries instead of an array of values. - -:: +You can use subqueries instead of an array of values.:: + // With closure $builder->havingIn('id', function (BaseBuilder $builder) { return $builder->select('user_id')->from('users_jobs')->where('group_id', 3); }); // Produces: HAVING "id" IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); + + $builder->havingIn('id', $subQuery); + **$builder->orHavingIn()** Generates a ``HAVING field IN ('item', 'item')`` SQL query joined with OR if @@ -540,16 +575,20 @@ appropriate $builder->orHavingIn('group_id', $groups); // Produces: OR group_id IN (1, 2, 3) -You can use subqueries instead of an array of values. - -:: +You can use subqueries instead of an array of values.:: + //With closure $builder->orHavingIn('id', function (BaseBuilder $builder) { return $builder->select('user_id')->from('users_jobs')->where('group_id', 3); }); // Produces: OR "id" IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); + + $builder->orHavingIn('id', $subQuery); + **$builder->havingNotIn()** Generates a ``HAVING field NOT IN ('item', 'item')`` SQL query joined with @@ -561,16 +600,19 @@ AND if appropriate $builder->havingNotIn('group_id', $groups); // Produces: HAVING group_id NOT IN (1, 2, 3) -You can use subqueries instead of an array of values. - -:: +You can use subqueries instead of an array of values.:: + //With closure $builder->havingNotIn('id', function (BaseBuilder $builder) { return $builder->select('user_id')->from('users_jobs')->where('group_id', 3); }); // Produces: HAVING "id" NOT IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); + + $builder->havingNotIn('id', $subQuery); **$builder->orHavingNotIn()** @@ -583,16 +625,20 @@ if appropriate $builder->havingNotIn('group_id', $groups); // Produces: OR group_id NOT IN (1, 2, 3) -You can use subqueries instead of an array of values. - -:: +You can use subqueries instead of an array of values.:: + //With closure $builder->orHavingNotIn('id', function (BaseBuilder $builder) { return $builder->select('user_id')->from('users_jobs')->where('group_id', 3); }); // Produces: OR "id" NOT IN (SELECT "user_id" FROM "users_jobs" WHERE "group_id" = 3) + // With builder directly + $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); + + $builder->orHavingNotIn('id', $subQuery); + **$builder->havingLike()** This method enables you to generate **LIKE** clauses for HAVING part or the query, useful for doing @@ -1397,7 +1443,7 @@ Class Reference .. php:method:: orWhereIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: The field to search - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` @@ -1407,7 +1453,7 @@ Class Reference .. php:method:: orWhereNotIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: The field to search - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` @@ -1417,7 +1463,7 @@ Class Reference .. php:method:: whereIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: Name of field to examine - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` @@ -1427,7 +1473,7 @@ Class Reference .. php:method:: whereNotIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: Name of field to examine - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` @@ -1540,7 +1586,7 @@ Class Reference .. php:method:: orHavingIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: The field to search - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` @@ -1550,7 +1596,7 @@ Class Reference .. php:method:: orHavingNotIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: The field to search - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` @@ -1560,7 +1606,7 @@ Class Reference .. php:method:: havingIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: Name of field to examine - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` @@ -1570,7 +1616,7 @@ Class Reference .. php:method:: havingNotIn([$key = null[, $values = null[, $escape = null]]]) :param string $key: Name of field to examine - :param array|Closure $values: Array of target values, or anonymous function for subquery + :param array|BaseBulder|Closure $values: Array of target values, or anonymous function for subquery :param bool $escape: Whether to escape values and identifiers :param bool $insensitiveSearch: Whether to force a case-insensitive search :returns: ``BaseBuilder`` instance (method chaining) From d4fe9895d592c0a6a3da88132dea59a9c6d62686 Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Mon, 20 Dec 2021 18:10:03 +0800 Subject: [PATCH 381/407] Rename method --- system/Database/BaseBuilder.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 6d97db101cbb..a2a021ea9630 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -693,8 +693,8 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $op = ' ='; } - if ($this->isSubQuery($v)) { - $v = $this->buildSubQuery($v, true); + if ($this->isSubquery($v)) { + $v = $this->buildSubquery($v, true); } else { $bind = $this->setBind($k, $v, $escape); $v = " :{$bind}:"; @@ -844,7 +844,7 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal return $this; // @codeCoverageIgnore } - if ($values === null || (! is_array($values) && ! $this->isSubQuery($values))) { + if ($values === null || (! is_array($values) && ! $this->isSubquery($values))) { if (CI_DEBUG) { throw new InvalidArgumentException(sprintf('%s() expects $values to be of type array or closure', debug_backtrace(0, 2)[1]['function'])); } @@ -864,8 +864,8 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal $not = ($not) ? ' NOT' : ''; - if ($this->isSubQuery($values)) { - $ok = $this->buildSubQuery($values); + if ($this->isSubquery($values)) { + $ok = $this->buildSubquery($values); } else { $whereIn = array_values($values); $ok = $this->setBind($ok, $whereIn, $escape); @@ -874,7 +874,7 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal $prefix = empty($this->{$clause}) ? $this->groupGetType('') : $this->groupGetType($type); $whereIn = [ - 'condition' => $prefix . $key . $not . ($this->isSubQuery($values) ? " IN ({$ok})" : " IN :{$ok}:"), + 'condition' => $prefix . $key . $not . ($this->isSubquery($values) ? " IN ({$ok})" : " IN :{$ok}:"), 'escape' => false, ]; @@ -2733,7 +2733,7 @@ protected function cleanClone() /** * @param mixed $value */ - protected function isSubQuery($value): bool + protected function isSubquery($value): bool { return $value instanceof BaseBuilder || $value instanceof Closure; } @@ -2742,15 +2742,15 @@ protected function isSubQuery($value): bool * @param BaseBuilder|Closure $builder * @param bool $wrapped Wrap the subquery in brackets */ - protected function buildSubQuery($builder, bool $wrapped = false): string + protected function buildSubquery($builder, bool $wrapped = false): string { if ($builder instanceof Closure) { $instance = (clone $this)->from([], true)->resetQuery(); $builder = $builder($instance); } - $subQuery = strtr($builder->getCompiledSelect(), "\n", ' '); + $subquery = strtr($builder->getCompiledSelect(), "\n", ' '); - return $wrapped ? '(' . $subQuery . ')' : $subQuery; + return $wrapped ? '(' . $subquery . ')' : $subquery; } } From 2aa2de794ea6039d0fd237e24da61bab85cb1fe5 Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Thu, 23 Dec 2021 12:58:19 +0800 Subject: [PATCH 382/407] Changelog and fix doc --- user_guide_src/source/changelogs/v4.1.6.rst | 2 ++ user_guide_src/source/database/query_builder.rst | 11 +---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index d53378a6b624..09cd48ceae80 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -33,6 +33,7 @@ Enhancements ************ - Database pane on debug toolbar now displays location where Query was called from. Also displays full backtrace. +- :ref:`Subqueries` in QueryBuilder can now be an instance of the BaseBuilder class. Changes ******* @@ -43,6 +44,7 @@ Deprecations ************ - ``Seeder::faker()`` and ``Seeder::$faker`` are deprecated. +- ``BaseBuilder::cleanClone()`` is deprecated. Sending Cookies =============== diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index 63d9c25f501b..4d0fd69ce2f9 100755 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -304,6 +304,7 @@ methods: $where = "name={$name} AND status='boss' OR status='active'"; $builder->where($where); +.. _query-builder-where-subquery: #. **Subqueries:** :: @@ -318,10 +319,8 @@ methods: // With builder directly $subQuery = $db->table('orders')->select('MAX(advance_amount)', false)->where('id >', 2) - $builder->where('advance_amount <', $subQuery); - **$builder->orWhere()** This function is identical to the one above, except that multiple @@ -350,7 +349,6 @@ You can use subqueries instead of an array of values:: // With builder directly $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); - $builder->whereIn('id', $subQuery); **$builder->orWhereIn()** @@ -373,7 +371,6 @@ You can use subqueries instead of an array of values:: // With builder directly $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); - $builder->orWhereIn('id', $subQuery); **$builder->whereNotIn()** @@ -396,7 +393,6 @@ You can use subqueries instead of an array of values:: // With builder directly $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); - $builder->whereNotIn('id', $subQuery); **$builder->orWhereNotIn()** @@ -419,7 +415,6 @@ You can use subqueries instead of an array of values:: // With builder directly $subQuery = $db->table('users_jobs')->select('job_id')->where('user_id', 3); - $builder->orWhereNotIn('id', $subQuery); ************************ @@ -561,7 +556,6 @@ You can use subqueries instead of an array of values.:: // With builder directly $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); - $builder->havingIn('id', $subQuery); **$builder->orHavingIn()** @@ -586,7 +580,6 @@ You can use subqueries instead of an array of values.:: // With builder directly $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); - $builder->orHavingIn('id', $subQuery); **$builder->havingNotIn()** @@ -611,7 +604,6 @@ You can use subqueries instead of an array of values.:: // With builder directly $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); - $builder->havingNotIn('id', $subQuery); **$builder->orHavingNotIn()** @@ -636,7 +628,6 @@ You can use subqueries instead of an array of values.:: // With builder directly $subQuery = $db->table('users_jobs')->select('user_id')->where('group_id', 3); - $builder->orHavingNotIn('id', $subQuery); **$builder->havingLike()** From fbaab7705a64448bc973c3cfefc7f408d9c07914 Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Thu, 23 Dec 2021 15:14:41 +0800 Subject: [PATCH 383/407] Update user_guide_src/source/changelogs/v4.1.6.rst Co-authored-by: kenjis --- user_guide_src/source/changelogs/v4.1.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/changelogs/v4.1.6.rst b/user_guide_src/source/changelogs/v4.1.6.rst index 09cd48ceae80..61214596ea97 100644 --- a/user_guide_src/source/changelogs/v4.1.6.rst +++ b/user_guide_src/source/changelogs/v4.1.6.rst @@ -33,7 +33,7 @@ Enhancements ************ - Database pane on debug toolbar now displays location where Query was called from. Also displays full backtrace. -- :ref:`Subqueries` in QueryBuilder can now be an instance of the BaseBuilder class. +- :ref:`Subqueries ` in QueryBuilder can now be an instance of the BaseBuilder class. Changes ******* From 5eb8c822c64c0f1500d40bfaeb9542c85567d53c Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Thu, 23 Dec 2021 15:14:51 +0800 Subject: [PATCH 384/407] Update user_guide_src/source/database/query_builder.rst Co-authored-by: kenjis --- user_guide_src/source/database/query_builder.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index 4d0fd69ce2f9..2c85a58e63e6 100755 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -305,6 +305,7 @@ methods: $builder->where($where); .. _query-builder-where-subquery: + #. **Subqueries:** :: From 864d366c87ab432a2a97ad92dd32603ea14a71ae Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Fri, 24 Dec 2021 09:45:58 +0800 Subject: [PATCH 385/407] Excluding a condition from a query string. --- system/Database/BaseBuilder.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index a2a021ea9630..2a431accd2f5 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -865,16 +865,18 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal $not = ($not) ? ' NOT' : ''; if ($this->isSubquery($values)) { - $ok = $this->buildSubquery($values); + $whereIn = $this->buildSubquery($values, true); + $escape = false; } else { $whereIn = array_values($values); - $ok = $this->setBind($ok, $whereIn, $escape); } + $ok = $this->setBind($ok, $whereIn, $escape); + $prefix = empty($this->{$clause}) ? $this->groupGetType('') : $this->groupGetType($type); $whereIn = [ - 'condition' => $prefix . $key . $not . ($this->isSubquery($values) ? " IN ({$ok})" : " IN :{$ok}:"), + 'condition' => "{$prefix}{$key}{$not} IN :{$ok}:", 'escape' => false, ]; From 70625366ae5fa901bc901c435903b008c417353f Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Dec 2021 11:57:59 +0900 Subject: [PATCH 386/407] fix: KINT visual error when activating CSP --- rector.php | 1 + system/CodeIgniter.php | 4 +- system/Debug/Kint/RichRenderer.php | 75 ++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 system/Debug/Kint/RichRenderer.php diff --git a/rector.php b/rector.php index 8be24cd7024d..68d16bbb66e4 100644 --- a/rector.php +++ b/rector.php @@ -71,6 +71,7 @@ $parameters->set(Option::SKIP, [ __DIR__ . '/app/Views', __DIR__ . '/system/Debug/Toolbar/Views/toolbar.tpl.php', + __DIR__ . '/system/Debug/Kint/RichRenderer.php', __DIR__ . '/system/ThirdParty', __DIR__ . '/tests/system/Config/fixtures', __DIR__ . '/tests/_support', diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index d309ca81c27a..56cb0df4b7bd 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -12,6 +12,7 @@ namespace CodeIgniter; use Closure; +use CodeIgniter\Debug\Kint\RichRenderer; use CodeIgniter\Debug\Timer; use CodeIgniter\Events\Events; use CodeIgniter\Exceptions\FrameworkException; @@ -33,7 +34,6 @@ use Exception; use Kint; use Kint\Renderer\CliRenderer; -use Kint\Renderer\RichRenderer; /** * This class is the core of the framework, and will analyse the @@ -257,6 +257,8 @@ protected function initializeKint() Kint::$plugins = $config->plugins; } + Kint::$renderers[Kint::MODE_RICH] = RichRenderer::class; + RichRenderer::$theme = $config->richTheme; RichRenderer::$folder = $config->richFolder; RichRenderer::$sort = $config->richSort; diff --git a/system/Debug/Kint/RichRenderer.php b/system/Debug/Kint/RichRenderer.php new file mode 100644 index 000000000000..756cac75e144 --- /dev/null +++ b/system/Debug/Kint/RichRenderer.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Debug\Kint; + +use Kint\Renderer\RichRenderer as KintRichRenderer; + +/** + * Overrides RichRenderer::preRender() for CSP + */ +class RichRenderer extends KintRichRenderer +{ + public function preRender() + { + $output = ''; + + if ($this->pre_render) { + foreach (self::$pre_render_sources as $type => $values) { + $contents = ''; + + foreach ($values as $v) { + $contents .= $v($this); + } + + if (! \strlen($contents)) { + continue; + } + + switch ($type) { + case 'script': + $output .= ''; + break; + + case 'style': + $output .= ''; + break; + + default: + $output .= $contents; + } + } + + // Don't pre-render on every dump + if (! $this->force_pre_render) { + self::$needs_pre_render = false; + } + } + + $output .= '
    '; + + return $output; + } +} From 9cd87553c1902c69cdbc0bed3fc9d691b9f07cde Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Dec 2021 18:43:41 +0900 Subject: [PATCH 387/407] docs: fix typo --- user_guide_src/source/general/common_functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index b9b21e29ba38..24d90ed654e1 100755 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -309,7 +309,7 @@ Miscellaneous Functions // Go back to the previous page return redirect()->back(); - // Go to specific UI + // Go to specific URI return redirect()->to('/admin'); // Go to a named/reverse-routed URI From 34209c8b6dfc03141040b231767e03514a8061db Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Dec 2021 18:43:59 +0900 Subject: [PATCH 388/407] docs: fix comment This code uses named route. --- user_guide_src/source/general/common_functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index 24d90ed654e1..cf99aaddda49 100755 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -312,7 +312,7 @@ Miscellaneous Functions // Go to specific URI return redirect()->to('/admin'); - // Go to a named/reverse-routed URI + // Go to a named route return redirect()->route('named_route'); // Keep the old input values upon redirect so they can be used by the `old()` function From a01b3313d220bf82181b7f8002b8d07880eff8cf Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Dec 2021 18:45:33 +0900 Subject: [PATCH 389/407] docs: decorate method --- user_guide_src/source/general/common_functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index cf99aaddda49..96a16fde77b6 100755 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -328,7 +328,7 @@ Miscellaneous Functions return redirect()->back()->withHeaders(); When passing an argument into the function, it is treated as a named/reverse-routed route, not a relative/full URI, - treating it the same as using redirect()->route():: + treating it the same as using ``redirect()->route()``:: // Go to a named/reverse-routed URI return redirect('named_route'); From aaf9cb2b4ede06b82b287016f04a5b7abdf7d8d3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 26 Dec 2021 06:58:17 +0900 Subject: [PATCH 390/407] docs: change text decoration --- user_guide_src/source/dbmgmt/forge.rst | 42 ++++++++++++-------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/user_guide_src/source/dbmgmt/forge.rst b/user_guide_src/source/dbmgmt/forge.rst index bbaa01490b0e..aadaf08d707b 100644 --- a/user_guide_src/source/dbmgmt/forge.rst +++ b/user_guide_src/source/dbmgmt/forge.rst @@ -40,7 +40,7 @@ Returns true/false based on success or failure:: echo 'Database created!'; } -An optional second parameter set to true will add IF EXISTS statement +An optional second parameter set to true will add ``IF EXISTS`` statement or will check if a database exists before create it (depending on DBMS). :: @@ -95,9 +95,9 @@ Adding fields ============= Fields are normally created via an associative array. Within the array, you must -include a 'type' key that relates to the datatype of the field. For +include a ``type`` key that relates to the datatype of the field. For example, INT, VARCHAR, TEXT, etc. Many datatypes (for example VARCHAR) -also require a 'constraint' key. +also require a ``constraint`` key. :: @@ -111,14 +111,14 @@ also require a 'constraint' key. Additionally, the following key/values can be used: -- unsigned/true : to generate "UNSIGNED" in the field definition. -- default/value : to generate a default value in the field definition. -- null/true : to generate "null" in the field definition. Without this, +- ``unsigned``/true : to generate "UNSIGNED" in the field definition. +- ``default``/value : to generate a default value in the field definition. +- ``null``/true : to generate "null" in the field definition. Without this, the field will default to "NOT null". -- auto_increment/true : generates an auto_increment flag on the +- ``auto_increment``/true : generates an auto_increment flag on the field. Note that the field type must be a type that supports this, such as integer. -- unique/true : to generate a unique key for the field definition. +- ``unique``/true : to generate a unique key for the field definition. :: @@ -162,15 +162,13 @@ Passing strings as fields ------------------------- If you know exactly how you want a field to be created, you can pass the -string into the field definitions with addField() - -:: +string into the field definitions with ``addField()``:: $forge->addField("label varchar(100) NOT NULL DEFAULT 'default label'"); .. note:: Passing raw strings as fields cannot be followed by ``addKey()`` calls on those fields. -.. note:: Multiple calls to addField() are cumulative. +.. note:: Multiple calls to ``addField()`` are cumulative. Creating an id field -------------------- @@ -188,10 +186,10 @@ Adding Keys =========== Generally speaking, you'll want your table to have Keys. This is -accomplished with $forge->addKey('field'). The optional second +accomplished with ``$forge->addKey('field')``. The optional second parameter set to true will make it a primary key and the third -parameter set to true will make it a unique key. Note that addKey() -must be followed by a call to createTable(). +parameter set to true will make it a unique key. Note that ``addKey()`` +must be followed by a call to ``createTable()``. Multiple column non-primary keys must be sent as an array. Sample output below is for MySQL. @@ -256,7 +254,7 @@ with $forge->createTable('table_name'); // gives CREATE TABLE table_name -An optional second parameter set to true adds an "IF NOT EXISTS" clause +An optional second parameter set to true adds an ``IF NOT EXISTS`` clause into the definition :: @@ -277,7 +275,7 @@ You could also pass optional table attributes, such as MySQL's ``ENGINE``:: Dropping a table ================ -Execute a DROP TABLE statement and optionally add an IF EXISTS clause. +Execute a ``DROP TABLE`` statement and optionally add an ``IF EXISTS`` clause. :: @@ -287,7 +285,7 @@ Execute a DROP TABLE statement and optionally add an IF EXISTS clause. // Produces: DROP TABLE IF EXISTS `table_name` $forge->dropTable('table_name', true); -A third parameter can be passed to add a "CASCADE" option, which might be required for some +A third parameter can be passed to add a ``CASCADE`` option, which might be required for some drivers to handle removal of tables with foreign keys. :: @@ -348,7 +346,7 @@ number of additional fields. // Executes: ALTER TABLE `table_name` ADD `preferences` TEXT If you are using MySQL or CUBIRD, then you can take advantage of their -AFTER and FIRST clauses to position the new column. +``AFTER`` and ``FIRST`` clauses to position the new column. Examples:: @@ -464,7 +462,7 @@ Class Reference .. php:method:: createDatabase($dbName[, $ifNotExists = false]) :param string $db_name: Name of the database to create - :param string $ifNotExists: Set to true to add an 'IF NOT EXISTS' clause or check if database exists + :param string $ifNotExists: Set to true to add an ``IF NOT EXISTS`` clause or check if database exists :returns: true on success, false on failure :rtype: bool @@ -473,7 +471,7 @@ Class Reference .. php:method:: createTable($table[, $if_not_exists = false[, array $attributes = []]]) :param string $table: Name of the table to create - :param string $if_not_exists: Set to true to add an 'IF NOT EXISTS' clause + :param string $if_not_exists: Set to true to add an ``IF NOT EXISTS`` clause :param string $attributes: An associative array of table attributes :returns: Query object on success, false on failure :rtype: mixed @@ -500,7 +498,7 @@ Class Reference .. php:method:: dropTable($table_name[, $if_exists = false]) :param string $table: Name of the table to drop - :param string $if_exists: Set to true to add an 'IF EXISTS' clause + :param string $if_exists: Set to true to add an ``IF EXISTS`` clause :returns: true on success, false on failure :rtype: bool From 63d3bf605e72be076de33fd6dd0fd33011d37346 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 26 Dec 2021 07:00:35 +0900 Subject: [PATCH 391/407] docs: remove `;` --- user_guide_src/source/dbmgmt/forge.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/dbmgmt/forge.rst b/user_guide_src/source/dbmgmt/forge.rst index aadaf08d707b..c74fada3551d 100644 --- a/user_guide_src/source/dbmgmt/forge.rst +++ b/user_guide_src/source/dbmgmt/forge.rst @@ -151,7 +151,7 @@ Additionally, the following key/values can be used: ]; After the fields have been defined, they can be added using -``$forge->addField($fields);`` followed by a call to the +``$forge->addField($fields)`` followed by a call to the ``createTable()`` method. **$forge->addField()** From 5876539b3b6dea4c69c07328da5b3fc2d0410cd0 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 26 Dec 2021 07:00:56 +0900 Subject: [PATCH 392/407] docs: change lowercase to uppercase --- user_guide_src/source/dbmgmt/forge.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/user_guide_src/source/dbmgmt/forge.rst b/user_guide_src/source/dbmgmt/forge.rst index c74fada3551d..2dedbc9af2dc 100644 --- a/user_guide_src/source/dbmgmt/forge.rst +++ b/user_guide_src/source/dbmgmt/forge.rst @@ -13,7 +13,7 @@ Initializing the Forge Class **************************** .. important:: In order to initialize the Forge class, your database - driver must already be running, since the forge class relies on it. + driver must already be running, since the Forge class relies on it. Load the Forge Class as follows:: @@ -91,7 +91,7 @@ There are several things you may wish to do when creating tables. Add fields, add keys to the table, alter columns. CodeIgniter provides a mechanism for this. -Adding fields +Adding Fields ============= Fields are normally created via an associative array. Within the array, you must @@ -243,7 +243,7 @@ You can specify the desired action for the "on delete" and "on update" propertie $forge->addForeignKey(['users_id', 'users_name'], 'users', ['id', 'name'], 'CASCADE', 'CASCADE'); // gives CONSTRAINT `TABLENAME_users_foreign` FOREIGN KEY(`users_id`, `users_name`) REFERENCES `users`(`id`, `name`) ON DELETE CASCADE ON UPDATE CASCADE -Creating a table +Creating a Table ================ After fields and keys have been declared, you can create a new table @@ -272,7 +272,7 @@ You could also pass optional table attributes, such as MySQL's ``ENGINE``:: ``createTable()`` will always add them with your configured *charset* and *DBCollat* values, as long as they are not empty (MySQL only). -Dropping a table +Dropping a Table ================ Execute a ``DROP TABLE`` statement and optionally add an ``IF EXISTS`` clause. @@ -314,7 +314,7 @@ Execute a DROP KEY. // Produces: DROP INDEX `users_index` ON `tablename` $forge->dropKey('tablename', 'users_index'); -Renaming a table +Renaming a Table ================ Executes a TABLE rename @@ -419,7 +419,7 @@ Class Reference :returns: \CodeIgniter\Database\Forge instance (method chaining) :rtype: \CodeIgniter\Database\Forge - Adds a field to the set that will be used to create a table. Usage: See `Adding fields`_. + Adds a field to the set that will be used to create a table. Usage: See `Adding Fields`_. .. php:method:: addForeignKey($fieldName, $tableName, $tableField[, $onUpdate = '', $onDelete = '']) @@ -476,7 +476,7 @@ Class Reference :returns: Query object on success, false on failure :rtype: mixed - Creates a new table. Usage: See `Creating a table`_. + Creates a new table. Usage: See `Creating a Table`_. .. php:method:: dropColumn($table, $column_name) @@ -502,7 +502,7 @@ Class Reference :returns: true on success, false on failure :rtype: bool - Drops a table. Usage: See `Dropping a table`_. + Drops a table. Usage: See `Dropping a Table`_. .. php:method:: modifyColumn($table, $field) @@ -520,4 +520,4 @@ Class Reference :returns: Query object on success, false on failure :rtype: mixed - Renames a table. Usage: See `Renaming a table`_. + Renames a table. Usage: See `Renaming a Table`_. From 3a03e452a944429df0ee85f7ad95e3274e357bc1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 27 Dec 2021 09:50:10 +0900 Subject: [PATCH 393/407] chore: add third party license files --- system/ComposerScripts.php | 19 +++++++++++++------ system/ThirdParty/Escaper/LICENSE.md | 26 ++++++++++++++++++++++++++ system/ThirdParty/Kint/LICENSE | 20 ++++++++++++++++++++ system/ThirdParty/PSR/Log/LICENSE | 19 +++++++++++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 system/ThirdParty/Escaper/LICENSE.md create mode 100644 system/ThirdParty/Kint/LICENSE create mode 100644 system/ThirdParty/PSR/Log/LICENSE diff --git a/system/ComposerScripts.php b/system/ComposerScripts.php index 6972395b5444..ef4dfe1a801b 100644 --- a/system/ComposerScripts.php +++ b/system/ComposerScripts.php @@ -43,20 +43,23 @@ final class ComposerScripts */ private static $dependencies = [ 'kint-src' => [ - 'from' => __DIR__ . '/../vendor/kint-php/kint/src/', - 'to' => __DIR__ . '/ThirdParty/Kint/', + 'license' => __DIR__ . '/../vendor/kint-php/kint/LICENSE', + 'from' => __DIR__ . '/../vendor/kint-php/kint/src/', + 'to' => __DIR__ . '/ThirdParty/Kint/', ], 'kint-resources' => [ 'from' => __DIR__ . '/../vendor/kint-php/kint/resources/', 'to' => __DIR__ . '/ThirdParty/Kint/resources/', ], 'escaper' => [ - 'from' => __DIR__ . '/../vendor/laminas/laminas-escaper/src/', - 'to' => __DIR__ . '/ThirdParty/Escaper/', + 'license' => __DIR__ . '/../vendor/laminas/laminas-escaper/LICENSE.md', + 'from' => __DIR__ . '/../vendor/laminas/laminas-escaper/src/', + 'to' => __DIR__ . '/ThirdParty/Escaper/', ], 'psr-log' => [ - 'from' => __DIR__ . '/../vendor/psr/log/Psr/Log/', - 'to' => __DIR__ . '/ThirdParty/PSR/Log/', + 'license' => __DIR__ . '/../vendor/psr/log/LICENSE', + 'from' => __DIR__ . '/../vendor/psr/log/Psr/Log/', + 'to' => __DIR__ . '/ThirdParty/PSR/Log/', ], ]; @@ -70,6 +73,10 @@ public static function postUpdate() foreach (self::$dependencies as $dependency) { self::recursiveMirror($dependency['from'], $dependency['to']); + if (isset($dependency['license'])) { + $license = basename($dependency['license']); + copy($dependency['license'], $dependency['to'] . '/' . $license); + } } self::copyKintInitFiles(); diff --git a/system/ThirdParty/Escaper/LICENSE.md b/system/ThirdParty/Escaper/LICENSE.md new file mode 100644 index 000000000000..10b40f1423b5 --- /dev/null +++ b/system/ThirdParty/Escaper/LICENSE.md @@ -0,0 +1,26 @@ +Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +- Neither the name of Laminas Foundation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/system/ThirdParty/Kint/LICENSE b/system/ThirdParty/Kint/LICENSE new file mode 100644 index 000000000000..01718d4953c4 --- /dev/null +++ b/system/ThirdParty/Kint/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Jonathan Vollebregt (jnvsor@gmail.com), Rokas Šleinius (raveren@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/system/ThirdParty/PSR/Log/LICENSE b/system/ThirdParty/PSR/Log/LICENSE new file mode 100644 index 000000000000..474c952b4b50 --- /dev/null +++ b/system/ThirdParty/PSR/Log/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. From 9c379088e8afa6cbfa470cbda79359f800ab5b24 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 27 Dec 2021 11:37:44 +0900 Subject: [PATCH 394/407] test: add tests for Kint with CSP --- tests/system/CommonFunctionsTest.php | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index c6f1d6b9b2e1..b7f4f381c233 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -29,6 +29,7 @@ use Config\Logger; use Config\Modules; use InvalidArgumentException; +use Kint; use stdClass; use Tests\Support\Models\JobModel; @@ -482,4 +483,37 @@ public function testIsCli() $this->assertIsBool(is_cli()); $this->assertTrue(is_cli()); } + + public function testDWithCSP() + { + /** @var App $config */ + $config = config(App::class); + $CSPEnabled = $config->CSPEnabled; + $cliDetection = Kint::$cli_detection; + + $config->CSPEnabled = true; + Kint::$cli_detection = false; + + $this->expectOutputRegex('/