From 9f7752583c3795ff7ef4903c7b318d18a2dcf838 Mon Sep 17 00:00:00 2001 From: MGatner Date: Mon, 17 May 2021 15:29:49 +0000 Subject: [PATCH 01/53] Increase handler robustness --- system/Cache/Handlers/FileHandler.php | 36 +++++++-------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index 91afb212e0e4..c67b2180a643 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -285,35 +285,13 @@ public function getMetaData(string $key) { $key = static::validateKey($key, $this->prefix); - if (! is_file($this->path . $key)) + if (false === $data = $this->getItem($key)) { return false; // This will return null in a future release } - $data = @unserialize(file_get_contents($this->path . $key)); - - if (! is_array($data) || ! isset($data['ttl'])) - { - return false; // This will return null in a future release - } - - // Consider expired items as missing - $expire = $data['time'] + $data['ttl']; - - // @phpstan-ignore-next-line - if ($data['ttl'] > 0 && time() > $expire) - { - // If the file is still there then remove it - if (is_file($this->path . $key)) - { - unlink($this->path . $key); - } - - return false; // This will return null in a future release - } - return [ - 'expire' => $expire, + 'expire' => $data['time'] + $data['ttl'], 'mtime' => filemtime($this->path . $key), 'data' => $data['data'], ]; @@ -348,15 +326,19 @@ protected function getItem(string $filename) return false; } - $data = unserialize(file_get_contents($this->path . $filename)); + $data = @unserialize(file_get_contents($this->path . $filename)); + if (! is_array($data) || ! isset($data['ttl'])) + { + return false; + } // @phpstan-ignore-next-line if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl']) { - // If the file is still there then remove it + // If the file is still there then try to remove it if (is_file($this->path . $filename)) { - unlink($this->path . $filename); + @unlink($this->path . $filename); } return false; From 31615e0542be4c228a2f6ff27d63a5bbf8d20ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Tue, 18 May 2021 11:42:25 +0200 Subject: [PATCH 02/53] Create .git/hooks directory if not already present --- admin/setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/setup.sh b/admin/setup.sh index 3170716c53ef..86254e8e8889 100644 --- a/admin/setup.sh +++ b/admin/setup.sh @@ -2,5 +2,6 @@ # Install a pre-commit hook that # automatically runs phpcs to fix styles +mkdir -p .git/hooks cp admin/pre-commit .git/hooks/pre-commit chmod +x .git/hooks/pre-commit From 2a509f380f15414e55646ff0011ac29cc764818d Mon Sep 17 00:00:00 2001 From: MGatner Date: Tue, 18 May 2021 14:52:07 +0000 Subject: [PATCH 03/53] Update release process --- admin/RELEASE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/RELEASE.md b/admin/RELEASE.md index 9b39c2558c31..62f9c222eb79 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -57,13 +57,13 @@ See the changelog: https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHA * Build the HTML version of the User Guide: `make html` * Build the ePub version of the User Guide: `make epub` * Switch to the **userguide** repo and create a new branch `release-4.x.x` -* Copy the contents of **CodeIgniter4/user_guide_src/build/html** into **docs/** +* Merge the contents of **CodeIgniter4/user_guide_src/build/html** into **docs/** (be sure to keep the assets in **docs/_static**) * Copy **CodeIgniter4/user_guide_src/build/epub/CodeIgniter.epub** to **./CodeIgniter4.x.x.epub** * Commit the changes with "Update for 4.x.x" and push to origin * Create a new PR from `release-4.x.x` to `develop`: * Title: "Update for 4.x.x" * Description: blank -* Merge the PR then fast-forward `develop` to catch the merge commit +* Merge the PR * Create a new Release: * Version: "v4.x.x" * Title: "CodeIgniter 4.x.x User Guide" @@ -74,7 +74,7 @@ See the changelog: https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHA Currently the User Guide on the website has to be updated manually. Visit Jim's user home where the served directory **codeigniter.com** exists. Copy the latest **docs** folder from -the User Guide repo into **public** and updated the symlink. +the User Guide repo to **public/userguide4** and browse to the website to make sure. ## Announcement From 0f0c1d6514c0234f4d16bdca0e5e308a39168986 Mon Sep 17 00:00:00 2001 From: MGatner Date: Tue, 18 May 2021 17:52:05 +0000 Subject: [PATCH 04/53] Add .nojekyll note --- admin/RELEASE.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/admin/RELEASE.md b/admin/RELEASE.md index 62f9c222eb79..822bd1f5f154 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -57,7 +57,8 @@ See the changelog: https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHA * Build the HTML version of the User Guide: `make html` * Build the ePub version of the User Guide: `make epub` * Switch to the **userguide** repo and create a new branch `release-4.x.x` -* Merge the contents of **CodeIgniter4/user_guide_src/build/html** into **docs/** (be sure to keep the assets in **docs/_static**) +* Replace **docs/** with **CodeIgniter4/user_guide_src/build/html** +* Ensure the file **docs/.nojekyll** exists or GitHub Pages will ignore folders with an underscore prefix * Copy **CodeIgniter4/user_guide_src/build/epub/CodeIgniter.epub** to **./CodeIgniter4.x.x.epub** * Commit the changes with "Update for 4.x.x" and push to origin * Create a new PR from `release-4.x.x` to `develop`: @@ -74,7 +75,7 @@ See the changelog: https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHA Currently the User Guide on the website has to be updated manually. Visit Jim's user home where the served directory **codeigniter.com** exists. Copy the latest **docs** folder from -the User Guide repo to **public/userguide4** and browse to the website to make sure. +the User Guide repo to **public/userguide4** and browse to the website to make sure it works. ## Announcement From 2fa4d13c17a9d07ad218b6fbb633c7f3f0776da6 Mon Sep 17 00:00:00 2001 From: MGatner Date: Tue, 18 May 2021 14:16:12 -0400 Subject: [PATCH 05/53] Revert "Fixed documentation styles to widen the content frame on large screens" --- user_guide_src/source/_static/css/citheme.css | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/user_guide_src/source/_static/css/citheme.css b/user_guide_src/source/_static/css/citheme.css index 733c5db71979..146b7d377686 100644 --- a/user_guide_src/source/_static/css/citheme.css +++ b/user_guide_src/source/_static/css/citheme.css @@ -95,20 +95,6 @@ body, p, legend { background-size: 200px; } -/* -- Breakpoint for large screens (> 900px) --------- */ -@media (min-width: 900px) and (max-width: 1100px) { - .wy-nav-content { - max-width: 1620px; - } -} - -@media (min-width: 1100px) { - .wy-nav-content { - margin: 0 auto; - max-width: 1620px; - } -} - /* Titles ------------------------------------------------------------------- */ h1, h2, h3, h4, h5, h6 { From 65278701de3dfdab9fa5f66bc199ffb77a6bab1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Wed, 19 May 2021 00:22:24 +0200 Subject: [PATCH 06/53] Check for configured instead of hard-coded database --- tests/system/Database/Live/DbUtilsTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/system/Database/Live/DbUtilsTest.php b/tests/system/Database/Live/DbUtilsTest.php index eff9d5abf8f8..1d3b6a9d083b 100644 --- a/tests/system/Database/Live/DbUtilsTest.php +++ b/tests/system/Database/Live/DbUtilsTest.php @@ -79,7 +79,7 @@ public function testUtilsListDatabases() { $databases = $util->listDatabases(); - $this->assertTrue(in_array('test', $databases, true)); + $this->assertTrue(in_array($this->db->getDatabase(), $databases, true)); } elseif ($this->db->DBDriver === 'SQLite3') { @@ -98,7 +98,7 @@ public function testUtilsDatabaseExist() if (in_array($this->db->DBDriver, ['MySQLi', 'Postgre', 'SQLSRV'], true)) { - $exist = $util->databaseExists('test'); + $exist = $util->databaseExists($this->db->getDatabase()); $this->assertTrue($exist); } @@ -107,7 +107,7 @@ public function testUtilsDatabaseExist() $this->expectException(DatabaseException::class); $this->expectExceptionMessage('Unsupported feature of the database platform you are using.'); - $util->databaseExists('test'); + $util->databaseExists($this->db->getDatabase()); } } From a9e4a7f506ddc61654f558b18b23e92408b26c7e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 19 May 2021 21:38:05 +0700 Subject: [PATCH 07/53] Remove unused rowOffset in Database/SQLSRV/Result.php --- system/Database/SQLSRV/Result.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/system/Database/SQLSRV/Result.php b/system/Database/SQLSRV/Result.php index b3ae7f975393..6dfd426375ef 100755 --- a/system/Database/SQLSRV/Result.php +++ b/system/Database/SQLSRV/Result.php @@ -20,13 +20,6 @@ */ class Result extends BaseResult { - /** - * Row offset - * - * @var integer - */ - private $rowOffset = 0; - //-------------------------------------------------------------------- /** From c0a7f22aa763d863f48f9498e802d2f157d9c60d Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 20 May 2021 18:33:20 +0000 Subject: [PATCH 08/53] Add file helpers --- system/Helpers/filesystem_helper.php | 73 ++++++++++++++ tests/system/Helpers/FilesystemHelperTest.php | 98 +++++++++++++++++++ .../source/helpers/filesystem_helper.rst | 29 +++++- 3 files changed, 197 insertions(+), 3 deletions(-) diff --git a/system/Helpers/filesystem_helper.php b/system/Helpers/filesystem_helper.php index ddbbcf5dcccb..efad574e5936 100644 --- a/system/Helpers/filesystem_helper.php +++ b/system/Helpers/filesystem_helper.php @@ -75,6 +75,61 @@ function directory_map(string $sourceDir, int $directoryDepth = 0, bool $hidden // ------------------------------------------------------------------------ +if (! function_exists('directory_mirror')) +{ + /** + * Recursively copies the files and directories of the origin directory + * into the target directory, i.e. "mirror" its contents. + * + * @param string $originDir + * @param string $targetDir + * @param bool $overwrite Whether individual files overwrite on collision + * + * @return void + * + * @throws InvalidArgumentException + */ + function directory_mirror(string $originDir, string $targetDir, bool $overwrite = true): void + { + $originDir = rtrim($originDir, '\\/'); + $targetDir = rtrim($targetDir, '\\/'); + + if (! is_dir($originDir)) + { + throw new InvalidArgumentException(sprintf('The origin directory "%s" was not found.', $originDir)); + } + + if (! is_dir($targetDir)) + { + @mkdir($targetDir, 0755, true); + } + + + $dirLen = strlen($originDir); + + /** @var SplFileInfo $file */ + foreach (new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($originDir, FilesystemIterator::SKIP_DOTS), + RecursiveIteratorIterator::SELF_FIRST + ) as $file) + { + $origin = $file->getPathname(); + $target = $targetDir . substr($origin, $dirLen); + + if ($file->isDir()) + { + mkdir($target, 0755); + } + elseif (! file_exists($target) || ($overwrite && is_file($target))) + { + copy($origin, $target); + } + } + } +} + +// ------------------------------------------------------------------------ + if (! function_exists('write_file')) { /** @@ -448,6 +503,24 @@ function octal_permissions(int $perms): string // ------------------------------------------------------------------------ +if (! function_exists('same_file')) +{ + /** + * Checks if two files both exist and have identical hashes + * + * @param string $file1 + * @param string $file2 + * + * @return bool Same or not + */ + function same_file(string $file1, string $file2): bool + { + return is_file($file1) && is_file($file2) && md5_file($file1) === md5_file($file2); + } +} + +// ------------------------------------------------------------------------ + if (! function_exists('set_realpath')) { /** diff --git a/tests/system/Helpers/FilesystemHelperTest.php b/tests/system/Helpers/FilesystemHelperTest.php index a30df24a197e..324e670b4f14 100644 --- a/tests/system/Helpers/FilesystemHelperTest.php +++ b/tests/system/Helpers/FilesystemHelperTest.php @@ -6,6 +6,9 @@ use InvalidArgumentException; use org\bovigo\vfs\vfsStream; +use org\bovigo\vfs\vfsStreamDirectory; +use org\bovigo\vfs\visitor\vfsStreamStructureVisitor; + class FilesystemHelperTest extends CIUnitTestCase { @@ -104,6 +107,58 @@ public function testDirectoryMapHandlesNotfound() //-------------------------------------------------------------------- + public function testDirectoryMirror() + { + $this->assertTrue(function_exists('directory_mirror')); + + // Create a subdirectory + $this->structure['foo']['bam'] = ['zab' => 'A deep file']; + + $vfs = vfsStream::setup('root', null, $this->structure); + $root = rtrim(vfsStream::url('root') . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + + directory_mirror($root . 'foo', $root . 'boo'); + + $this->assertFileExists($root . 'boo/bar'); + $this->assertFileExists($root . 'boo/bam/zab'); + } + + public function testDirectoryMirrorOverwrites() + { + $this->assertTrue(function_exists('directory_mirror')); + + // Create duplicate files + $this->structure['foo']['far'] = 'all your base'; + $this->structure['foo']['faz'] = 'are belong to us'; + + $vfs = vfsStream::setup('root', null, $this->structure); + $root = rtrim(vfsStream::url('root') . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + + directory_mirror($root . 'foo', $root . 'boo', true); + $result = file_get_contents($root . 'boo/faz'); + + $this->assertEquals($this->structure['foo']['faz'], $result); + } + + public function testDirectoryMirrorNotOverwrites() + { + $this->assertTrue(function_exists('directory_mirror')); + + // Create duplicate files + $this->structure['foo']['far'] = 'all your base'; + $this->structure['foo']['faz'] = 'are belong to us'; + + $vfs = vfsStream::setup('root', null, $this->structure); + $root = rtrim(vfsStream::url('root') . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + + directory_mirror($root . 'foo', $root . 'boo', false); + $result = file_get_contents($root . 'boo/faz'); + + $this->assertEquals($this->structure['boo']['faz'], $result); + } + + //-------------------------------------------------------------------- + public function testWriteFileSuccess() { $vfs = vfsStream::setup('root'); @@ -379,6 +434,49 @@ public function testGetFileNotThereInfo() } //-------------------------------------------------------------------- + + public function testSameFileSame() + { + $file1 = SUPPORTPATH . 'Files/able/apple.php'; + $file2 = SUPPORTPATH . 'Files/able/apple.php'; + + $this->assertTrue(same_file($file1, $file2)); + } + + public function testSameFileIdentical() + { + $file1 = SUPPORTPATH . 'Files/able/apple.php'; + $file2 = SUPPORTPATH . 'Files/baker/banana.php'; + + $this->assertTrue(same_file($file1, $file2)); + } + + public function testSameFileDifferent() + { + $file1 = SUPPORTPATH . 'Files/able/apple.php'; + $file2 = SUPPORTPATH . 'Images/ci-logo.gif'; + + $this->assertFalse(same_file($file1, $file2)); + } + + public function testSameFileOrder() + { + $file1 = SUPPORTPATH . 'Files/able/apple.php'; + $file2 = SUPPORTPATH . 'Images/ci-logo.gif'; + + $this->assertFalse(same_file($file2, $file1)); + } + + public function testSameFileDirectory() + { + $file1 = SUPPORTPATH . 'Files/able/apple.php'; + $file2 = SUPPORTPATH . 'Images/'; + + $this->assertFalse(same_file($file1, $file2)); + } + + //-------------------------------------------------------------------- + public function testOctalPermissions() { $this->assertEquals('777', octal_permissions(0777)); diff --git a/user_guide_src/source/helpers/filesystem_helper.rst b/user_guide_src/source/helpers/filesystem_helper.rst index 3d55afec0cad..735671420282 100644 --- a/user_guide_src/source/helpers/filesystem_helper.rst +++ b/user_guide_src/source/helpers/filesystem_helper.rst @@ -26,7 +26,7 @@ The following functions are available: :param string $source_dir: Path to the source directory :param int $directory_depth: Depth of directories to traverse (0 = fully recursive, 1 = current dir, etc) - :param bool $hidden: Whether to include hidden directories + :param bool $hidden: Whether to include hidden paths :returns: An array of files :rtype: array @@ -42,8 +42,9 @@ The following functions are available: $map = directory_map('./mydirectory/', 1); - By default, hidden files will not be included in the returned array. To - override this behavior, you may set a third parameter to true (boolean):: + By default, hidden files will not be included in the returned array and + hidden directories will be skipped. To override this behavior, you may + set a third parameter to true (boolean):: $map = directory_map('./mydirectory/', FALSE, TRUE); @@ -79,6 +80,28 @@ The following functions are available: If no results are found, this will return an empty array. +.. php:function:: directory_mirror($original, $target[, $overwrite = true]) + + :param string $original: Original source directory + :param string $target: Target destination directory + :param bool $overwrite: Whether individual files overwrite on collision + + Recursively copies the files and directories of the origin directory + into the target directory, i.e. "mirror" its contents. + + Example:: + + try + {      + directory_mirror($uploadedImages, FCPATH . 'images/'); + } + catch (Throwable $e) + {      + echo 'Failed to export uploads!'; + } + + You can optionally change the overwrite behavior via the third parameter. + .. php:function:: write_file($path, $data[, $mode = 'wb']) :param string $path: File path From e0005cb4b442488bbbcfaa35cd9dfd98b0caa0fb Mon Sep 17 00:00:00 2001 From: MGatner Date: Fri, 21 May 2021 14:27:42 +0000 Subject: [PATCH 09/53] Apply review suggestions --- system/Helpers/filesystem_helper.php | 10 +++------- user_guide_src/source/helpers/filesystem_helper.rst | 13 +++++++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/system/Helpers/filesystem_helper.php b/system/Helpers/filesystem_helper.php index efad574e5936..5499c5d6430c 100644 --- a/system/Helpers/filesystem_helper.php +++ b/system/Helpers/filesystem_helper.php @@ -91,20 +91,16 @@ function directory_map(string $sourceDir, int $directoryDepth = 0, bool $hidden */ function directory_mirror(string $originDir, string $targetDir, bool $overwrite = true): void { - $originDir = rtrim($originDir, '\\/'); - $targetDir = rtrim($targetDir, '\\/'); - - if (! is_dir($originDir)) + if (! is_dir($originDir = rtrim($originDir, '\\/'))) { throw new InvalidArgumentException(sprintf('The origin directory "%s" was not found.', $originDir)); } - if (! is_dir($targetDir)) + if (! is_dir($targetDir = rtrim($targetDir, '\\/'))) { @mkdir($targetDir, 0755, true); } - $dirLen = strlen($originDir); /** @var SplFileInfo $file */ @@ -120,7 +116,7 @@ function directory_mirror(string $originDir, string $targetDir, bool $overwrite { mkdir($target, 0755); } - elseif (! file_exists($target) || ($overwrite && is_file($target))) + elseif (! is_file($target) || ($overwrite && is_file($target))) { copy($origin, $target); } diff --git a/user_guide_src/source/helpers/filesystem_helper.rst b/user_guide_src/source/helpers/filesystem_helper.rst index 735671420282..5cfffae21f33 100644 --- a/user_guide_src/source/helpers/filesystem_helper.rst +++ b/user_guide_src/source/helpers/filesystem_helper.rst @@ -239,6 +239,19 @@ The following functions are available: echo octal_permissions(fileperms('./index.php')); // 644 +.. php:function:: same_file($file1, $file2) + + :param string $file1: Path to the first file + :param string $file2: Path to the second file + :returns: Whether both files exist with identical hashes + :rtype: boolean + + Compares two files to see if they are the same (based on their MD5 hash). + + :: + + echo same_file($newFile, $oldFile) ? 'Same!' : 'Different!'; + .. php:function:: set_realpath($path[, $check_existence = FALSE]) :param string $path: Path From bac8391b3046568ea2dd6e2c94e3eae7d23ac498 Mon Sep 17 00:00:00 2001 From: MGatner Date: Fri, 21 May 2021 14:58:15 +0000 Subject: [PATCH 10/53] Format URI directly, fixes #4707 --- system/HTTP/CURLRequest.php | 3 ++- tests/system/HTTP/CURLRequestTest.php | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 35fb535e5c8e..55797e06c646 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -347,7 +347,8 @@ protected function prepareURL(string $url): string $uri = $this->baseURI->resolveRelativeURI($url); - return (string) $uri; + // Create the string instead of casting to prevent baseURL muddling + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index e1ccd5fb2f43..003b8298acc7 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -33,6 +33,24 @@ protected function getRequest(array $options = []) //-------------------------------------------------------------------- + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/4707 + */ + public function testPrepareURLIgnoresAppConfig() + { + config('App')->baseURL = 'http://example.com/fruit/'; + + $request = $this->getRequest([ + 'base_uri' => 'http://example.com/v1/', + ]); + + $method = $this->getPrivateMethodInvoker($request, 'prepareURL'); + + $this->assertEquals('http://example.com/v1/bananas', $method('bananas')); + } + + //-------------------------------------------------------------------- + /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/1029 */ From 2d2340b59eb9ebeb3e166481c6983ca10db206aa Mon Sep 17 00:00:00 2001 From: MGatner Date: Fri, 21 May 2021 15:35:23 +0000 Subject: [PATCH 11/53] Replace URI string casts --- system/CodeIgniter.php | 4 ++-- system/HTTP/RedirectResponse.php | 2 +- system/Helpers/url_helper.php | 17 +++------------- system/Log/Handlers/ChromeLoggerHandler.php | 4 +--- system/Pager/Pager.php | 2 +- system/Pager/PagerRenderer.php | 17 ++++++++-------- tests/system/HTTP/RedirectResponseTest.php | 2 +- .../Helpers/URLHelper/CurrentUrlTest.php | 20 ++++++++----------- 8 files changed, 26 insertions(+), 42 deletions(-) diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 56a01dcd9344..c19918aec1d9 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -474,7 +474,7 @@ protected function handleRequest(?RouteCollectionInterface $routes, Cache $cache // Save our current URI as the previous URI in the session // for safer, more accurate use with `previous_url()` helper function. - $this->storePreviousURL((string) current_url(true)); + $this->storePreviousURL(current_url(true)); unset($uri); @@ -1080,7 +1080,7 @@ public function storePreviousURL($uri) if (isset($_SESSION)) { - $_SESSION['_ci_previous_url'] = (string) $uri; + $_SESSION['_ci_previous_url'] = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } } diff --git a/system/HTTP/RedirectResponse.php b/system/HTTP/RedirectResponse.php index 50061c8925b0..4f31e901e1fe 100644 --- a/system/HTTP/RedirectResponse.php +++ b/system/HTTP/RedirectResponse.php @@ -36,7 +36,7 @@ public function to(string $uri, int $code = null, string $method = 'auto') // for better security. if (strpos($uri, 'http') !== 0) { - $uri = (string) current_url(true)->resolveRelativeURI($uri); + $uri = site_url($uri); } return $this->redirect($uri, $method, $code); diff --git a/system/Helpers/url_helper.php b/system/Helpers/url_helper.php index f58045ae73a7..2424a98c0291 100644 --- a/system/Helpers/url_helper.php +++ b/system/Helpers/url_helper.php @@ -205,20 +205,9 @@ function previous_url(bool $returnObject = false) */ function uri_string(bool $relative = false): string { - $request = Services::request(); - $uri = $request->uri; - - // An absolute path is equivalent to getPath() - if (! $relative) - { - return $uri->getPath(); - } - - // Remove the baseURL from the entire URL - $url = (string) $uri->__toString(); - $baseURL = rtrim($request->config->baseURL, '/ ') . '/'; - - return substr($url, strlen($baseURL)); + return $relative + ? ltrim(Services::request()->getPath(), '/') + : Services::request()->getUri()->getPath(); } } diff --git a/system/Log/Handlers/ChromeLoggerHandler.php b/system/Log/Handlers/ChromeLoggerHandler.php index b248072aa829..73c301f91503 100644 --- a/system/Log/Handlers/ChromeLoggerHandler.php +++ b/system/Log/Handlers/ChromeLoggerHandler.php @@ -87,9 +87,7 @@ public function __construct(array $config = []) { parent::__construct($config); - $request = Services::request(null, true); - - $this->json['request_uri'] = (string) $request->uri; + $this->json['request_uri'] = current_url(); } //-------------------------------------------------------------------- diff --git a/system/Pager/Pager.php b/system/Pager/Pager.php index 3220d127e7e5..d5f059f318ce 100644 --- a/system/Pager/Pager.php +++ b/system/Pager/Pager.php @@ -377,7 +377,7 @@ public function getPageURI(int $page = null, string $group = 'default', bool $re $uri->setQueryArray($query); } - return $returnObject === true ? $uri : (string) $uri; + return $returnObject === true ? $uri : URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- diff --git a/system/Pager/PagerRenderer.php b/system/Pager/PagerRenderer.php index 37f289e9affe..f1a45992b3a3 100644 --- a/system/Pager/PagerRenderer.php +++ b/system/Pager/PagerRenderer.php @@ -156,7 +156,7 @@ public function getPrevious() $uri->setSegment($this->segment, $this->first - 1); } - return (string) $uri; + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- @@ -200,7 +200,7 @@ public function getNext() $uri->setSegment($this->segment, $this->last + 1); } - return (string) $uri; + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- @@ -223,7 +223,7 @@ public function getFirst(): string $uri->setSegment($this->segment, 1); } - return (string) $uri; + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- @@ -246,7 +246,7 @@ public function getLast(): string $uri->setSegment($this->segment, $this->pageCount); } - return (string) $uri; + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- @@ -269,7 +269,7 @@ public function getCurrent(): string $uri->setSegment($this->segment, $this->current); } - return (string) $uri; + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- @@ -290,8 +290,9 @@ public function links(): array for ($i = $this->first; $i <= $this->last; $i ++) { + $uri = $this->segment === 0 ? $uri->addQuery($this->pageSelector, $i) : $uri->setSegment($this->segment, $i); $links[] = [ - 'uri' => (string) ($this->segment === 0 ? $uri->addQuery($this->pageSelector, $i) : $uri->setSegment($this->segment, $i)), + 'uri' => URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()), 'title' => (int) $i, 'active' => ($i === $this->current), ]; @@ -359,7 +360,7 @@ public function getPreviousPage() $uri->setSegment($this->segment, $this->current - 1); } - return (string) $uri; + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } //-------------------------------------------------------------------- @@ -401,7 +402,7 @@ public function getNextPage() $uri->setSegment($this->segment, $this->current + 1); } - return (string) $uri; + return URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment()); } /** diff --git a/tests/system/HTTP/RedirectResponseTest.php b/tests/system/HTTP/RedirectResponseTest.php index 3e5c211127ef..a154b6fce3f1 100644 --- a/tests/system/HTTP/RedirectResponseTest.php +++ b/tests/system/HTTP/RedirectResponseTest.php @@ -90,7 +90,7 @@ public function testRedirectRelativeConvertsToFullURI() $response = $response->to('/foo'); $this->assertTrue($response->hasHeader('Location')); - $this->assertEquals('http://example.com/foo', $response->getHeaderLine('Location')); + $this->assertEquals('http://example.com/index.php/foo', $response->getHeaderLine('Location')); } //-------------------------------------------------------------------- diff --git a/tests/system/Helpers/URLHelper/CurrentUrlTest.php b/tests/system/Helpers/URLHelper/CurrentUrlTest.php index 895f8318ecbd..44e5a260211e 100644 --- a/tests/system/Helpers/URLHelper/CurrentUrlTest.php +++ b/tests/system/Helpers/URLHelper/CurrentUrlTest.php @@ -153,7 +153,6 @@ public function testUriStringAbsolute() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('/assets/image.jpg', uri_string()); } @@ -167,7 +166,6 @@ public function testUriStringRelative() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('assets/image.jpg', uri_string(true)); } @@ -182,7 +180,6 @@ public function testUriStringNoTrailingSlashAbsolute() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('/assets/image.jpg', uri_string()); } @@ -197,7 +194,6 @@ public function testUriStringNoTrailingSlashRelative() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('assets/image.jpg', uri_string(true)); } @@ -208,7 +204,6 @@ public function testUriStringEmptyAbsolute() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('/', uri_string()); } @@ -219,7 +214,6 @@ public function testUriStringEmptyRelative() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('', uri_string(true)); } @@ -234,15 +228,14 @@ public function testUriStringSubfolderAbsolute() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('/subfolder/assets/image.jpg', uri_string()); } public function testUriStringSubfolderRelative() { $_SERVER['HTTP_HOST'] = 'example.com'; - $_SERVER['REQUEST_URI'] = '/assets/image.jpg'; $_SERVER['REQUEST_URI'] = '/subfolder/assets/image.jpg'; + $_SERVER['SCRIPT_NAME'] = '/subfolder/index.php'; $this->config->baseURL = 'http://example.com/subfolder/'; $request = Services::request($this->config); @@ -250,7 +243,6 @@ public function testUriStringSubfolderRelative() Services::injectMock('request', $request); - $url = current_url(); $this->assertEquals('assets/image.jpg', uri_string(true)); } @@ -304,7 +296,8 @@ public function urlIsProvider() */ public function testUrlIs(string $currentPath, string $testPath, bool $expected) { - $_SERVER['HTTP_HOST'] = 'example.com'; + $_SERVER['HTTP_HOST'] = 'example.com'; + $_SERVER['REQUEST_URI'] = '/' . $currentPath; $request = Services::request(); $request->uri = new URI('http://example.com/' . $currentPath); @@ -319,6 +312,7 @@ public function testUrlIs(string $currentPath, string $testPath, bool $expected) public function testUrlIsNoIndex(string $currentPath, string $testPath, bool $expected) { $_SERVER['HTTP_HOST'] = 'example.com'; + $_SERVER['REQUEST_URI'] = '/' . $currentPath; $this->config->indexPage = ''; $request = Services::request($this->config); @@ -333,8 +327,10 @@ public function testUrlIsNoIndex(string $currentPath, string $testPath, bool $ex */ public function testUrlIsWithSubfolder(string $currentPath, string $testPath, bool $expected) { - $_SERVER['HTTP_HOST'] = 'example.com'; - $this->config->baseURL = 'http://example.com/subfolder/'; + $_SERVER['HTTP_HOST'] = 'example.com'; + $_SERVER['REQUEST_URI'] = '/' . $currentPath; + $_SERVER['SCRIPT_NAME'] = '/subfolder/index.php'; + $this->config->baseURL = 'http://example.com/subfolder/'; $request = Services::request($this->config); $request->uri = new URI('http://example.com/subfolder/' . $currentPath); From 021a6f445dc1173262337a2285253181347de882 Mon Sep 17 00:00:00 2001 From: MGatner Date: Fri, 21 May 2021 15:42:34 +0000 Subject: [PATCH 12/53] Add UG cast warning --- user_guide_src/source/libraries/uri.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/user_guide_src/source/libraries/uri.rst b/user_guide_src/source/libraries/uri.rst index 69ba98d0b240..649685db71ec 100644 --- a/user_guide_src/source/libraries/uri.rst +++ b/user_guide_src/source/libraries/uri.rst @@ -61,6 +61,11 @@ using the URI class' static ``createURIString()`` method:: // Creates: http://exmample.com/some/path?foo=bar#first-heading echo URI::createURIString('http', 'example.com', 'some/path', 'foo=bar', 'first-heading'); +.. important:: When ``URI`` is cast to a string, it will attempt to adjust project URLs to the + settings defined in ``Config\App``. If you need the exact, unaltered string representation + then use ``URI::createURIString()`` instead. + + ============= The URI Parts ============= From 866e27125f3947a3d810c06d59769e32739fc66d Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" <51850998+paulbalandan@users.noreply.github.com> Date: Sat, 22 May 2021 00:41:24 +0800 Subject: [PATCH 13/53] Annotate specifically designed slow tests with custom limits (#4698) --- tests/system/CLI/CLITest.php | 12 +++++- .../system/Cache/Handlers/FileHandlerTest.php | 19 +++++--- .../Cache/Handlers/MemcachedHandlerTest.php | 18 +++++--- .../Cache/Handlers/PredisHandlerTest.php | 18 +++++--- .../Cache/Handlers/RedisHandlerTest.php | 18 +++++--- tests/system/Debug/TimerTest.php | 43 ++++++------------- 6 files changed, 75 insertions(+), 53 deletions(-) diff --git a/tests/system/CLI/CLITest.php b/tests/system/CLI/CLITest.php index 3b67821d229f..85b2ded4f007 100644 --- a/tests/system/CLI/CLITest.php +++ b/tests/system/CLI/CLITest.php @@ -1,10 +1,12 @@ -assertInstanceOf(FileHandler::class, $this->fileHandler); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testGet() { $this->fileHandler->save(self::$key1, 'value', 2); @@ -106,6 +111,12 @@ public function testGet() $this->assertNull($this->fileHandler->get(self::$key1)); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testRemember() { $this->fileHandler->remember(self::$key1, 2, function () { @@ -295,8 +306,6 @@ public function modeProvider() ]; } - //-------------------------------------------------------------------- - public function testFileHandler() { $fileHandler = new BaseTestFileHandler(); @@ -316,7 +325,6 @@ public function testFileHandler() final class BaseTestFileHandler extends FileHandler { - private static $directory = 'FileHandler'; private $config; @@ -344,5 +352,4 @@ public function getFileInfoTest() 'fileperms', ]); } - } diff --git a/tests/system/Cache/Handlers/MemcachedHandlerTest.php b/tests/system/Cache/Handlers/MemcachedHandlerTest.php index ff3ab1027942..82232c3061ae 100644 --- a/tests/system/Cache/Handlers/MemcachedHandlerTest.php +++ b/tests/system/Cache/Handlers/MemcachedHandlerTest.php @@ -7,7 +7,7 @@ use Config\Cache; use Exception; -class MemcachedHandlerTest extends CIUnitTestCase +final class MemcachedHandlerTest extends CIUnitTestCase { private $memcachedHandler; private static $key1 = 'key1'; @@ -32,10 +32,6 @@ protected function setUp(): void $this->config = new Cache(); $this->memcachedHandler = new MemcachedHandler($this->config); - if (! $this->memcachedHandler->isSupported()) - { - $this->markTestSkipped('Not support memcached and memcache'); - } $this->memcachedHandler->initialize(); } @@ -53,6 +49,12 @@ public function testNew() $this->assertInstanceOf(MemcachedHandler::class, $this->memcachedHandler); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testGet() { $this->memcachedHandler->save(self::$key1, 'value', 2); @@ -64,6 +66,12 @@ public function testGet() $this->assertNull($this->memcachedHandler->get(self::$key1)); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testRemember() { $this->memcachedHandler->remember(self::$key1, 2, function () { diff --git a/tests/system/Cache/Handlers/PredisHandlerTest.php b/tests/system/Cache/Handlers/PredisHandlerTest.php index 960098b76121..23e294ddb18a 100644 --- a/tests/system/Cache/Handlers/PredisHandlerTest.php +++ b/tests/system/Cache/Handlers/PredisHandlerTest.php @@ -6,7 +6,7 @@ use CodeIgniter\Test\CIUnitTestCase; use Config\Cache; -class PredisHandlerTest extends CIUnitTestCase +final class PredisHandlerTest extends CIUnitTestCase { private $PredisHandler; private static $key1 = 'key1'; @@ -32,10 +32,6 @@ protected function setUp(): void $this->config = new Cache(); $this->PredisHandler = new PredisHandler($this->config); - if (! $this->PredisHandler->isSupported()) - { - $this->markTestSkipped('Not support Predis'); - } $this->PredisHandler->initialize(); } @@ -61,6 +57,12 @@ public function testDestruct() $this->assertInstanceOf(PRedisHandler::class, $this->PredisHandler); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testGet() { $this->PredisHandler->save(self::$key1, 'value', 2); @@ -72,6 +74,12 @@ public function testGet() $this->assertNull($this->PredisHandler->get(self::$key1)); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testRemember() { $this->PredisHandler->remember(self::$key1, 2, function () { diff --git a/tests/system/Cache/Handlers/RedisHandlerTest.php b/tests/system/Cache/Handlers/RedisHandlerTest.php index a2ab6a463780..36cab2d0c0d4 100644 --- a/tests/system/Cache/Handlers/RedisHandlerTest.php +++ b/tests/system/Cache/Handlers/RedisHandlerTest.php @@ -6,7 +6,7 @@ use CodeIgniter\Test\CIUnitTestCase; use Config\Cache; -class RedisHandlerTest extends CIUnitTestCase +final class RedisHandlerTest extends CIUnitTestCase { private $redisHandler; private static $key1 = 'key1'; @@ -32,10 +32,6 @@ protected function setUp(): void $this->config = new Cache(); $this->redisHandler = new RedisHandler($this->config); - if (! $this->redisHandler->isSupported()) - { - $this->markTestSkipped('Not support redis'); - } $this->redisHandler->initialize(); } @@ -61,6 +57,12 @@ public function testDestruct() $this->assertInstanceOf(RedisHandler::class, $this->redisHandler); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testGet() { $this->redisHandler->save(self::$key1, 'value', 2); @@ -72,6 +74,12 @@ public function testGet() $this->assertNull($this->redisHandler->get(self::$key1)); } + /** + * This test waits for 3 seconds before last assertion so this + * is naturally a "slow" test on the perspective of the default limit. + * + * @timeLimit 3.5 + */ public function testRemember() { $this->redisHandler->remember(self::$key1, 2, function () { diff --git a/tests/system/Debug/TimerTest.php b/tests/system/Debug/TimerTest.php index 34ec2c1e572a..d637c27a35e7 100644 --- a/tests/system/Debug/TimerTest.php +++ b/tests/system/Debug/TimerTest.php @@ -1,27 +1,17 @@ assertGreaterThanOrEqual(1.0, $timers['test1']['duration']); } - //-------------------------------------------------------------------- - + /** + * @timeLimit 1.5 + */ public function testAutoCalcsTimerEnd() { $timer = new Timer(); @@ -59,8 +50,9 @@ public function testAutoCalcsTimerEnd() $this->assertGreaterThanOrEqual(1.0, $timers['test1']['duration']); } - //-------------------------------------------------------------------- - + /** + * @timeLimit 1.5 + */ public function testElapsedTimeGivesSameResultAsTimersArray() { $timer = new Timer(); @@ -76,8 +68,6 @@ public function testElapsedTimeGivesSameResultAsTimersArray() $this->assertEquals($expected, $timer->getElapsedTime('test1')); } - //-------------------------------------------------------------------- - public function testThrowsExceptionStoppingNonTimer() { $this->expectException('RunTimeException'); @@ -87,8 +77,6 @@ public function testThrowsExceptionStoppingNonTimer() $timer->stop('test1'); } - //-------------------------------------------------------------------- - public function testLongExecutionTime() { $timer = new Timer(); @@ -96,8 +84,6 @@ public function testLongExecutionTime() $this->assertCloseEnough(11 * 60, $timer->getElapsedTime('longjohn')); } - //-------------------------------------------------------------------- - public function testLongExecutionTimeThroughCommonFunc() { $timer = new Timer(); @@ -105,8 +91,9 @@ public function testLongExecutionTimeThroughCommonFunc() $this->assertCloseEnough(11 * 60, $timer->getElapsedTime('longjohn')); } - //-------------------------------------------------------------------- - + /** + * @timeLimit 1.5 + */ public function testCommonStartStop() { timer('test1'); @@ -116,14 +103,10 @@ public function testCommonStartStop() $this->assertGreaterThanOrEqual(1.0, timer()->getElapsedTime('test1')); } - //-------------------------------------------------------------------- - public function testReturnsNullGettingElapsedTimeOfNonTimer() { $timer = new Timer(); $this->assertNull($timer->getElapsedTime('test1')); } - - //-------------------------------------------------------------------- } From be8b803417378935a99df0e9e712141f59c1f9bb Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 22 May 2021 09:06:19 +0700 Subject: [PATCH 14/53] [Rector] Add custom Rector Rule: RemoveErrorSuppressInTryCatchStmtsRector rector rule --- rector.php | 2 + system/Helpers/filesystem_helper.php | 18 ++--- ...moveErrorSuppressInTryCatchStmtsRector.php | 68 +++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php diff --git a/rector.php b/rector.php index 591e4e6784cf..b1518c82ed7c 100644 --- a/rector.php +++ b/rector.php @@ -27,6 +27,7 @@ use Rector\Set\ValueObject\SetList; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Utils\Rector\PassStrictParameterToFunctionParameterRector; +use Utils\Rector\RemoveErrorSuppressInTryCatchStmtsRector; use Utils\Rector\UnderscoreToCamelCaseVariableNameRector; return static function (ContainerConfigurator $containerConfigurator): void { @@ -84,4 +85,5 @@ $services->set(ChangeArrayPushToArrayAssignRector::class); $services->set(UnnecessaryTernaryExpressionRector::class); $services->set(RemoveUnusedPrivatePropertyRector::class); + $services->set(RemoveErrorSuppressInTryCatchStmtsRector::class); }; diff --git a/system/Helpers/filesystem_helper.php b/system/Helpers/filesystem_helper.php index 5499c5d6430c..c39d8974f2f2 100644 --- a/system/Helpers/filesystem_helper.php +++ b/system/Helpers/filesystem_helper.php @@ -81,9 +81,9 @@ function directory_map(string $sourceDir, int $directoryDepth = 0, bool $hidden * Recursively copies the files and directories of the origin directory * into the target directory, i.e. "mirror" its contents. * - * @param string $originDir - * @param string $targetDir - * @param bool $overwrite Whether individual files overwrite on collision + * @param string $originDir + * @param string $targetDir + * @param boolean $overwrite Whether individual files overwrite on collision * * @return void * @@ -103,7 +103,9 @@ function directory_mirror(string $originDir, string $targetDir, bool $overwrite $dirLen = strlen($originDir); - /** @var SplFileInfo $file */ + /** + * @var SplFileInfo $file + */ foreach (new RecursiveIteratorIterator( new RecursiveDirectoryIterator($originDir, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST @@ -210,12 +212,12 @@ function delete_files(string $path, bool $delDir = false, bool $htdocs = false, $isDir = $object->isDir(); if ($isDir && $delDir) { - @rmdir($object->getPathname()); + rmdir($object->getPathname()); continue; } if (! $isDir) { - @unlink($object->getPathname()); + unlink($object->getPathname()); } } } @@ -315,7 +317,7 @@ function get_dir_file_info(string $sourceDir, bool $topLevelOnly = true, bool $r try { - $fp = @opendir($sourceDir); { + $fp = opendir($sourceDir); { // reset the array and make sure $source_dir has a trailing slash on the initial call if ($recursion === false) { @@ -507,7 +509,7 @@ function octal_permissions(int $perms): string * @param string $file1 * @param string $file2 * - * @return bool Same or not + * @return boolean Same or not */ function same_file(string $file1, string $file2): bool { diff --git a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php new file mode 100644 index 000000000000..b4884836b77f --- /dev/null +++ b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php @@ -0,0 +1,68 @@ +betterNodeFinder->findParentType($node, TryCatch::class); + if (! $tryCatch instanceof TryCatch) + { + return null; + } + + // not in stmts, means it in catch or finally + $inStmts = (bool) $this->betterNodeFinder->findFirst((array) $tryCatch->stmts, function (Node $n) use ($node) : bool { + return $n === $node; + }); + + if (! $inStmts) + { + return null; + } + + // in try { ... } stmts + return $node->expr; + } +} From 4c860dc740a63b63a1fc566201b52b3bc4c2e81f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 22 May 2021 21:17:01 +0700 Subject: [PATCH 15/53] apply code review --- ...emoveErrorSuppressInTryCatchStmtsRector.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php index b4884836b77f..7af456039f3f 100644 --- a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php +++ b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php @@ -15,18 +15,18 @@ final class RemoveErrorSuppressInTryCatchStmtsRector extends AbstractRector { public function getRuleDefinition(): RuleDefinition { - return new RuleDefinition('Remove error suppress @', [ + return new RuleDefinition('Remove error suppression operator `@` inside try...catch blocks', [ new CodeSample( <<<'CODE_SAMPLE' -try { - @rmdir($dirname); -} catch (Exception $e) {} + try { + @rmdir($dirname); + } catch (Exception $e) {} CODE_SAMPLE , <<<'CODE_SAMPLE' -try { - rmdir($dirname); -} catch (Exception $e) {} + try { + rmdir($dirname); + } catch (Exception $e) {} CODE_SAMPLE ), ]); @@ -52,11 +52,11 @@ public function refactor(Node $node): ?Node return null; } - // not in stmts, means it in catch or finally - $inStmts = (bool) $this->betterNodeFinder->findFirst((array) $tryCatch->stmts, function (Node $n) use ($node) : bool { + $inStmts = (bool) $this->betterNodeFinder->findFirst((array) $tryCatch->stmts, static function (Node $n) use ($node) : bool { return $n === $node; }); + // not in stmts, means it in catch or finally if (! $inStmts) { return null; From 67d8ec3cad0980b4a55165d4dfd7d77809e8267b Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 22 May 2021 21:18:47 +0700 Subject: [PATCH 16/53] another move comment --- utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php index 7af456039f3f..7573a04122f2 100644 --- a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php +++ b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php @@ -45,8 +45,9 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - // not in try catch $tryCatch = $this->betterNodeFinder->findParentType($node, TryCatch::class); + + // not in try catch if (! $tryCatch instanceof TryCatch) { return null; From 7212c532434d64b03033a298142a469f04d8d015 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 22 May 2021 21:22:28 +0700 Subject: [PATCH 17/53] better indentation --- ...RemoveErrorSuppressInTryCatchStmtsRector.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php index 7573a04122f2..67d153e68e24 100644 --- a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php +++ b/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php @@ -18,16 +18,15 @@ public function getRuleDefinition(): RuleDefinition return new RuleDefinition('Remove error suppression operator `@` inside try...catch blocks', [ new CodeSample( <<<'CODE_SAMPLE' - try { - @rmdir($dirname); - } catch (Exception $e) {} -CODE_SAMPLE -, + try { + @rmdir($dirname); + } catch (Exception $e) {} + CODE_SAMPLE, <<<'CODE_SAMPLE' - try { - rmdir($dirname); - } catch (Exception $e) {} -CODE_SAMPLE + try { + rmdir($dirname); + } catch (Exception $e) {} + CODE_SAMPLE ), ]); } From ee2d6a1357fa6573b2e4473be9d60c8cccc00a1f Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 22 May 2021 23:42:07 +0800 Subject: [PATCH 18/53] Expand CLI detection --- system/Common.php | 46 ++++++++++++++++++++++------ tests/system/CommonFunctionsTest.php | 6 ++++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/system/Common.php b/system/Common.php index acdc66823db2..a79bd57aebc9 100644 --- a/system/Common.php +++ b/system/Common.php @@ -740,15 +740,36 @@ function helper($filenames) if (! function_exists('is_cli')) { /** - * Is CLI? - * - * Test to see if a request was made from the command line. + * Check if PHP was invoked from the command line. * * @return boolean + * + * @codeCoverageIgnore Cannot be tested fully as PHPUnit always run in CLI */ function is_cli(): bool { - return (PHP_SAPI === 'cli' || defined('STDIN')); + if (PHP_SAPI === 'cli') + { + return true; + } + + if (defined('STDIN')) + { + return true; + } + + if (stristr(PHP_SAPI, 'cgi') && getenv('TERM')) + { + return true; + } + + if (! isset($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT'])) + { + return true; + } + + // if source of request is from CLI, the `$_SERVER` array will not populate this key + return ! isset($_SERVER['REQUEST_METHOD']); } } @@ -1278,14 +1299,16 @@ function view_cell(string $library, $params = null, int $ttl = 0, string $cacheN * * @see https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/helpers.php */ -// @codeCoverageIgnoreStart if (! function_exists('class_basename')) { /** * Get the class "basename" of the given object / class. * - * @param string|object $class + * @param string|object $class + * * @return string + * + * @codeCoverageIgnore */ function class_basename($class) { @@ -1300,8 +1323,11 @@ function class_basename($class) /** * Returns all traits used by a class, its parent classes and trait of their traits. * - * @param object|string $class + * @param object|string $class + * * @return array + * + * @codeCoverageIgnore */ function class_uses_recursive($class) { @@ -1327,8 +1353,11 @@ function class_uses_recursive($class) /** * Returns all traits used by a trait and its traits. * - * @param string $trait + * @param string $trait + * * @return array + * + * @codeCoverageIgnore */ function trait_uses_recursive($trait) { @@ -1342,4 +1371,3 @@ function trait_uses_recursive($trait) return $traits; } } -// @codeCoverageIgnoreEnd diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index 0a92d5a01642..62aa4182ac60 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -507,4 +507,10 @@ public function testHelperLoadsOnce() $this->assertFalse($exception); Services::reset(); } + + public function testIsCli() + { + $this->assertIsBool(is_cli()); + $this->assertTrue(is_cli()); + } } From 029b855c774a11b1501a4dc32c4f5a79e11d5b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Sat, 22 May 2021 18:35:07 +0200 Subject: [PATCH 19/53] Add MySQL 8.0 to the test matrix --- .github/workflows/test-phpunit.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index fecd1d78b317..589d96384cc0 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -42,10 +42,15 @@ jobs: matrix: php-versions: ['7.3', '7.4', '8.0'] db-platforms: ['MySQLi', 'Postgre', 'SQLite3', 'SQLSRV'] + mysql-versions: ['5.7'] + include: + - php-versions: 7.4 + db-platforms: MySQLi + mysql-versions: 8.0 services: mysql: - image: mysql:5.7 + image: mysql:${{ matrix.mysql-versions }} env: MYSQL_ALLOW_EMPTY_PASSWORD: yes MYSQL_DATABASE: test From 5e775bc8d18624f3308ffc41d36d8a39ba58269c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Sat, 22 May 2021 00:50:17 +0200 Subject: [PATCH 20/53] Skip coveralls when running on a forked repo --- .github/workflows/test-phpunit.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index 589d96384cc0..c15f3694698d 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -138,7 +138,7 @@ jobs: DB: ${{ matrix.db-platforms }} TERM: xterm-256color - - if: matrix.php-versions == '7.4' + - if: github.repository_owner == 'codeigniter4' && matrix.php-versions == '7.4' name: Run Coveralls run: | composer global require php-coveralls/php-coveralls:^2.4 @@ -149,6 +149,7 @@ jobs: COVERALLS_FLAG_NAME: PHP ${{ matrix.php-versions }} - ${{ matrix.db-platforms }} coveralls-finish: + if: github.repository_owner == 'codeigniter4' needs: [tests] runs-on: ubuntu-20.04 steps: From 5a3625dbc52293b219ce1d3a8a5384295f756011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Sat, 22 May 2021 18:09:49 +0200 Subject: [PATCH 21/53] Don't test the max_length attribute on MySQL >= 8.0.17 As of MySQL 8.0.17, the display width attribute for integer data types is deprecated and is not reported back anymore. https://dev.mysql.com/doc/refman/8.0/en/numeric-type-attributes.html --- tests/system/Database/Live/ForgeTest.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/system/Database/Live/ForgeTest.php b/tests/system/Database/Live/ForgeTest.php index 9383b46af2bb..c7ea8fc4510b 100644 --- a/tests/system/Database/Live/ForgeTest.php +++ b/tests/system/Database/Live/ForgeTest.php @@ -249,8 +249,16 @@ public function testCreateTableWithArrayFieldConstraints() public function testCreateTableWithNullableFieldsGivesNullDataType(): void { $this->forge->addField([ - 'id' => ['type' => 'INT', 'constraint' => 11, 'auto_increment' => true], - 'name' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true], + 'id' => [ + 'type' => 'INT', + 'constraint' => 11, + 'auto_increment' => true, + ], + 'name' => [ + 'type' => 'VARCHAR', + 'constraint' => 255, + 'null' => true, + ], ]); $createTable = $this->getPrivateMethodInvoker($this->forge, '_createTable'); @@ -620,7 +628,13 @@ public function testAddFields() $this->assertEquals($fieldsData[0]->type, 'int'); $this->assertEquals($fieldsData[1]->type, 'varchar'); - $this->assertEquals($fieldsData[0]->max_length, 11); + if (version_compare($this->db->getVersion(), '8.0.17', '<')) + { + // As of MySQL 8.0.17, the display width attribute for integer data types + // is deprecated and is not reported back anymore. + // @see https://dev.mysql.com/doc/refman/8.0/en/numeric-type-attributes.html + $this->assertEquals($fieldsData[0]->max_length, 11); + } $this->assertNull($fieldsData[0]->default); $this->assertNull($fieldsData[1]->default); From da5a67866c9fed41f73e3ace4fd8e0b85d225cab Mon Sep 17 00:00:00 2001 From: MGatner Date: Sun, 23 May 2021 21:49:54 +0000 Subject: [PATCH 22/53] Ensure segment before check --- 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 560b6523e86c..40d4316bc34c 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -270,7 +270,7 @@ protected function parseRequestURI(): string foreach (explode('/', $_SERVER['SCRIPT_NAME']) as $i => $segment) { // If these segments are not the same then we're done - if ($segment !== $segments[$i]) + if (! isset($segments[$i]) || $segment !== $segments[$i]) { break; } From 7b80ba62a2502076205c09b3d5f806366d8e2f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Mon, 24 May 2021 01:03:38 +0200 Subject: [PATCH 23/53] Remove unused imports --- system/Commands/Generators/ValidationGenerator.php | 1 - system/Database/SQLSRV/Connection.php | 1 - system/Database/SQLite3/Connection.php | 1 - system/HTTP/IncomingRequest.php | 1 - system/Router/RouteCollection.php | 1 - system/Test/DatabaseTestTrait.php | 3 --- system/Test/Fabricator.php | 1 - system/Test/Mock/MockServices.php | 2 +- system/Test/TestResponse.php | 1 - 9 files changed, 1 insertion(+), 11 deletions(-) diff --git a/system/Commands/Generators/ValidationGenerator.php b/system/Commands/Generators/ValidationGenerator.php index 13fe3e2d0fc1..9a79d47f09fe 100644 --- a/system/Commands/Generators/ValidationGenerator.php +++ b/system/Commands/Generators/ValidationGenerator.php @@ -12,7 +12,6 @@ namespace CodeIgniter\Commands\Generators; use CodeIgniter\CLI\BaseCommand; -use CodeIgniter\CLI\CLI; use CodeIgniter\CLI\GeneratorTrait; /** diff --git a/system/Database/SQLSRV/Connection.php b/system/Database/SQLSRV/Connection.php index c7b6b1da28e8..9c8e42f794d2 100755 --- a/system/Database/SQLSRV/Connection.php +++ b/system/Database/SQLSRV/Connection.php @@ -11,7 +11,6 @@ namespace CodeIgniter\Database\SQLSRV; -use CodeIgniter\Database\Query; use CodeIgniter\Database\BaseConnection; use CodeIgniter\Database\Exceptions\DatabaseException; use Exception; diff --git a/system/Database/SQLite3/Connection.php b/system/Database/SQLite3/Connection.php index 3bdf1fa8d18a..4547ad7c5937 100644 --- a/system/Database/SQLite3/Connection.php +++ b/system/Database/SQLite3/Connection.php @@ -11,7 +11,6 @@ namespace CodeIgniter\Database\SQLite3; -use CodeIgniter\Database\Query; use CodeIgniter\Database\BaseConnection; use CodeIgniter\Database\Exceptions\DatabaseException; use ErrorException; diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index 560b6523e86c..422f5b9151d6 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -14,7 +14,6 @@ use CodeIgniter\HTTP\Exceptions\HTTPException; use CodeIgniter\HTTP\Files\FileCollection; use CodeIgniter\HTTP\Files\UploadedFile; -use CodeIgniter\HTTP\URI; use Config\App; use Config\Services; use InvalidArgumentException; diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 4cd4f207c173..b7d586e48907 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -13,7 +13,6 @@ use Closure; use CodeIgniter\Autoloader\FileLocator; -use CodeIgniter\HTTP\Request; use CodeIgniter\Router\Exceptions\RouterException; use Config\Modules; use Config\Services; diff --git a/system/Test/DatabaseTestTrait.php b/system/Test/DatabaseTestTrait.php index 0d2949af4806..2c8ba23a795d 100644 --- a/system/Test/DatabaseTestTrait.php +++ b/system/Test/DatabaseTestTrait.php @@ -12,10 +12,7 @@ namespace CodeIgniter\Test; use CodeIgniter\Database\BaseBuilder; -use CodeIgniter\Database\BaseConnection; use CodeIgniter\Database\Exceptions\DatabaseException; -use CodeIgniter\Database\MigrationRunner; -use CodeIgniter\Database\Seeder; use CodeIgniter\Test\Constraints\SeeInDatabase; use Config\Database; use Config\Migrations; diff --git a/system/Test/Fabricator.php b/system/Test/Fabricator.php index ef2294e0acbf..48cb2309cdd1 100644 --- a/system/Test/Fabricator.php +++ b/system/Test/Fabricator.php @@ -12,7 +12,6 @@ namespace CodeIgniter\Test; use CodeIgniter\Exceptions\FrameworkException; -use CodeIgniter\Model; use Faker\Factory; use Faker\Generator; use InvalidArgumentException; diff --git a/system/Test/Mock/MockServices.php b/system/Test/Mock/MockServices.php index 3fa1a142aea0..58fac0c1ad68 100644 --- a/system/Test/Mock/MockServices.php +++ b/system/Test/Mock/MockServices.php @@ -11,7 +11,7 @@ namespace CodeIgniter\Test\Mock; -use \CodeIgniter\Config\BaseService; +use CodeIgniter\Config\BaseService; use CodeIgniter\Autoloader\FileLocator; class MockServices extends BaseService diff --git a/system/Test/TestResponse.php b/system/Test/TestResponse.php index 4c7a655457c8..a1bacdaacd2c 100644 --- a/system/Test/TestResponse.php +++ b/system/Test/TestResponse.php @@ -16,7 +16,6 @@ use CodeIgniter\HTTP\ResponseInterface; use Config\Services; use Exception; -use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\TestCase; /** From 7e674e2cfc62dc93c4c63423aad554369eb9c567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Mon, 24 May 2021 03:55:03 +0200 Subject: [PATCH 24/53] De-duplicate seeder instantiation --- system/Database/Seeder.php | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/system/Database/Seeder.php b/system/Database/Seeder.php index 4e9b2a7b266f..6d32702f40e4 100644 --- a/system/Database/Seeder.php +++ b/system/Database/Seeder.php @@ -127,25 +127,16 @@ public static function faker(): ?Generator */ public function call(string $class) { - if (empty($class)) + $class = trim($class); + + if ($class === '') { throw new InvalidArgumentException('No seeder was specified.'); } - $path = str_replace('.php', '', $class) . '.php'; - - // If we have namespaced class, simply try to load it. - if (strpos($class, '\\') !== false) + if (strpos($class, '\\') === false) { - /** - * @var Seeder - */ - $seeder = new $class($this->config); - } - // Otherwise, try to load the class manually. - else - { - $path = $this->seedPath . $path; + $path = $this->seedPath . str_replace('.php', '', $class) . '.php'; if (! is_file($path)) { @@ -160,14 +151,13 @@ public function call(string $class) { require_once $path; } - - /** - * @var Seeder - */ - $seeder = new $class($this->config); // @codeCoverageIgnoreEnd } + /** + * @var Seeder + */ + $seeder = new $class($this->config); $seeder->setSilent($this->silent)->run(); unset($seeder); From b54e1a354ed6bc93375b84ac26c75284d3a2ad21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Mon, 24 May 2021 01:46:49 +0200 Subject: [PATCH 25/53] Remove duplicated common part --- system/Format/XMLFormatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Format/XMLFormatter.php b/system/Format/XMLFormatter.php index 1e46f6ab70b8..249f916c4308 100644 --- a/system/Format/XMLFormatter.php +++ b/system/Format/XMLFormatter.php @@ -63,15 +63,15 @@ protected function arrayToXML(array $data, &$output) { foreach ($data as $key => $value) { + $key = $this->normalizeXMLTag($key); + if (is_array($value)) { - $key = $this->normalizeXMLTag($key); $subnode = $output->addChild("$key"); $this->arrayToXML($value, $subnode); } else { - $key = $this->normalizeXMLTag($key); $output->addChild("$key", htmlspecialchars("$value")); } } From 3ee77056102b56b30c5a382f56ac52767099cde9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Mon, 24 May 2021 03:46:44 +0200 Subject: [PATCH 26/53] Replace isset() with the `??` null coalesce operator --- rector.php | 2 ++ system/CLI/CLI.php | 2 +- system/Database/Forge.php | 4 ++-- system/Database/MySQLi/Result.php | 2 +- system/Database/SQLSRV/Result.php | 2 +- system/Database/SQLite3/Result.php | 2 +- system/Database/SQLite3/Table.php | 8 ++------ system/Email/Email.php | 2 +- system/HTTP/RequestTrait.php | 2 +- system/Session/Session.php | 6 ++++-- system/View/Table.php | 6 +++--- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/rector.php b/rector.php index b1518c82ed7c..dd9d636b2fd0 100644 --- a/rector.php +++ b/rector.php @@ -22,6 +22,7 @@ use Rector\EarlyReturn\Rector\If_\ChangeIfElseValueAssignToEarlyReturnRector; use Rector\EarlyReturn\Rector\If_\RemoveAlwaysElseRector; use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector; +use Rector\Php70\Rector\Ternary\TernaryToNullCoalescingRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; use Rector\Set\ValueObject\SetList; @@ -86,4 +87,5 @@ $services->set(UnnecessaryTernaryExpressionRector::class); $services->set(RemoveUnusedPrivatePropertyRector::class); $services->set(RemoveErrorSuppressInTryCatchStmtsRector::class); + $services->set(TernaryToNullCoalescingRector::class); }; diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index 1f311adf01f6..a477f71be151 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -983,7 +983,7 @@ public static function getOption(string $name) // If the option didn't have a value, simply return TRUE // so they know it was set, otherwise return the actual value. - $val = static::$options[$name] === null ? true : static::$options[$name]; + $val = static::$options[$name] ?? true; return $val; } diff --git a/system/Database/Forge.php b/system/Database/Forge.php index a8975f17fe22..f2e2ee511067 100644 --- a/system/Database/Forge.php +++ b/system/Database/Forge.php @@ -964,8 +964,8 @@ protected function _processFields(bool $createTable = false): array $field = [ 'name' => $key, - 'new_name' => isset($attributes['NAME']) ? $attributes['NAME'] : null, - 'type' => isset($attributes['TYPE']) ? $attributes['TYPE'] : null, + 'new_name' => $attributes['NAME'] ?? null, + 'type' => $attributes['TYPE'] ?? null, 'length' => '', 'unsigned' => '', 'null' => '', diff --git a/system/Database/MySQLi/Result.php b/system/Database/MySQLi/Result.php index 5488212530bd..4be7fc9f96af 100644 --- a/system/Database/MySQLi/Result.php +++ b/system/Database/MySQLi/Result.php @@ -98,7 +98,7 @@ public function getFieldData(): array $retVal[$i] = new stdClass(); $retVal[$i]->name = $data->name; $retVal[$i]->type = $data->type; - $retVal[$i]->type_name = in_array($data->type, [1, 247], true) ? 'char' : (isset($dataTypes[$data->type]) ? $dataTypes[$data->type] : null); + $retVal[$i]->type_name = in_array($data->type, [1, 247], true) ? 'char' : ($dataTypes[$data->type] ?? null); $retVal[$i]->max_length = $data->max_length; $retVal[$i]->primary_key = (int) ($data->flags & 2); $retVal[$i]->length = $data->length; diff --git a/system/Database/SQLSRV/Result.php b/system/Database/SQLSRV/Result.php index 6dfd426375ef..f5e771e5e614 100755 --- a/system/Database/SQLSRV/Result.php +++ b/system/Database/SQLSRV/Result.php @@ -99,7 +99,7 @@ public function getFieldData(): array $retVal[$i] = new stdClass(); $retVal[$i]->name = $field['Name']; $retVal[$i]->type = $field['Type']; - $retVal[$i]->type_name = isset($dataTypes[$field['Type']]) ? $dataTypes[$field['Type']] : null; + $retVal[$i]->type_name = $dataTypes[$field['Type']] ?? null; $retVal[$i]->max_length = $field['Size']; } diff --git a/system/Database/SQLite3/Result.php b/system/Database/SQLite3/Result.php index 7d1948b0bb18..bd07eacff21f 100644 --- a/system/Database/SQLite3/Result.php +++ b/system/Database/SQLite3/Result.php @@ -76,7 +76,7 @@ public function getFieldData(): array $retVal[$i]->name = $this->resultID->columnName($i); // @phpstan-ignore-line $type = $this->resultID->columnType($i); // @phpstan-ignore-line $retVal[$i]->type = $type; - $retVal[$i]->type_name = isset($dataTypes[$type]) ? $dataTypes[$type] : null; + $retVal[$i]->type_name = $dataTypes[$type] ?? null; $retVal[$i]->max_length = null; $retVal[$i]->length = null; } diff --git a/system/Database/SQLite3/Table.php b/system/Database/SQLite3/Table.php index 296810a121d4..abfcef8db875 100644 --- a/system/Database/SQLite3/Table.php +++ b/system/Database/SQLite3/Table.php @@ -301,12 +301,8 @@ protected function copyData() foreach ($this->fields as $name => $details) { - $newFields[] = isset($details['new_name']) - // Are we modifying the column? - ? $details['new_name'] - : $name; - - $exFields[] = $name; + $newFields[] = $details['new_name'] ?? $name; + $exFields[] = $name; } $exFields = implode(', ', $exFields); diff --git a/system/Email/Email.php b/system/Email/Email.php index a3c3b274da9a..eddde1426b2c 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -1432,7 +1432,7 @@ protected function appendAttachments(&$body, $boundary, $multipart = null) { continue; } - $name = isset($attachment['name'][1]) ? $attachment['name'][1] : basename($attachment['name'][0]); + $name = $attachment['name'][1] ?? basename($attachment['name'][0]); $body .= '--' . $boundary . $this->newline . 'Content-Type: ' . $attachment['type'] . '; name="' . $name . '"' . $this->newline . 'Content-Disposition: ' . $attachment['disposition'] . ';' . $this->newline diff --git a/system/HTTP/RequestTrait.php b/system/HTTP/RequestTrait.php index 0f4de37f9ba8..2c9a0f963e9f 100644 --- a/system/HTTP/RequestTrait.php +++ b/system/HTTP/RequestTrait.php @@ -60,7 +60,7 @@ public function getIPAddress(): string /** * @deprecated $this->proxyIPs property will be removed in the future */ - $proxyIPs = isset($this->proxyIPs) ? $this->proxyIPs : config('App')->proxyIPs; + $proxyIPs = $this->proxyIPs ?? config('App')->proxyIPs; if (! empty($proxyIPs) && ! is_array($proxyIPs)) { $proxyIPs = explode(',', str_replace(' ', '', $proxyIPs)); diff --git a/system/Session/Session.php b/system/Session/Session.php index e6cab173b263..5532dc7d48fa 100644 --- a/system/Session/Session.php +++ b/system/Session/Session.php @@ -187,7 +187,9 @@ public function __construct(SessionHandlerInterface $driver, App $config) $this->cookieSecure = $config->cookieSecure ?? $this->cookieSecure; $this->cookieSameSite = $config->cookieSameSite ?? $this->cookieSameSite; - /** @var CookieConfig */ + /** + * @var CookieConfig + */ $cookie = config('Cookie'); $this->cookie = new Cookie($this->sessionCookieName, '', [ @@ -512,7 +514,7 @@ public function set($data, $value = null) */ public function get(string $key = null) { - if (! empty($key) && (! is_null($value = isset($_SESSION[$key]) ? $_SESSION[$key] : null) || ! is_null($value = dot_array_search($key, $_SESSION ?? [])))) + if (! empty($key) && (! is_null($value = $_SESSION[$key] ?? null) || ! is_null($value = dot_array_search($key, $_SESSION ?? [])))) { return $value; } diff --git a/system/View/Table.php b/system/View/Table.php index aa1ae3659e24..ec10e75c79e7 100644 --- a/system/View/Table.php +++ b/system/View/Table.php @@ -320,7 +320,7 @@ public function generate($tableData = null) } } - $out .= $temp . (isset($heading['data']) ? $heading['data'] : '') . $this->template['heading_cell_end']; + $out .= $temp . ($heading['data'] ?? '') . $this->template['heading_cell_end']; } $out .= $this->template['heading_row_end'] . $this->newline . $this->template['thead_close'] . $this->newline; @@ -352,7 +352,7 @@ public function generate($tableData = null) } } - $cell = isset($cell['data']) ? $cell['data'] : ''; + $cell = $cell['data'] ?? ''; $out .= $temp; if ($cell === '' || $cell === null) @@ -394,7 +394,7 @@ public function generate($tableData = null) } } - $out .= $temp . (isset($footing['data']) ? $footing['data'] : '') . $this->template['footing_cell_end']; + $out .= $temp . ($footing['data'] ?? '') . $this->template['footing_cell_end']; } $out .= $this->template['footing_row_end'] . $this->newline . $this->template['tfoot_close'] . $this->newline; From 1e5b7d0b5b4d7e8d9e0e9f5c0ce89f3a93db884e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Mon, 24 May 2021 01:39:32 +0200 Subject: [PATCH 27/53] Remove explicit condition that is always true --- system/Helpers/text_helper.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/system/Helpers/text_helper.php b/system/Helpers/text_helper.php index eebe3ca17dd8..0e3baed7e434 100755 --- a/system/Helpers/text_helper.php +++ b/system/Helpers/text_helper.php @@ -122,7 +122,7 @@ function ascii_to_entities(string $str): string */ if (count($temp) === 1) { - $out .= '&#' . array_shift($temp) . ';'; + $out .= '&#' . array_shift($temp) . ';'; $count = 1; } @@ -140,9 +140,9 @@ function ascii_to_entities(string $str): string 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); - $out .= '&#' . $number . ';'; - $count = 1; - $temp = []; + $out .= '&#' . $number . ';'; + $count = 1; + $temp = []; } // If this is the last iteration, just output whatever we have elseif ($i === $s) @@ -486,7 +486,7 @@ function word_wrap(string $str, int $charlim = 76): string } // Trim the word down $temp .= mb_substr($line, 0, $charlim - 1); - $line = mb_substr($line, $charlim - 1); + $line = mb_substr($line, $charlim - 1); } // If $temp contains data it means we had to split up an over-length @@ -811,14 +811,14 @@ function excerpt(string $text, string $phrase = null, int $radius = 100, string $phrasePos = stripos($text, $phrase); $phraseLen = strlen($phrase); } - elseif (! isset($phrase)) + else { $phrasePos = $radius / 2; $phraseLen = 1; } - $pre = explode(' ', substr($text, 0, $phrasePos)); // @phpstan-ignore-line - $pos = explode(' ', substr($text, $phrasePos + $phraseLen)); // @phpstan-ignore-line + $pre = explode(' ', substr($text, 0, $phrasePos)); + $pos = explode(' ', substr($text, $phrasePos + $phraseLen)); $prev = ' '; $post = ' '; From ee176f896d8609e899f52f6971dae647ce51af46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Mon, 24 May 2021 20:39:50 +0200 Subject: [PATCH 28/53] Add missing imports --- system/Config/Factories.php | 2 +- system/Helpers/test_helper.php | 1 + system/Test/CIUnitTestCase.php | 1 + system/Test/ControllerTestTrait.php | 1 + system/Test/ControllerTester.php | 1 + system/Test/Fabricator.php | 3 ++- 6 files changed, 7 insertions(+), 2 deletions(-) diff --git a/system/Config/Factories.php b/system/Config/Factories.php index 9222e5e71ead..22a9a27b84a2 100644 --- a/system/Config/Factories.php +++ b/system/Config/Factories.php @@ -23,7 +23,7 @@ * instantiation checks. * * @method static Model models(...$arguments) - * @method static \Config\BaseConfig config(...$arguments) + * @method static BaseConfig config(...$arguments) */ class Factories { diff --git a/system/Helpers/test_helper.php b/system/Helpers/test_helper.php index c6f9bebe7577..e051d9d44eda 100644 --- a/system/Helpers/test_helper.php +++ b/system/Helpers/test_helper.php @@ -9,6 +9,7 @@ * file that was distributed with this source code. */ +use CodeIgniter\Model; use CodeIgniter\Test\Fabricator; /** diff --git a/system/Test/CIUnitTestCase.php b/system/Test/CIUnitTestCase.php index 95fea0843fba..c651aaa8d81d 100644 --- a/system/Test/CIUnitTestCase.php +++ b/system/Test/CIUnitTestCase.php @@ -14,6 +14,7 @@ use CodeIgniter\CodeIgniter; use CodeIgniter\Config\Factories; use CodeIgniter\Database\BaseConnection; +use CodeIgniter\Database\MigrationRunner; use CodeIgniter\Database\Seeder; use CodeIgniter\Events\Events; use CodeIgniter\Router\RouteCollection; diff --git a/system/Test/ControllerTestTrait.php b/system/Test/ControllerTestTrait.php index 83a520e7bc05..47810e519df3 100644 --- a/system/Test/ControllerTestTrait.php +++ b/system/Test/ControllerTestTrait.php @@ -19,6 +19,7 @@ use Config\App; use Config\Services; use InvalidArgumentException; +use Psr\Log\LoggerInterface; use Throwable; /** diff --git a/system/Test/ControllerTester.php b/system/Test/ControllerTester.php index 078d26093547..391873ac436f 100644 --- a/system/Test/ControllerTester.php +++ b/system/Test/ControllerTester.php @@ -18,6 +18,7 @@ use Config\App; use Config\Services; use InvalidArgumentException; +use Psr\Log\LoggerInterface; use Throwable; /** diff --git a/system/Test/Fabricator.php b/system/Test/Fabricator.php index 48cb2309cdd1..885f2ef42e10 100644 --- a/system/Test/Fabricator.php +++ b/system/Test/Fabricator.php @@ -12,6 +12,7 @@ namespace CodeIgniter\Test; use CodeIgniter\Exceptions\FrameworkException; +use CodeIgniter\Model; use Faker\Factory; use Faker\Generator; use InvalidArgumentException; @@ -42,7 +43,7 @@ class Fabricator /** * Model instance (can be non-framework if it follows framework design) * - * @var CodeIgniter\Model|object + * @var Model|object */ protected $model; From 54c9f45c50515e5af27c583cae5397d2896bb82c Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 25 May 2021 02:57:29 +0800 Subject: [PATCH 29/53] Fix default values for cookie flag attributes --- system/Cookie/Cookie.php | 20 ++++++++++++-------- tests/system/HTTP/ResponseCookieTest.php | 4 ++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/system/Cookie/Cookie.php b/system/Cookie/Cookie.php index f6ebf37a9847..84c7b5c0dec9 100644 --- a/system/Cookie/Cookie.php +++ b/system/Cookie/Cookie.php @@ -220,15 +220,19 @@ final public function __construct(string $name, string $value = '', array $optio unset($options['max-age']); } - // to retain backward compatibility with previous versions' fallback - $prefix = $options['prefix'] ?: self::$defaults['prefix']; - $path = $options['path'] ?: self::$defaults['path']; - $domain = $options['domain'] ?: self::$defaults['domain']; - $secure = $options['secure'] ?: self::$defaults['secure']; - $httponly = $options['httponly'] ?: self::$defaults['httponly']; + // to preserve backward compatibility with array-based cookies in previous CI versions + $prefix = $options['prefix'] ?: self::$defaults['prefix']; + $path = $options['path'] ?: self::$defaults['path']; + $domain = $options['domain'] ?: self::$defaults['domain']; + + // empty string SameSite should use the default for browsers $samesite = $options['samesite'] ?: self::$defaults['samesite']; - $this->validateName($name, $options['raw']); + $raw = $options['raw']; + $secure = $options['secure']; + $httponly = $options['httponly']; + + $this->validateName($name, $raw); $this->validatePrefix($prefix, $secure, $path, $domain); $this->validateSameSite($samesite, $secure); @@ -241,7 +245,7 @@ final public function __construct(string $name, string $value = '', array $optio $this->secure = $secure; $this->httponly = $httponly; $this->samesite = ucfirst(strtolower($samesite)); - $this->raw = $options['raw']; + $this->raw = $raw; } //========================================================================= diff --git a/tests/system/HTTP/ResponseCookieTest.php b/tests/system/HTTP/ResponseCookieTest.php index 16a90316f8c0..aaa92a57871a 100644 --- a/tests/system/HTTP/ResponseCookieTest.php +++ b/tests/system/HTTP/ResponseCookieTest.php @@ -117,9 +117,9 @@ public function testCookieHTTPOnly() $response->setCookie('foo', 'bar'); $cookie = $response->getCookie('foo'); - $this->assertTrue($cookie->isHTTPOnly()); + $this->assertFalse($cookie->isHTTPOnly()); - $response->setCookie(['name' => 'bee', 'value' => 'bop', 'httponly' => false]); + $response->setCookie(['name' => 'bee', 'value' => 'bop', 'httponly' => true]); $cookie = $response->getCookie('bee'); $this->assertTrue($cookie->isHTTPOnly()); } From 5516434e03edf9f7de6d287dc59a611225877b29 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 25 May 2021 02:58:09 +0800 Subject: [PATCH 30/53] Fix errors in cookie docs --- user_guide_src/source/libraries/cookies.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user_guide_src/source/libraries/cookies.rst b/user_guide_src/source/libraries/cookies.rst index 2558681de17b..e935c56bb1e8 100644 --- a/user_guide_src/source/libraries/cookies.rst +++ b/user_guide_src/source/libraries/cookies.rst @@ -33,7 +33,7 @@ There are currently four (4) ways to create a new ``Cookie`` value object. use CodeIgniter\Cookie\Cookie; use DateTime; - // Throw the constructor + // Using the constructor $cookie = new Cookie( 'remember_token', 'f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6', @@ -79,7 +79,7 @@ instance or an array of defaults to the static ``Cookie::setDefaults()`` method. use CodeIgniter\Cookie\Cookie; use Config\Cookie as CookieConfig; - // pass in an App instance before constructing a Cookie class + // pass in an Config\Cookie instance before constructing a Cookie class Cookie::setDefaults(new CookieConfig()); $cookie = new Cookie('login_token'); @@ -456,11 +456,11 @@ Class Reference .. php:staticmethod:: setDefaults([$config = []]) - :param App|array $config: The configuration array or instance + :param \Config\Cookie|array $config: The configuration array or instance :rtype: array :returns: The old defaults - Set the default attributes to a Cookie instance by injecting the values from the ``App`` config or an array. + Set the default attributes to a Cookie instance by injecting the values from the ``\Config\Cookie`` config or an array. .. php:staticmethod:: fromHeaderString(string $header[, bool $raw = false]) From 53ef356b1c59eb6fd4471bb3bd194dcb454a680b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?= Date: Mon, 24 May 2021 20:46:02 +0200 Subject: [PATCH 31/53] Ensure variable declarations --- system/Database/Postgre/Builder.php | 17 ++++++++++------- system/Email/Email.php | 15 ++++++++++----- system/Helpers/filesystem_helper.php | 4 +++- system/Images/Handlers/ImageMagickHandler.php | 5 +++-- system/Log/Handlers/FileHandler.php | 4 +++- system/Session/Handlers/FileHandler.php | 4 +++- system/View/Parser.php | 15 ++++++--------- 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/system/Database/Postgre/Builder.php b/system/Database/Postgre/Builder.php index d77bcb25d8c1..f23d6dc9f685 100644 --- a/system/Database/Postgre/Builder.php +++ b/system/Database/Postgre/Builder.php @@ -310,7 +310,8 @@ protected function _update(string $table, array $values): string */ protected function _updateBatch(string $table, array $values, string $index): string { - $ids = []; + $ids = []; + $final = []; foreach ($values as $val) { $ids[] = $val[$index]; @@ -319,13 +320,15 @@ protected function _updateBatch(string $table, array $values, string $index): st { if ($field !== $index) { + $final[$field] = $final[$field] ?? []; + $final[$field][] = "WHEN {$val[$index]} THEN {$val[$field]}"; } } } $cases = ''; - foreach ($final as $k => $v) // @phpstan-ignore-line + foreach ($final as $k => $v) { $cases .= "{$k} = (CASE {$index}\n" . implode("\n", $v) @@ -383,11 +386,11 @@ protected function _truncate(string $table): string * * @see https://www.postgresql.org/docs/9.2/static/functions-matching.html * - * @param string|null $prefix - * @param string $column - * @param string|null $not - * @param string $bind - * @param boolean $insensitiveSearch + * @param string|null $prefix + * @param string $column + * @param string|null $not + * @param string $bind + * @param boolean $insensitiveSearch * * @return string $like_statement */ diff --git a/system/Email/Email.php b/system/Email/Email.php index eddde1426b2c..36720ba99c59 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -1272,6 +1272,8 @@ protected function buildMessage() return; case 'html': + $boundary = uniqid('B_ALT_', true); + if ($this->sendMultipart === false) { $hdr .= 'Content-Type: text/html; charset=' @@ -1280,8 +1282,6 @@ protected function buildMessage() } else { - $boundary = uniqid('B_ALT_', true); - $hdr .= 'Content-Type: multipart/alternative; boundary="' . $boundary . '"'; $body .= $this->getMimeMessage() . $this->newline . $this->newline . '--' . $boundary . $this->newline @@ -1306,7 +1306,7 @@ protected function buildMessage() if ($this->sendMultipart !== false) { - $this->finalBody .= '--' . $boundary . '--'; // @phpstan-ignore-line + $this->finalBody .= '--' . $boundary . '--'; } return; @@ -2184,13 +2184,16 @@ protected function sendCommand($cmd, $data = '') $this->sendData('QUIT'); $resp = 221; break; + + default: + $resp = null; } $reply = $this->getSMTPData(); $this->debugMessage[] = '
' . $cmd . ': ' . $reply . '
'; - if ((int) static::substr($reply, 0, 3) !== $resp) // @phpstan-ignore-line + if ($resp === null || ((int) static::substr($reply, 0, 3) !== $resp)) { $this->setErrorMessage(lang('Email.SMTPError', [$reply])); @@ -2278,6 +2281,8 @@ protected function sendData($data) { $data .= $this->newline; + $result = null; + for ($written = $timestamp = 0, $length = static::strlen($data); $written < $length; $written += $result) { if (($result = fwrite($this->SMTPConnect, static::substr($data, $written))) === false) @@ -2307,7 +2312,7 @@ protected function sendData($data) $timestamp = 0; } - if ($result === false) // @phpstan-ignore-line + if (! is_int($result)) { $this->setErrorMessage(lang('Email.SMTPDataFailure', [$data])); diff --git a/system/Helpers/filesystem_helper.php b/system/Helpers/filesystem_helper.php index c39d8974f2f2..57355370b55d 100644 --- a/system/Helpers/filesystem_helper.php +++ b/system/Helpers/filesystem_helper.php @@ -374,6 +374,8 @@ function get_file_info(string $file, $returnedValues = ['name', 'server_path', ' return null; } + $fileInfo = []; + if (is_string($returnedValues)) { $returnedValues = explode(',', $returnedValues); @@ -409,7 +411,7 @@ function get_file_info(string $file, $returnedValues = ['name', 'server_path', ' } } - return $fileInfo; // @phpstan-ignore-line + return $fileInfo; } } diff --git a/system/Images/Handlers/ImageMagickHandler.php b/system/Images/Handlers/ImageMagickHandler.php index b43863aa64ec..80904a4b6fce 100644 --- a/system/Images/Handlers/ImageMagickHandler.php +++ b/system/Images/Handlers/ImageMagickHandler.php @@ -234,10 +234,11 @@ protected function process(string $action, int $quality = 100): array $this->config->libraryPath = rtrim($this->config->libraryPath, '/') . '/convert'; } - $cmd = $this->config->libraryPath; + $cmd = $this->config->libraryPath; $cmd .= $action === '-version' ? ' ' . $action : ' -quality ' . $quality . ' ' . $action; $retval = 1; + $output = []; // exec() might be disabled if (function_usable('exec')) { @@ -250,7 +251,7 @@ protected function process(string $action, int $quality = 100): array throw ImageException::forImageProcessFailed(); } - return $output; // @phpstan-ignore-line + return $output; } //-------------------------------------------------------------------- diff --git a/system/Log/Handlers/FileHandler.php b/system/Log/Handlers/FileHandler.php index 8b608b3692fe..362758f07581 100644 --- a/system/Log/Handlers/FileHandler.php +++ b/system/Log/Handlers/FileHandler.php @@ -112,6 +112,8 @@ public function handle($level, $message): bool flock($fp, LOCK_EX); + $result = null; + for ($written = 0, $length = strlen($msg); $written < $length; $written += $result) { if (($result = fwrite($fp, substr($msg, $written))) === false) @@ -131,7 +133,7 @@ public function handle($level, $message): bool chmod($filepath, $this->filePermissions); } - return is_int($result); // @phpstan-ignore-line + return is_int($result); } //-------------------------------------------------------------------- diff --git a/system/Session/Handlers/FileHandler.php b/system/Session/Handlers/FileHandler.php index 17ee5bf46671..dc28cd4f9822 100644 --- a/system/Session/Handlers/FileHandler.php +++ b/system/Session/Handlers/FileHandler.php @@ -240,6 +240,8 @@ public function write($sessionID, $sessionData): bool if (($length = strlen($sessionData)) > 0) { + $result = null; + for ($written = 0; $written < $length; $written += $result) { if (($result = fwrite($this->fileHandle, substr($sessionData, $written))) === false) @@ -248,7 +250,7 @@ public function write($sessionID, $sessionData): bool } } - if (! is_int($result)) // @phpstan-ignore-line + if (! is_int($result)) { $this->fingerprint = md5(substr($sessionData, 0, $written)); $this->logger->error('Session: Unable to write data.'); diff --git a/system/View/Parser.php b/system/View/Parser.php index 9bfb937067ca..b3cef4b4a1c1 100644 --- a/system/View/Parser.php +++ b/system/View/Parser.php @@ -101,16 +101,13 @@ public function render(string $view, array $options = null, bool $saveData = nul $fileExt = pathinfo($view, PATHINFO_EXTENSION); $view = empty($fileExt) ? $view . '.php' : $view; // allow Views as .html, .tpl, etc (from CI3) + $cacheName = $options['cache_name'] ?? str_replace('.php', '', $view); + // Was it cached? - if (isset($options['cache'])) + if (isset($options['cache']) && ($output = cache($cacheName))) { - $cacheName = $options['cache_name'] ?? str_replace('.php', '', $view); - - if ($output = cache($cacheName)) - { - $this->logPerformance($start, microtime(true), $view); - return $output; - } + $this->logPerformance($start, microtime(true), $view); + return $output; } $file = $this->viewPath . $view; @@ -143,7 +140,7 @@ public function render(string $view, array $options = null, bool $saveData = nul // Should we cache? if (isset($options['cache'])) { - cache()->save($cacheName, $output, (int) $options['cache']); // @phpstan-ignore-line + cache()->save($cacheName, $output, (int) $options['cache']); } $this->tempData = null; return $output; From 76fe1c737c983305c3615101eb7103d582678024 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 25 May 2021 02:21:15 +0800 Subject: [PATCH 32/53] Add environment spark command --- system/Commands/Utilities/Environment.php | 160 ++++++++++++++++++ .../Commands/EnvironmentCommandTest.php | 86 ++++++++++ 2 files changed, 246 insertions(+) create mode 100644 system/Commands/Utilities/Environment.php create mode 100644 tests/system/Commands/EnvironmentCommandTest.php diff --git a/system/Commands/Utilities/Environment.php b/system/Commands/Utilities/Environment.php new file mode 100644 index 000000000000..aa9cb8ae3aa2 --- /dev/null +++ b/system/Commands/Utilities/Environment.php @@ -0,0 +1,160 @@ +]'; + + /** + * The Command's arguments + * + * @var array + */ + protected $arguments = [ + 'environment' => '[Optional] The new environment to set. If none is provided, this will print the current environment.', + ]; + + /** + * The Command's options + * + * @var array + */ + protected $options = []; + + /** + * Allowed values for environment. `testing` is excluded + * since spark won't work on it. + * + * @var array + */ + private static $knownTypes = [ + 'production', + 'development', + ]; + + /** + * @inheritDoc + * + * @param array $params + * + * @return void + */ + public function run(array $params) + { + if ($params === []) + { + CLI::write(sprintf('Your environment is currently set as %s.', CLI::color(ENVIRONMENT, 'green'))); + CLI::newLine(); + + return; + } + + $env = strtolower(array_shift($params)); + + if ($env === 'testing') + { + CLI::error('The "testing" environment is reserved for PHPUnit testing.', 'light_gray', 'red'); + CLI::error('You will not be able to run spark under a "testing" environment.', 'light_gray', 'red'); + CLI::newLine(); + + return; + } + + if (! in_array($env, self::$knownTypes, true)) + { + CLI::error(sprintf('Invalid environment type "%s". Expected one of "%s".', $env, implode('" and "', self::$knownTypes)), 'light_gray', 'red'); + CLI::newLine(); + + return; + } + + if (! $this->writeNewEnvironmentToEnvFile($env)) + { + CLI::error('Error in writing new environment to .env file.', 'light_gray', 'red'); + CLI::newLine(); + + return; + } + + // force DotEnv to reload the new environment + // however we cannot redefine the ENVIRONMENT constant + putenv('CI_ENVIRONMENT'); + unset($_ENV['CI_ENVIRONMENT'], $_SERVER['CI_ENVIRONMENT']); + (new DotEnv(ROOTPATH))->load(); + + CLI::write(sprintf('Environment is successfully changed to "%s".', $env), 'green'); + CLI::write('The ENVIRONMENT constant will be changed on the next script execution.'); + CLI::newLine(); + } + + /** + * @see https://regex101.com/r/4sSORp/1 for the regex in action + * + * @param string $newEnv + * + * @return boolean + */ + private function writeNewEnvironmentToEnvFile(string $newEnv): bool + { + $baseEnv = ROOTPATH . 'env'; + $envFile = ROOTPATH . '.env'; + + if (! is_file($envFile)) + { + if (! is_file($baseEnv)) + { + CLI::write('Both default shipped `env` file and custom `.env` are missing.', 'yellow'); + CLI::write('It is impossible to write the new environment type.', 'yellow'); + CLI::newLine(); + + return false; + } + + copy($baseEnv, $envFile); + } + + $pattern = preg_quote($_SERVER['CI_ENVIRONMENT'] ?? ENVIRONMENT, '/'); + $pattern = sprintf('/^[#\s]*CI_ENVIRONMENT[=\s]+%s$/m', $pattern); + + return file_put_contents( + $envFile, + preg_replace($pattern, "\nCI_ENVIRONMENT = {$newEnv}", file_get_contents($envFile), -1, $count) + ) !== false && $count > 0; + } +} diff --git a/tests/system/Commands/EnvironmentCommandTest.php b/tests/system/Commands/EnvironmentCommandTest.php new file mode 100644 index 000000000000..0f30f98868be --- /dev/null +++ b/tests/system/Commands/EnvironmentCommandTest.php @@ -0,0 +1,86 @@ +streamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter'); + $this->streamFilter = stream_filter_append(STDERR, 'CITestStreamFilter'); + + if (is_file($this->envPath)) + { + rename($this->envPath, $this->backupEnvPath); + } + } + + protected function tearDown(): void + { + parent::tearDown(); + stream_filter_remove($this->streamFilter); + + if (is_file($this->envPath)) + { + unlink($this->envPath); + } + + if (is_file($this->backupEnvPath)) + { + rename($this->backupEnvPath, $this->envPath); + } + + $_SERVER['CI_ENVIRONMENT'] = $_ENV['CI_ENVIRONMENT'] = ENVIRONMENT; + } + + public function testUsingCommandWithNoArgumentsGivesCurrentEnvironment(): void + { + command('env'); + $this->assertStringContainsString('testing', CITestStreamFilter::$buffer); + $this->assertStringContainsString(ENVIRONMENT, CITestStreamFilter::$buffer); + } + + public function testProvidingTestingAsEnvGivesErrorMessage(): void + { + command('env testing'); + $this->assertStringContainsString('The "testing" environment is reserved for PHPUnit testing.', CITestStreamFilter::$buffer); + } + + public function testProvidingUnknownEnvGivesErrorMessage(): void + { + command('env foobar'); + $this->assertStringContainsString('Invalid environment type "foobar".', CITestStreamFilter::$buffer); + } + + public function testDefaultShippedEnvIsMissing() + { + rename(ROOTPATH . 'env', ROOTPATH . 'lostenv'); + command('env development'); + rename(ROOTPATH . 'lostenv', ROOTPATH . 'env'); + + $this->assertStringContainsString('Both default shipped', CITestStreamFilter::$buffer); + $this->assertStringContainsString('It is impossible to write the new environment type.', CITestStreamFilter::$buffer); + } + + public function testSettingNewEnvIsSuccess(): void + { + // default env file has `production` env in it + $_SERVER['CI_ENVIRONMENT'] = 'production'; + command('env development'); + + $this->assertStringContainsString('Environment is successfully changed to', CITestStreamFilter::$buffer); + $this->assertStringContainsString('CI_ENVIRONMENT = development', file_get_contents($this->envPath)); + } +} From d48dc2acae27be309d9924380719ecc0f3aff15c Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" <51850998+paulbalandan@users.noreply.github.com> Date: Tue, 25 May 2021 20:40:59 +0800 Subject: [PATCH 33/53] Additional check for `$argv` variable when detecting CLI --- system/Common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Common.php b/system/Common.php index a79bd57aebc9..f975ab3afa06 100644 --- a/system/Common.php +++ b/system/Common.php @@ -763,7 +763,7 @@ function is_cli(): bool return true; } - if (! isset($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT'])) + if (! isset($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']) && isset($_SERVER['argv']) && count($_SERVER['argv']) > 0) { return true; } From 93f0ffa1dc77ee24ea0f1780a379960f8f345b7a Mon Sep 17 00:00:00 2001 From: Toto Date: Tue, 25 May 2021 19:45:33 +0700 Subject: [PATCH 34/53] update return sample --- user_guide_src/source/helpers/array_helper.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/helpers/array_helper.rst b/user_guide_src/source/helpers/array_helper.rst index c8b77c464474..3ccdee76dd6d 100644 --- a/user_guide_src/source/helpers/array_helper.rst +++ b/user_guide_src/source/helpers/array_helper.rst @@ -70,7 +70,7 @@ The following functions are available: // Returns: 23 $barBaz = dot_array_search('foo.bar\.baz', $data); - // Returns: 42 + // Returns: 43 $fooBar = dot_array_search('foo\.bar.baz', $data); From 827a412a190b674a241ec233f3565fe21daaff18 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 26 May 2021 00:46:01 +0800 Subject: [PATCH 35/53] Add note to contributors about the env file --- contributing/internals.rst | 82 +++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/contributing/internals.rst b/contributing/internals.rst index 2ef86d0b563c..ba7f908f88e9 100644 --- a/contributing/internals.rst +++ b/contributing/internals.rst @@ -2,18 +2,18 @@ CodeIgniter Internals Overview ############################## -This guide should help contributors understand how the core of the framework works, -and what needs to be done when creating new functionality. Specifically, it +This guide should help contributors understand how the core of the framework works, +and what needs to be done when creating new functionality. Specifically, it details the information needed to create new packages for the core. Dependencies ============ -All packages should be designed to be completely isolated from the rest of the -packages, if possible. This will allow them to be used in projects outside of CodeIgniter. -Basically, this means that any dependencies should be kept to a minimum. +All packages should be designed to be completely isolated from the rest of the +packages, if possible. This will allow them to be used in projects outside of CodeIgniter. +Basically, this means that any dependencies should be kept to a minimum. Any dependencies must be able to be passed into the constructor. If you do need to use one -of the other core packages, you can create that in the constructor using the +of the other core packages, you can create that in the constructor using the Services class, as long as you provide a way for dependencies to override that:: public function __construct(Foo $foo=null) @@ -27,7 +27,7 @@ Type hinting ============ PHP7 provides the ability to `type hint `_ -method parameters and return types. Use it where possible. Return type hinting +method parameters and return types. Use it where possible. Return type hinting is not always practical, but do try to make it work. At this time, we are not using strict type hinting. @@ -35,9 +35,9 @@ At this time, we are not using strict type hinting. Abstractions ============ -The amount of abstraction required to implement a solution should be the minimal -amount required. Every layer of abstraction brings additional levels of technical -debt and unnecessary complexity. That said, don't be afraid to use it when it's +The amount of abstraction required to implement a solution should be the minimal +amount required. Every layer of abstraction brings additional levels of technical +debt and unnecessary complexity. That said, don't be afraid to use it when it's needed and can help things. * Don't create a new container class when an array will do just fine. @@ -46,35 +46,35 @@ needed and can help things. Testing ======= -Any new packages submitted to the framework must be accompanied by unit tests. +Any new packages submitted to the framework must be accompanied by unit tests. The target is 80%+ code coverage of all classes within the package. * Test only public methods, not protected and private unless the method really needs it due to complexity. * Don't just test that the method works, but test for all fail states, thrown exceptions, and other pathways through your code. -You should be aware of the extra assertions that we have made, provisions for -accessing private properties for testing, and mock services. +You should be aware of the extra assertions that we have made, provisions for +accessing private properties for testing, and mock services. We have also made a **CITestStreamFilter** to capture test output. -Do check out similar tests in ``tests/system/``, and read the "Testing" section +Do check out similar tests in ``tests/system/``, and read the "Testing" section in the user guide, before you dig in to your own. -Some testing needs to be done in a separate process, in order to setup the -PHP globals to mimic test situations properly. See +Some testing needs to be done in a separate process, in order to setup the +PHP globals to mimic test situations properly. See ``tests/system/HTTP/ResponseSendTest`` for an example of this. Namespaces and Files ==================== -All new packages should live under the ``CodeIgniter`` namespace. +All new packages should live under the ``CodeIgniter`` namespace. The package itself will need its own sub-namespace that collects all related files into one grouping, like ``CodeIgniter\HTTP``. -Files MUST be named the same as the class they hold, and they must match the -:doc:`Style Guide <./styleguide.rst>`, meaning CamelCase class and file names. -They should be in their own directory that matches the sub-namespace under the +Files MUST be named the same as the class they hold, and they must match the +:doc:`Style Guide <./styleguide.rst>`, meaning CamelCase class and file names. +They should be in their own directory that matches the sub-namespace under the **system** directory. -Take the Router class as an example. The Router lives in the ``CodeIgniter\Router`` +Take the Router class as an example. The Router lives in the ``CodeIgniter\Router`` namespace. Its two main classes, **RouteCollection** and **Router**, are in the files **system/Router/RouteCollection.php** and **system/Router/Router.php** respectively. @@ -82,10 +82,10 @@ namespace. Its two main classes, Interfaces ---------- -Most base classes should have an interface defined for them. +Most base classes should have an interface defined for them. At the very least this allows them to be easily mocked -and passed to other classes as a dependency, without breaking the type-hinting. -The interface names should match the name of the class with "Interface" appended +and passed to other classes as a dependency, without breaking the type-hinting. +The interface names should match the name of the class with "Interface" appended to it, like ``RouteCollectionInterface``. The Router package mentioned above includes the @@ -95,8 +95,8 @@ interfaces to provide the abstractions for the two classes in the package. Handlers -------- -When a package supports multiple "drivers", the convention is to place them in -a **Handlers** directory, and name the child classes as Handlers. +When a package supports multiple "drivers", the convention is to place them in +a **Handlers** directory, and name the child classes as Handlers. You will often find that creating a ``BaseHandler``, that the child classes can extend, to be beneficial in keeping the code DRY. @@ -105,27 +105,27 @@ See the Log and Session packages for examples. Configuration ============= -Should the package require user-configurable settings, you should create a new -file just for that package under **app/Config**. +Should the package require user-configurable settings, you should create a new +file just for that package under **app/Config**. The file name should generally match the package name. Autoloader ========== -All files within the package should be added to **system/Config/AutoloadConfig.php**, -in the "classmap" property. This is only used for core framework files, and helps +All files within the package should be added to **system/Config/AutoloadConfig.php**, +in the "classmap" property. This is only used for core framework files, and helps to minimize file system scans and keep performance high. Command-Line Support ==================== -CodeIgniter has never been known for it's strong CLI support. However, if your -package could benefit from it, create a new file under **system/Commands**. +CodeIgniter has never been known for it's strong CLI support. However, if your +package could benefit from it, create a new file under **system/Commands**. The class contained within is simply a controller that is intended for CLI -usage only. The ``index()`` method should provide a list of available commands +usage only. The ``index()`` method should provide a list of available commands provided by that package. -Routes must be added to **system/Config/Routes.php** using the ``cli()`` method +Routes must be added to **system/Config/Routes.php** using the ``cli()`` method to ensure it is not accessible through the browser, but is restricted to the CLI only. See the **MigrationsCommand** file for an example. @@ -133,6 +133,16 @@ See the **MigrationsCommand** file for an example. Documentation ============= -All packages must contain appropriate documentation that matches the tone and -style of the rest of the user guide. In most cases, the top portion of the package's +All packages must contain appropriate documentation that matches the tone and +style of the rest of the user guide. In most cases, the top portion of the package's page should be treated in tutorial fashion, while the second half would be a class reference. + +Modification of the ``env`` file +================================ + +CodeIgniter is shipped with a template ``env`` file to support adding secrets too sensitive to +be stored in a version control system. Contributors adding new entries to the env file should +always ensure that these entries are commented, i.e., starting with a hash (``#``). This is +because we have spark commands that actually copy the template file to a ``.env`` file (which +is actually the live version actually read by CodeIgniter for secrets) if the latter is missing. +As much as possible, we do not want settings to go live unexpectedly without the user's knowledge. From 2e96bdeda72f59a82ec294083efc3aed38b9f984 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 26 May 2021 00:49:26 +0800 Subject: [PATCH 36/53] Check $_SERVER first for env value --- system/Commands/Utilities/Environment.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Commands/Utilities/Environment.php b/system/Commands/Utilities/Environment.php index aa9cb8ae3aa2..1fa4331cce87 100644 --- a/system/Commands/Utilities/Environment.php +++ b/system/Commands/Utilities/Environment.php @@ -79,7 +79,7 @@ public function run(array $params) { if ($params === []) { - CLI::write(sprintf('Your environment is currently set as %s.', CLI::color(ENVIRONMENT, 'green'))); + CLI::write(sprintf('Your environment is currently set as %s.', CLI::color($_SERVER['CI_ENVIRONMENT'] ?? ENVIRONMENT, 'green'))); CLI::newLine(); return; @@ -119,7 +119,7 @@ public function run(array $params) (new DotEnv(ROOTPATH))->load(); CLI::write(sprintf('Environment is successfully changed to "%s".', $env), 'green'); - CLI::write('The ENVIRONMENT constant will be changed on the next script execution.'); + CLI::write('The ENVIRONMENT constant will be changed in the next script execution.'); CLI::newLine(); } From 6d20b53eb4eef8115bef56b544fe9e10defbf01c Mon Sep 17 00:00:00 2001 From: MGatner Date: Tue, 25 May 2021 17:53:30 +0000 Subject: [PATCH 37/53] Add default TTL --- app/Config/Cache.php | 15 +++++++++++++++ user_guide_src/source/libraries/caching.rst | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/app/Config/Cache.php b/app/Config/Cache.php index a3b3bbcf895d..e5711a35fbca 100644 --- a/app/Config/Cache.php +++ b/app/Config/Cache.php @@ -82,6 +82,21 @@ class Cache extends BaseConfig */ public $prefix = ''; + /** + * -------------------------------------------------------------------------- + * Default TTL + * -------------------------------------------------------------------------- + * + * The default number of seconds to save items when none is specified. + * + * WARNING: This is not used by framework handlers where 60 seconds is + * hard-coded, but may be useful to projects and modules. This will replace + * the hard-coded value in a future release. + * + * @var integer + */ + public $ttl = 60; + /** * -------------------------------------------------------------------------- * File settings diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst index 058dc824645c..87d213839f5f 100644 --- a/user_guide_src/source/libraries/caching.rst +++ b/user_guide_src/source/libraries/caching.rst @@ -59,6 +59,12 @@ more complex, multi-server setups. If you have more than one application using the same cache storage, you can add a custom prefix string here that is prepended to all key names. +**$ttl** + +The default number of seconds to save items when none is specified. +WARNING: This is not used by framework handlers where 60 seconds is hard-coded, but may be useful +to projects and modules. This will replace the hard-coded value in a future release. + **$file** This is an array of settings specific to the ``File`` handler to determine how it should save the cache files. From ed5aa8c814964c0d648fd51866e2143f0a4d432e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 26 May 2021 13:29:51 +0700 Subject: [PATCH 38/53] [Rector] Apply Rector : ListToArrayDestructRector --- rector.php | 2 ++ system/Cache/Handlers/MemcachedHandler.php | 2 +- system/Config/DotEnv.php | 4 ++-- system/Cookie/Cookie.php | 2 +- system/Filters/Filters.php | 2 +- system/HTTP/Negotiate.php | 4 ++-- system/I18n/Time.php | 2 +- system/Images/Handlers/BaseHandler.php | 4 ++-- system/Images/Handlers/ImageMagickHandler.php | 2 +- system/Language/Language.php | 8 ++++---- system/Log/Logger.php | 2 +- system/Router/Router.php | 2 +- system/Test/DOMParser.php | 6 +++--- system/Validation/Rules.php | 4 ++-- system/View/Cell.php | 6 +++--- 15 files changed, 27 insertions(+), 25 deletions(-) diff --git a/rector.php b/rector.php index dd9d636b2fd0..b2cb189da335 100644 --- a/rector.php +++ b/rector.php @@ -23,6 +23,7 @@ use Rector\EarlyReturn\Rector\If_\RemoveAlwaysElseRector; use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector; use Rector\Php70\Rector\Ternary\TernaryToNullCoalescingRector; +use Rector\Php71\Rector\List_\ListToArrayDestructRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; use Rector\Set\ValueObject\SetList; @@ -88,4 +89,5 @@ $services->set(RemoveUnusedPrivatePropertyRector::class); $services->set(RemoveErrorSuppressInTryCatchStmtsRector::class); $services->set(TernaryToNullCoalescingRector::class); + $services->set(ListToArrayDestructRector::class); }; diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index 7452330a83c4..e6a0ce2007c0 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -351,7 +351,7 @@ public function getMetaData(string $key) return false; // This will return null in a future release } - list($data, $time, $limit) = $stored; + [$data, $time, $limit] = $stored; // Calculate the remaining time to live from the original limit $ttl = time() - $time - $limit; diff --git a/system/Config/DotEnv.php b/system/Config/DotEnv.php index 75140f05571d..54374add5c65 100644 --- a/system/Config/DotEnv.php +++ b/system/Config/DotEnv.php @@ -90,7 +90,7 @@ public function parse(): ?array // If there is an equal sign, then we know we are assigning a variable. if (strpos($line, '=') !== false) { - list($name, $value) = $this->normaliseVariable($line); + [$name, $value] = $this->normaliseVariable($line); $vars[$name] = $value; $this->setVariable($name, $value); } @@ -143,7 +143,7 @@ public function normaliseVariable(string $name, string $value = ''): array // Split our compound string into its parts. if (strpos($name, '=') !== false) { - list($name, $value) = explode('=', $name, 2); + [$name, $value] = explode('=', $name, 2); } $name = trim($name); diff --git a/system/Cookie/Cookie.php b/system/Cookie/Cookie.php index 84c7b5c0dec9..614f327d64e7 100644 --- a/system/Cookie/Cookie.php +++ b/system/Cookie/Cookie.php @@ -184,7 +184,7 @@ public static function fromHeaderString(string $cookie, bool $raw = false) { if (strpos($part, '=') !== false) { - list($attr, $val) = explode('=', $part); + [$attr, $val] = explode('=', $part); } else { diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index 0e96943a3bef..1ba881fd78c9 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -358,7 +358,7 @@ public function enableFilter(string $name, string $when = 'before') // Get parameters and clean name if (strpos($name, ':') !== false) { - list($name, $params) = explode(':', $name); + [$name, $params] = explode(':', $name); $params = explode(',', $params); array_walk($params, function (&$item) { diff --git a/system/HTTP/Negotiate.php b/system/HTTP/Negotiate.php index 4dea868d8a25..fb2608f3239e 100644 --- a/system/HTTP/Negotiate.php +++ b/system/HTTP/Negotiate.php @@ -391,8 +391,8 @@ public function matchTypes(array $acceptable, array $supported): bool { // PHPDocumentor v2 cannot parse yet the shorter list syntax, // causing no API generation for the file. - list($aType, $aSubType) = explode('/', $acceptable['value']); - list($sType, $sSubType) = explode('/', $supported['value']); + [$aType, $aSubType] = explode('/', $acceptable['value']); + [$sType, $sSubType] = explode('/', $supported['value']); // If the types don't match, we're done. if ($aType !== $sType) diff --git a/system/I18n/Time.php b/system/I18n/Time.php index 87697c673488..c50f8f4691b4 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -758,7 +758,7 @@ public function setSecond($value) */ protected function setValue(string $name, $value) { - list($year, $month, $day, $hour, $minute, $second) = explode('-', $this->format('Y-n-j-G-i-s')); + [$year, $month, $day, $hour, $minute, $second] = explode('-', $this->format('Y-n-j-G-i-s')); $$name = $value; return Time::create( diff --git a/system/Images/Handlers/BaseHandler.php b/system/Images/Handlers/BaseHandler.php index 9eb007a6c647..b721bce21a0f 100644 --- a/system/Images/Handlers/BaseHandler.php +++ b/system/Images/Handlers/BaseHandler.php @@ -638,14 +638,14 @@ public function fit(int $width, int $height = null, string $position = 'center') $origWidth = $this->image()->origWidth; $origHeight = $this->image()->origHeight; - list($cropWidth, $cropHeight) = $this->calcAspectRatio($width, $height, $origWidth, $origHeight); + [$cropWidth, $cropHeight] = $this->calcAspectRatio($width, $height, $origWidth, $origHeight); if (is_null($height)) { $height = ceil(($width / $cropWidth) * $cropHeight); } - list($x, $y) = $this->calcCropCoords($cropWidth, $cropHeight, $origWidth, $origHeight, $position); + [$x, $y] = $this->calcCropCoords($cropWidth, $cropHeight, $origWidth, $origHeight, $position); return $this->crop($cropWidth, $cropHeight, $x, $y) ->resize($width, $height); diff --git a/system/Images/Handlers/ImageMagickHandler.php b/system/Images/Handlers/ImageMagickHandler.php index 80904a4b6fce..53dc66e97fbc 100644 --- a/system/Images/Handlers/ImageMagickHandler.php +++ b/system/Images/Handlers/ImageMagickHandler.php @@ -450,7 +450,7 @@ protected function _text(string $text, array $options = []) // Color if (isset($options['color'])) { - list($r, $g, $b) = sscanf("#{$options['color']}", '#%02x%02x%02x'); + [$r, $g, $b] = sscanf("#{$options['color']}", '#%02x%02x%02x'); $cmd .= " -fill 'rgba({$r},{$g},{$b},{$options['opacity']})'"; } diff --git a/system/Language/Language.php b/system/Language/Language.php index cb66922cd339..be66b8aab5b5 100644 --- a/system/Language/Language.php +++ b/system/Language/Language.php @@ -115,15 +115,15 @@ public function getLine(string $line, array $args = []) // Parse out the file name and the actual alias. // Will load the language file and strings. - list($file, $parsedLine) = $this->parseLine($line, $this->locale); + [$file, $parsedLine] = $this->parseLine($line, $this->locale); $output = $this->getTranslationOutput($this->locale, $file, $parsedLine); if ($output === null && strpos($this->locale, '-')) { - list($locale) = explode('-', $this->locale, 2); + [$locale] = explode('-', $this->locale, 2); - list($file, $parsedLine) = $this->parseLine($line, $locale); + [$file, $parsedLine] = $this->parseLine($line, $locale); $output = $this->getTranslationOutput($locale, $file, $parsedLine); } @@ -131,7 +131,7 @@ public function getLine(string $line, array $args = []) // if still not found, try English if ($output === null) { - list($file, $parsedLine) = $this->parseLine($line, 'en'); + [$file, $parsedLine] = $this->parseLine($line, 'en'); $output = $this->getTranslationOutput('en', $file, $parsedLine); } diff --git a/system/Log/Logger.php b/system/Log/Logger.php index d3054ef0f6ed..c457545e75cf 100644 --- a/system/Log/Logger.php +++ b/system/Log/Logger.php @@ -409,7 +409,7 @@ protected function interpolate($message, array $context = []) // Allow us to log the file/line that we are logging from if (strpos($message, '{file}') !== false) { - list($file, $line) = $this->determineFile(); + [$file, $line] = $this->determineFile(); $replace['{file}'] = $file; $replace['{line}'] = $line; diff --git a/system/Router/Router.php b/system/Router/Router.php index 1980bda6e40e..dcadd8b832e2 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -716,7 +716,7 @@ protected function setRequest(array $segments = []) return; } - list($controller, $method) = array_pad(explode('::', $segments[0]), 2, null); + [$controller, $method] = array_pad(explode('::', $segments[0]), 2, null); $this->controller = $controller; diff --git a/system/Test/DOMParser.php b/system/Test/DOMParser.php index ab8616756d34..4938fdfed0b7 100644 --- a/system/Test/DOMParser.php +++ b/system/Test/DOMParser.php @@ -296,7 +296,7 @@ public function parseSelector(string $selector) // ID? if ($pos = strpos($selector, '#') !== false) { - list($tag, $id) = explode('#', $selector); + [$tag, $id] = explode('#', $selector); } // Attribute elseif (strpos($selector, '[') !== false && strpos($selector, ']') !== false) @@ -311,7 +311,7 @@ public function parseSelector(string $selector) $text = explode(',', $text); $text = trim(array_shift($text)); - list($name, $value) = explode('=', $text); + [$name, $value] = explode('=', $text); $name = trim($name); $value = trim($value); $attr = [$name => trim($value, '] ')]; @@ -319,7 +319,7 @@ public function parseSelector(string $selector) // Class? elseif ($pos = strpos($selector, '.') !== false) { - list($tag, $class) = explode('.', $selector); + [$tag, $class] = explode('.', $selector); } // Otherwise, assume the entire string is our tag else diff --git a/system/Validation/Rules.php b/system/Validation/Rules.php index 44e77a5502a1..9f9e23d0762c 100644 --- a/system/Validation/Rules.php +++ b/system/Validation/Rules.php @@ -130,7 +130,7 @@ public function greater_than_equal_to(string $str = null, string $min): bool public function is_not_unique(string $str = null, string $field, array $data): bool { // Grab any data for exclusion of a single row. - list($field, $whereField, $whereValue) = array_pad(explode(',', $field), 3, null); + [$field, $whereField, $whereValue] = array_pad(explode(',', $field), 3, null); // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); @@ -186,7 +186,7 @@ public function in_list(string $value = null, string $list): bool public function is_unique(string $str = null, string $field, array $data): bool { // Grab any data for exclusion of a single row. - list($field, $ignoreField, $ignoreValue) = array_pad(explode(',', $field), 3, null); + [$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null); // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); diff --git a/system/View/Cell.php b/system/View/Cell.php index acb58de77735..8f753e68bae8 100644 --- a/system/View/Cell.php +++ b/system/View/Cell.php @@ -78,7 +78,7 @@ public function __construct(CacheInterface $cache) */ public function render(string $library, $params = null, int $ttl = 0, string $cacheName = null): string { - list($class, $method) = $this->determineClass($library); + [$class, $method] = $this->determineClass($library); // Is it cached? $cacheName = ! empty($cacheName) @@ -194,7 +194,7 @@ public function prepareParams($params) { if (! empty($p)) { - list($key, $val) = explode('=', $p); + [$key, $val] = explode('=', $p); $newParams[trim($key)] = trim($val, ', '); } } @@ -228,7 +228,7 @@ protected function determineClass(string $library): array // by default, so convert any double colons. $library = str_replace('::', ':', $library); - list($class, $method) = explode(':', $library); + [$class, $method] = explode(':', $library); if (empty($class)) { From f92665b3e2db719482ab7bb2966f2cb9e6024d54 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 26 May 2021 17:08:40 +0700 Subject: [PATCH 39/53] Use variable for Config/Paths config to reduce repetitive definition --- public/index.php | 3 ++- spark | 3 ++- user_guide_src/source/general/managing_apps.rst | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/public/index.php b/public/index.php index cd60baeb11eb..77373025f96d 100644 --- a/public/index.php +++ b/public/index.php @@ -17,8 +17,9 @@ // Load our paths config file // This is the line that might need to be changed, depending on your folder structure. -require realpath(FCPATH . '../app/Config/Paths.php') ?: FCPATH . '../app/Config/Paths.php'; +$pathsConfig = FCPATH . '../app/Config/Paths.php'; // ^^^ Change this if you move your application folder +require realpath($pathsConfig) ?: $pathsConfig; $paths = new Config\Paths(); diff --git a/spark b/spark index c4ad645a366b..f62aeddb2978 100755 --- a/spark +++ b/spark @@ -33,8 +33,9 @@ if (strpos(PHP_SAPI, 'cgi') === 0) define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); // Load our paths config file -require realpath('app/Config/Paths.php') ?: 'app/Config/Paths.php'; +$pathsConfig = 'app/Config/Paths.php'; // ^^^ Change this line if you move your application folder +require realpath($pathsConfig) ?: $pathsConfig; $paths = new Config\Paths(); diff --git a/user_guide_src/source/general/managing_apps.rst b/user_guide_src/source/general/managing_apps.rst index 3f412c8fa886..172c017b2233 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -23,14 +23,15 @@ they can find the ``Paths`` configuration file: - ``/spark`` runs command line apps; the path is specified on or about line 36:: - require realpath('app/Config/Paths.php') ?: 'app/Config/Paths.php'; - // ^^^ Change this if you move your application folder + $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 path is specified on or about line 20:: - require realpath(FCPATH . '../app/Config/Paths.php') ?: FCPATH . '../app/Config/Paths.php'; + // This is the line that might need to be changed, depending on your folder structure. + $pathsConfig = FCPATH . '../app/Config/Paths.php'; // ^^^ Change this if you move your application folder From d60a5b79864ac5ce5384f4be6c813bf4efb2f78d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 26 May 2021 17:15:13 +0700 Subject: [PATCH 40/53] doc fix --- 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 172c017b2233..c1781e032fa0 100644 --- a/user_guide_src/source/general/managing_apps.rst +++ b/user_guide_src/source/general/managing_apps.rst @@ -30,7 +30,6 @@ they can find the ``Paths`` configuration file: - ``/public/index.php`` is the front controller for your webapp; the config path is specified on or about line 20:: - // This is the line that might need to be changed, depending on your folder structure. $pathsConfig = FCPATH . '../app/Config/Paths.php'; // ^^^ Change this if you move your application folder From b766e46c26f0bd71ee23bbb6c8a84d08aefd16c0 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 27 May 2021 16:28:47 +0700 Subject: [PATCH 41/53] Remove $response variable at ControllerResponse as never defined --- system/Test/ControllerResponse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Test/ControllerResponse.php b/system/Test/ControllerResponse.php index 8e7cea612875..2365c35ed069 100644 --- a/system/Test/ControllerResponse.php +++ b/system/Test/ControllerResponse.php @@ -46,7 +46,7 @@ class ControllerResponse extends TestResponse */ public function __construct() { - parent::__construct($response ?? Services::response()); + parent::__construct(Services::response()); $this->dom = &$this->domParser; } From d355030944a9cea7f237d8161b964a5fdbb9b511 Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 27 May 2021 14:27:06 +0000 Subject: [PATCH 42/53] Correct attribute name, fixes #4746 --- system/Database/SQLite3/Table.php | 6 +++--- tests/system/Database/Live/SQLite/AlterTableTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/system/Database/SQLite3/Table.php b/system/Database/SQLite3/Table.php index abfcef8db875..1183f4a2ef01 100644 --- a/system/Database/SQLite3/Table.php +++ b/system/Database/SQLite3/Table.php @@ -332,9 +332,9 @@ protected function formatFields($fields) foreach ($fields as $field) { $return[$field->name] = [ - 'type' => $field->type, - 'default' => $field->default, - 'nullable' => $field->nullable, + 'type' => $field->type, + 'default' => $field->default, + 'null' => $field->nullable, ]; if ($field->primary_key) diff --git a/tests/system/Database/Live/SQLite/AlterTableTest.php b/tests/system/Database/Live/SQLite/AlterTableTest.php index 8d8f5387329e..05842cbdf53c 100644 --- a/tests/system/Database/Live/SQLite/AlterTableTest.php +++ b/tests/system/Database/Live/SQLite/AlterTableTest.php @@ -83,17 +83,17 @@ public function testFromTableFillsDetails() $this->assertCount(4, $fields); $this->assertTrue(array_key_exists('id', $fields)); $this->assertNull($fields['id']['default']); - $this->assertTrue($fields['id']['nullable']); + $this->assertTrue($fields['id']['null']); $this->assertEquals('integer', strtolower($fields['id']['type'])); $this->assertTrue(array_key_exists('name', $fields)); $this->assertNull($fields['name']['default']); - $this->assertFalse($fields['name']['nullable']); + $this->assertFalse($fields['name']['null']); $this->assertEquals('varchar', strtolower($fields['name']['type'])); $this->assertTrue(array_key_exists('email', $fields)); $this->assertNull($fields['email']['default']); - $this->assertTrue($fields['email']['nullable']); + $this->assertTrue($fields['email']['null']); $this->assertEquals('varchar', strtolower($fields['email']['type'])); $keys = $this->getPrivateProperty($this->table, 'keys'); From ab11e7a9a8e9fdb7f8cdc72d309ed9f7048fbcf6 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 30 May 2021 06:04:42 +0700 Subject: [PATCH 43/53] [Rector] Apply Rector: MoveVariableDeclarationNearReferenceRector --- composer.json | 4 ++-- rector.php | 2 ++ system/Pager/Pager.php | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 5c5816819c65..b9dac5fb3a09 100644 --- a/composer.json +++ b/composer.json @@ -19,10 +19,10 @@ "fakerphp/faker": "^1.9", "mikey179/vfsstream": "^1.6", "nexusphp/tachycardia": "^1.0", - "phpstan/phpstan": "0.12.86", + "phpstan/phpstan": "0.12.88", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.11.2", + "rector/rector": "0.11.7", "squizlabs/php_codesniffer": "^3.3", "symplify/package-builder": "^9.3" }, diff --git a/rector.php b/rector.php index b2cb189da335..3872c24584f9 100644 --- a/rector.php +++ b/rector.php @@ -11,6 +11,7 @@ use Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector; use Rector\CodeQuality\Rector\Return_\SimplifyUselessVariableRector; use Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector; +use Rector\CodeQualityStrict\Rector\Variable\MoveVariableDeclarationNearReferenceRector; use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector; use Rector\Core\Configuration\Option; use Rector\Core\ValueObject\PhpVersion; @@ -90,4 +91,5 @@ $services->set(RemoveErrorSuppressInTryCatchStmtsRector::class); $services->set(TernaryToNullCoalescingRector::class); $services->set(ListToArrayDestructRector::class); + $services->set(MoveVariableDeclarationNearReferenceRector::class); }; diff --git a/system/Pager/Pager.php b/system/Pager/Pager.php index d5f059f318ce..7b15b317e62f 100644 --- a/system/Pager/Pager.php +++ b/system/Pager/Pager.php @@ -147,12 +147,11 @@ public function makeLinks(int $page, ?int $perPage, int $total, string $template */ protected function displayLinks(string $group, string $template): string { - $pager = new PagerRenderer($this->getDetails($group)); - if (! array_key_exists($template, $this->config->templates)) { throw PagerException::forInvalidTemplate($template); } + $pager = new PagerRenderer($this->getDetails($group)); return $this->view->setVar('pager', $pager) ->render($this->config->templates[$template]); From d6ff2391c2b9d08f791910301d7ae3ea172e8c58 Mon Sep 17 00:00:00 2001 From: michalsn Date: Sun, 30 May 2021 19:57:14 +0200 Subject: [PATCH 44/53] Fix imagemagick build --- .github/workflows/test-phpunit.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index c15f3694698d..1b547fb76884 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -105,9 +105,8 @@ jobs: - name: Install latest ImageMagick run: | - sudo apt-get remove ghostscript - sudo apt-get update - sudo apt-get install -y imagemagick ghostscript-x gsfonts + 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 - name: Get composer cache directory id: composercache From a9d0ad83a7ce33f87eae4a10b849ff0a00a332bd Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 31 May 2021 10:27:13 +0700 Subject: [PATCH 45/53] [Autoloader] include_once is not needed on Autoloader::loadClass() with no namespace --- system/Autoloader/Autoloader.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 273be08c52d6..94bbd76b52ca 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -22,17 +22,17 @@ * An autoloader that uses both PSR4 autoloading, and traditional classmaps. * * Given a foo-bar package of classes in the file system at the following paths: - *``` + * ``` * /path/to/packages/foo-bar/ * /src * Baz.php # Foo\Bar\Baz * Qux/ * Quux.php # Foo\Bar\Qux\Quux - *``` + * ``` * you can add the path to the configuration array that is passed in the constructor. * The Config array consists of 2 primary keys, both of which are associative arrays: * 'psr4', and 'classmap'. - *``` + * ``` * $Config = [ * 'psr4' => [ * 'Foo\Bar' => '/path/to/packages/foo-bar' @@ -41,9 +41,9 @@ * 'MyClass' => '/path/to/class/file.php' * ] * ]; - *``` + * ``` * Example: - *``` + * ``` * register(); - *``` + * ``` */ class Autoloader { @@ -260,9 +260,9 @@ protected function loadInNamespace(string $class) { $class = 'Config\\' . $class; $filePath = APPPATH . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; - $filename = $this->includeFile($filePath); + $filename = $this->sanitizeFilename($filePath); - if ($filename) + if (is_file($filename)) { return $filename; } @@ -353,7 +353,9 @@ protected function discoverComposerNamespaces() return; } - /** @var ClassLoader $composer */ + /** + * @var ClassLoader $composer + */ $composer = include COMPOSER_PATH; $paths = $composer->getPrefixesPsr4(); $classes = $composer->getClassMap(); From 81c54543b106d83276eab2dcd761b04100beaf88 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 1 Jun 2021 07:08:04 +0700 Subject: [PATCH 46/53] return false early on non-namespaced load class --- system/Autoloader/Autoloader.php | 9 --------- tests/system/Autoloader/AutoloaderTest.php | 14 ++------------ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 94bbd76b52ca..162d898394a2 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -258,15 +258,6 @@ protected function loadInNamespace(string $class) { if (strpos($class, '\\') === false) { - $class = 'Config\\' . $class; - $filePath = APPPATH . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; - $filename = $this->sanitizeFilename($filePath); - - if (is_file($filename)) - { - return $filename; - } - return false; } diff --git a/tests/system/Autoloader/AutoloaderTest.php b/tests/system/Autoloader/AutoloaderTest.php index e8476fabdbf9..c96f60adac58 100644 --- a/tests/system/Autoloader/AutoloaderTest.php +++ b/tests/system/Autoloader/AutoloaderTest.php @@ -172,19 +172,9 @@ public function testRemoveNamespace() $this->assertFalse((bool) $this->loader->loadClass('My\App\AutoloaderTest')); } - public function testloadClassConfigFound() + public function testloadClassNonNamespaced() { - $this->loader->addNamespace('Config', APPPATH . 'Config'); - $this->assertSame( - APPPATH . 'Config' . DIRECTORY_SEPARATOR . 'Modules.php', - $this->loader->loadClass('Modules') - ); - } - - public function testloadClassConfigNotFound() - { - $this->loader->addNamespace('Config', APPPATH . 'Config'); - $this->assertFalse($this->loader->loadClass('NotFound')); + $this->assertFalse($this->loader->loadClass('Modules')); } //-------------------------------------------------------------------- From 77d7d1bd3e35afb18f7df6536c9bba37c488b592 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 1 Jun 2021 17:13:21 +0700 Subject: [PATCH 47/53] [Rector] Apply Rector: VarConstantCommentRector --- rector.php | 2 + system/Cache/Handlers/BaseHandler.php | 4 + system/Cache/Handlers/FileHandler.php | 2 + system/CodeIgniter.php | 2 + system/Cookie/CookieInterface.php | 2 + system/HTTP/ResponseInterface.php | 312 ++++++++++++++---- system/HTTP/URI.php | 2 + system/Log/Handlers/ErrorlogHandler.php | 4 + tests/system/Validation/FormatRulesTest.php | 8 +- ...rictParameterToFunctionParameterRector.php | 3 + 10 files changed, 281 insertions(+), 60 deletions(-) diff --git a/rector.php b/rector.php index 3872c24584f9..1a0e381acb84 100644 --- a/rector.php +++ b/rector.php @@ -12,6 +12,7 @@ use Rector\CodeQuality\Rector\Return_\SimplifyUselessVariableRector; use Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector; use Rector\CodeQualityStrict\Rector\Variable\MoveVariableDeclarationNearReferenceRector; +use Rector\CodingStyle\Rector\ClassConst\VarConstantCommentRector; use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector; use Rector\Core\Configuration\Option; use Rector\Core\ValueObject\PhpVersion; @@ -92,4 +93,5 @@ $services->set(TernaryToNullCoalescingRector::class); $services->set(ListToArrayDestructRector::class); $services->set(MoveVariableDeclarationNearReferenceRector::class); + $services->set(VarConstantCommentRector::class); }; diff --git a/system/Cache/Handlers/BaseHandler.php b/system/Cache/Handlers/BaseHandler.php index a5de4286f093..7d7b936940e8 100644 --- a/system/Cache/Handlers/BaseHandler.php +++ b/system/Cache/Handlers/BaseHandler.php @@ -24,11 +24,15 @@ abstract class BaseHandler implements CacheInterface /** * Reserved characters that cannot be used in a key or tag. * From https://github.com/symfony/cache-contracts/blob/c0446463729b89dd4fa62e9aeecc80287323615d/ItemInterface.php#L43 + * + * @var string */ public const RESERVED_CHARACTERS = '{}()/\@:'; /** * Maximum key length. + * + * @var int */ public const MAX_KEY_LENGTH = PHP_INT_MAX; diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index c67b2180a643..95bdfa0995b8 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -22,6 +22,8 @@ class FileHandler extends BaseHandler { /** * Maximum key length. + * + * @var int */ public const MAX_KEY_LENGTH = 255; diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index c19918aec1d9..dfef0bb27ce7 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -43,6 +43,8 @@ class CodeIgniter { /** * The current version of CodeIgniter Framework + * + * @var string */ const CI_VERSION = '4.1.2'; diff --git a/system/Cookie/CookieInterface.php b/system/Cookie/CookieInterface.php index 1dddb13a1426..1984432610be 100644 --- a/system/Cookie/CookieInterface.php +++ b/system/Cookie/CookieInterface.php @@ -22,6 +22,8 @@ interface CookieInterface * Cookies will be sent in all contexts, i.e in responses to both * first-party and cross-origin requests. If `SameSite=None` is set, * the cookie `Secure` attribute must also be set (or the cookie will be blocked). + * + * @var string */ public const SAMESITE_NONE = 'none'; diff --git a/system/HTTP/ResponseInterface.php b/system/HTTP/ResponseInterface.php index bfa493b99987..2098cc329a39 100644 --- a/system/HTTP/ResponseInterface.php +++ b/system/HTTP/ResponseInterface.php @@ -36,77 +36,271 @@ interface ResponseInterface /** * Constants for status codes. * From https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + * + * @var int */ // Informational - const HTTP_CONTINUE = 100; + const HTTP_CONTINUE = 100; + /** + * @var int + */ const HTTP_SWITCHING_PROTOCOLS = 101; - const HTTP_PROCESSING = 102; - const HTTP_EARLY_HINTS = 103; + /** + * @var int + */ + const HTTP_PROCESSING = 102; + /** + * @var int + */ + const HTTP_EARLY_HINTS = 103; // Success - const HTTP_OK = 200; - const HTTP_CREATED = 201; - const HTTP_ACCEPTED = 202; + /** + * @var int + */ + const HTTP_OK = 200; + /** + * @var int + */ + const HTTP_CREATED = 201; + /** + * @var int + */ + const HTTP_ACCEPTED = 202; + /** + * @var int + */ const HTTP_NONAUTHORITATIVE_INFORMATION = 203; - const HTTP_NO_CONTENT = 204; - const HTTP_RESET_CONTENT = 205; - const HTTP_PARTIAL_CONTENT = 206; - const HTTP_MULTI_STATUS = 207; - const HTTP_ALREADY_REPORTED = 208; - const HTTP_IM_USED = 226; + /** + * @var int + */ + const HTTP_NO_CONTENT = 204; + /** + * @var int + */ + const HTTP_RESET_CONTENT = 205; + /** + * @var int + */ + const HTTP_PARTIAL_CONTENT = 206; + /** + * @var int + */ + const HTTP_MULTI_STATUS = 207; + /** + * @var int + */ + const HTTP_ALREADY_REPORTED = 208; + /** + * @var int + */ + const HTTP_IM_USED = 226; // Redirection - const HTTP_MULTIPLE_CHOICES = 300; - const HTTP_MOVED_PERMANENTLY = 301; - const HTTP_FOUND = 302; - const HTTP_SEE_OTHER = 303; - const HTTP_NOT_MODIFIED = 304; - const HTTP_USE_PROXY = 305; - const HTTP_SWITCH_PROXY = 306; + /** + * @var int + */ + const HTTP_MULTIPLE_CHOICES = 300; + /** + * @var int + */ + const HTTP_MOVED_PERMANENTLY = 301; + /** + * @var int + */ + const HTTP_FOUND = 302; + /** + * @var int + */ + const HTTP_SEE_OTHER = 303; + /** + * @var int + */ + const HTTP_NOT_MODIFIED = 304; + /** + * @var int + */ + const HTTP_USE_PROXY = 305; + /** + * @var int + */ + const HTTP_SWITCH_PROXY = 306; + /** + * @var int + */ const HTTP_TEMPORARY_REDIRECT = 307; + /** + * @var int + */ const HTTP_PERMANENT_REDIRECT = 308; // Client Error - const HTTP_BAD_REQUEST = 400; - const HTTP_UNAUTHORIZED = 401; - const HTTP_PAYMENT_REQUIRED = 402; - const HTTP_FORBIDDEN = 403; - const HTTP_NOT_FOUND = 404; - const HTTP_METHOD_NOT_ALLOWED = 405; - const HTTP_NOT_ACCEPTABLE = 406; - const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; - const HTTP_REQUEST_TIMEOUT = 408; - const HTTP_CONFLICT = 409; - const HTTP_GONE = 410; - const HTTP_LENGTH_REQUIRED = 411; - const HTTP_PRECONDITION_FAILED = 412; - const HTTP_PAYLOAD_TOO_LARGE = 413; - const HTTP_URI_TOO_LONG = 414; - const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; - const HTTP_RANGE_NOT_SATISFIABLE = 416; - const HTTP_EXPECTATION_FAILED = 417; - const HTTP_IM_A_TEAPOT = 418; - const HTTP_MISDIRECTED_REQUEST = 421; - const HTTP_UNPROCESSABLE_ENTITY = 422; - const HTTP_LOCKED = 423; - const HTTP_FAILED_DEPENDENCY = 424; - const HTTP_TOO_EARLY = 425; - const HTTP_UPGRADE_REQUIRED = 426; - const HTTP_PRECONDITION_REQUIRED = 428; - const HTTP_TOO_MANY_REQUESTS = 429; + /** + * @var int + */ + const HTTP_BAD_REQUEST = 400; + /** + * @var int + */ + const HTTP_UNAUTHORIZED = 401; + /** + * @var int + */ + const HTTP_PAYMENT_REQUIRED = 402; + /** + * @var int + */ + const HTTP_FORBIDDEN = 403; + /** + * @var int + */ + const HTTP_NOT_FOUND = 404; + /** + * @var int + */ + const HTTP_METHOD_NOT_ALLOWED = 405; + /** + * @var int + */ + const HTTP_NOT_ACCEPTABLE = 406; + /** + * @var int + */ + const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; + /** + * @var int + */ + const HTTP_REQUEST_TIMEOUT = 408; + /** + * @var int + */ + const HTTP_CONFLICT = 409; + /** + * @var int + */ + const HTTP_GONE = 410; + /** + * @var int + */ + const HTTP_LENGTH_REQUIRED = 411; + /** + * @var int + */ + const HTTP_PRECONDITION_FAILED = 412; + /** + * @var int + */ + const HTTP_PAYLOAD_TOO_LARGE = 413; + /** + * @var int + */ + const HTTP_URI_TOO_LONG = 414; + /** + * @var int + */ + const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; + /** + * @var int + */ + const HTTP_RANGE_NOT_SATISFIABLE = 416; + /** + * @var int + */ + const HTTP_EXPECTATION_FAILED = 417; + /** + * @var int + */ + const HTTP_IM_A_TEAPOT = 418; + /** + * @var int + */ + const HTTP_MISDIRECTED_REQUEST = 421; + /** + * @var int + */ + const HTTP_UNPROCESSABLE_ENTITY = 422; + /** + * @var int + */ + const HTTP_LOCKED = 423; + /** + * @var int + */ + const HTTP_FAILED_DEPENDENCY = 424; + /** + * @var int + */ + const HTTP_TOO_EARLY = 425; + /** + * @var int + */ + const HTTP_UPGRADE_REQUIRED = 426; + /** + * @var int + */ + const HTTP_PRECONDITION_REQUIRED = 428; + /** + * @var int + */ + const HTTP_TOO_MANY_REQUESTS = 429; + /** + * @var int + */ const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; - const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; - const HTTP_CLIENT_CLOSED_REQUEST = 499; + /** + * @var int + */ + const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + /** + * @var int + */ + const HTTP_CLIENT_CLOSED_REQUEST = 499; // Server Error - const HTTP_INTERNAL_SERVER_ERROR = 500; - const HTTP_NOT_IMPLEMENTED = 501; - const HTTP_BAD_GATEWAY = 502; - const HTTP_SERVICE_UNAVAILABLE = 503; - const HTTP_GATEWAY_TIMEOUT = 504; - const HTTP_HTTP_VERSION_NOT_SUPPORTED = 505; - const HTTP_VARIANT_ALSO_NEGOTIATES = 506; - const HTTP_INSUFFICIENT_STORAGE = 507; - const HTTP_LOOP_DETECTED = 508; - const HTTP_NOT_EXTENDED = 510; + /** + * @var int + */ + const HTTP_INTERNAL_SERVER_ERROR = 500; + /** + * @var int + */ + const HTTP_NOT_IMPLEMENTED = 501; + /** + * @var int + */ + const HTTP_BAD_GATEWAY = 502; + /** + * @var int + */ + const HTTP_SERVICE_UNAVAILABLE = 503; + /** + * @var int + */ + const HTTP_GATEWAY_TIMEOUT = 504; + /** + * @var int + */ + const HTTP_HTTP_VERSION_NOT_SUPPORTED = 505; + /** + * @var int + */ + const HTTP_VARIANT_ALSO_NEGOTIATES = 506; + /** + * @var int + */ + const HTTP_INSUFFICIENT_STORAGE = 507; + /** + * @var int + */ + const HTTP_LOOP_DETECTED = 508; + /** + * @var int + */ + const HTTP_NOT_EXTENDED = 510; + /** + * @var int + */ const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; - const HTTP_NETWORK_CONNECT_TIMEOUT_ERROR = 599; + /** + * @var int + */ + const HTTP_NETWORK_CONNECT_TIMEOUT_ERROR = 599; /** * Gets the response status code. diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index 4eb1f39f0e73..fe55fe6be0ee 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -23,6 +23,7 @@ class URI * Sub-delimiters used in query strings and fragments. * * @const string + * @var string */ const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; @@ -30,6 +31,7 @@ class URI * Unreserved characters used in paths, query strings, and fragments. * * @const string + * @var string */ const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; diff --git a/system/Log/Handlers/ErrorlogHandler.php b/system/Log/Handlers/ErrorlogHandler.php index fb5d1a478327..fd744138173e 100644 --- a/system/Log/Handlers/ErrorlogHandler.php +++ b/system/Log/Handlers/ErrorlogHandler.php @@ -22,11 +22,15 @@ class ErrorlogHandler extends BaseHandler * Message is sent to PHP's system logger, using the Operating System's * system logging mechanism or a file, depending on what the error_log * configuration directive is set to. + * + * @var int */ public const TYPE_OS = 0; /** * Message is sent directly to the SAPI logging handler. + * + * @var int */ public const TYPE_SAPI = 4; diff --git a/tests/system/Validation/FormatRulesTest.php b/tests/system/Validation/FormatRulesTest.php index 8154c6035882..dd3e013842a0 100644 --- a/tests/system/Validation/FormatRulesTest.php +++ b/tests/system/Validation/FormatRulesTest.php @@ -9,7 +9,13 @@ class FormatRulesTest extends CIUnitTestCase { - const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ'; + /** + * @var string + */ + const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ'; + /** + * @var string + */ const ALPHANUMERIC = 'abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789'; /** diff --git a/utils/Rector/PassStrictParameterToFunctionParameterRector.php b/utils/Rector/PassStrictParameterToFunctionParameterRector.php index 0c406d70b24e..62d1877e8767 100644 --- a/utils/Rector/PassStrictParameterToFunctionParameterRector.php +++ b/utils/Rector/PassStrictParameterToFunctionParameterRector.php @@ -18,6 +18,9 @@ */ final class PassStrictParameterToFunctionParameterRector extends AbstractRector { + /** + * @var array + */ private const FUNCTION_WITH_ARG_POSITION = [ // position start from 0 'array_search' => 2, From 52a1823e589f6a9852af4efad180e8489e09403c Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 1 Jun 2021 17:43:57 +0700 Subject: [PATCH 48/53] remove @const --- system/HTTP/URI.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index fe55fe6be0ee..509621eb307a 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -22,16 +22,14 @@ class URI /** * Sub-delimiters used in query strings and fragments. * - * @const string - * @var string + * @var string */ const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; /** * Unreserved characters used in paths, query strings, and fragments. * - * @const string - * @var string + * @var string */ const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; From 3e4e4143269d608f38db30231f9dc1e2e6919be0 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 2 Jun 2021 10:29:44 +0700 Subject: [PATCH 49/53] [Rector] Remove @var from class constant by add custom Rector rule RemoveVarTagFromClassConstantRector --- rector.php | 4 +- system/Cache/Handlers/BaseHandler.php | 4 - system/Cache/Handlers/FileHandler.php | 2 - system/CodeIgniter.php | 5 - system/Cookie/CookieInterface.php | 10 - system/HTTP/ResponseInterface.php | 324 ++++-------------- system/HTTP/URI.php | 4 - system/Log/Handlers/ChromeLoggerHandler.php | 2 - system/Log/Handlers/ErrorlogHandler.php | 4 - tests/system/Validation/FormatRulesTest.php | 8 +- ...rictParameterToFunctionParameterRector.php | 3 - .../RemoveVarTagFromClassConstantRector.php | 60 ++++ ...nderscoreToCamelCaseVariableNameRector.php | 1 - 13 files changed, 126 insertions(+), 305 deletions(-) create mode 100644 utils/Rector/RemoveVarTagFromClassConstantRector.php diff --git a/rector.php b/rector.php index 1a0e381acb84..3df26ace9d06 100644 --- a/rector.php +++ b/rector.php @@ -12,7 +12,6 @@ use Rector\CodeQuality\Rector\Return_\SimplifyUselessVariableRector; use Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector; use Rector\CodeQualityStrict\Rector\Variable\MoveVariableDeclarationNearReferenceRector; -use Rector\CodingStyle\Rector\ClassConst\VarConstantCommentRector; use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector; use Rector\Core\Configuration\Option; use Rector\Core\ValueObject\PhpVersion; @@ -32,6 +31,7 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Utils\Rector\PassStrictParameterToFunctionParameterRector; use Utils\Rector\RemoveErrorSuppressInTryCatchStmtsRector; +use Utils\Rector\RemoveVarTagFromClassConstantRector; use Utils\Rector\UnderscoreToCamelCaseVariableNameRector; return static function (ContainerConfigurator $containerConfigurator): void { @@ -93,5 +93,5 @@ $services->set(TernaryToNullCoalescingRector::class); $services->set(ListToArrayDestructRector::class); $services->set(MoveVariableDeclarationNearReferenceRector::class); - $services->set(VarConstantCommentRector::class); + $services->set(RemoveVarTagFromClassConstantRector::class); }; diff --git a/system/Cache/Handlers/BaseHandler.php b/system/Cache/Handlers/BaseHandler.php index 7d7b936940e8..a5de4286f093 100644 --- a/system/Cache/Handlers/BaseHandler.php +++ b/system/Cache/Handlers/BaseHandler.php @@ -24,15 +24,11 @@ abstract class BaseHandler implements CacheInterface /** * Reserved characters that cannot be used in a key or tag. * From https://github.com/symfony/cache-contracts/blob/c0446463729b89dd4fa62e9aeecc80287323615d/ItemInterface.php#L43 - * - * @var string */ public const RESERVED_CHARACTERS = '{}()/\@:'; /** * Maximum key length. - * - * @var int */ public const MAX_KEY_LENGTH = PHP_INT_MAX; diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index 95bdfa0995b8..c67b2180a643 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -22,8 +22,6 @@ class FileHandler extends BaseHandler { /** * Maximum key length. - * - * @var int */ public const MAX_KEY_LENGTH = 255; diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index dfef0bb27ce7..866ec65ec0d2 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -43,14 +43,9 @@ class CodeIgniter { /** * The current version of CodeIgniter Framework - * - * @var string */ const CI_VERSION = '4.1.2'; - /** - * @var string - */ private const MIN_PHP_VERSION = '7.3'; /** diff --git a/system/Cookie/CookieInterface.php b/system/Cookie/CookieInterface.php index 1984432610be..550323fe89aa 100644 --- a/system/Cookie/CookieInterface.php +++ b/system/Cookie/CookieInterface.php @@ -22,8 +22,6 @@ interface CookieInterface * Cookies will be sent in all contexts, i.e in responses to both * first-party and cross-origin requests. If `SameSite=None` is set, * the cookie `Secure` attribute must also be set (or the cookie will be blocked). - * - * @var string */ public const SAMESITE_NONE = 'none'; @@ -31,24 +29,18 @@ interface CookieInterface * Cookies are not sent on normal cross-site subrequests (for example to * load images or frames into a third party site), but are sent when a * user is navigating to the origin site (i.e. when following a link). - * - * @var string */ public const SAMESITE_LAX = 'lax'; /** * Cookies will only be sent in a first-party context and not be sent * along with requests initiated by third party websites. - * - * @var string */ public const SAMESITE_STRICT = 'strict'; /** * RFC 6265 allowed values for the "SameSite" attribute. * - * @var string[] - * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite */ public const ALLOWED_SAMESITE_VALUES = [ @@ -60,8 +52,6 @@ interface CookieInterface /** * Expires date format. * - * @var string - * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Date * @see https://tools.ietf.org/html/rfc7231#section-7.1.1.2 */ diff --git a/system/HTTP/ResponseInterface.php b/system/HTTP/ResponseInterface.php index 2098cc329a39..c1f2ed0e5bf3 100644 --- a/system/HTTP/ResponseInterface.php +++ b/system/HTTP/ResponseInterface.php @@ -36,271 +36,73 @@ interface ResponseInterface /** * Constants for status codes. * From https://en.wikipedia.org/wiki/List_of_HTTP_status_codes - * - * @var int */ // Informational - const HTTP_CONTINUE = 100; - /** - * @var int - */ - const HTTP_SWITCHING_PROTOCOLS = 101; - /** - * @var int - */ - const HTTP_PROCESSING = 102; - /** - * @var int - */ - const HTTP_EARLY_HINTS = 103; - // Success - /** - * @var int - */ - const HTTP_OK = 200; - /** - * @var int - */ - const HTTP_CREATED = 201; - /** - * @var int - */ - const HTTP_ACCEPTED = 202; - /** - * @var int - */ - const HTTP_NONAUTHORITATIVE_INFORMATION = 203; - /** - * @var int - */ - const HTTP_NO_CONTENT = 204; - /** - * @var int - */ - const HTTP_RESET_CONTENT = 205; - /** - * @var int - */ - const HTTP_PARTIAL_CONTENT = 206; - /** - * @var int - */ - const HTTP_MULTI_STATUS = 207; - /** - * @var int - */ - const HTTP_ALREADY_REPORTED = 208; - /** - * @var int - */ - const HTTP_IM_USED = 226; - // Redirection - /** - * @var int - */ - const HTTP_MULTIPLE_CHOICES = 300; - /** - * @var int - */ - const HTTP_MOVED_PERMANENTLY = 301; - /** - * @var int - */ - const HTTP_FOUND = 302; - /** - * @var int - */ - const HTTP_SEE_OTHER = 303; - /** - * @var int - */ - const HTTP_NOT_MODIFIED = 304; - /** - * @var int - */ - const HTTP_USE_PROXY = 305; - /** - * @var int - */ - const HTTP_SWITCH_PROXY = 306; - /** - * @var int - */ - const HTTP_TEMPORARY_REDIRECT = 307; - /** - * @var int - */ - const HTTP_PERMANENT_REDIRECT = 308; - // Client Error - /** - * @var int - */ - const HTTP_BAD_REQUEST = 400; - /** - * @var int - */ - const HTTP_UNAUTHORIZED = 401; - /** - * @var int - */ - const HTTP_PAYMENT_REQUIRED = 402; - /** - * @var int - */ - const HTTP_FORBIDDEN = 403; - /** - * @var int - */ - const HTTP_NOT_FOUND = 404; - /** - * @var int - */ - const HTTP_METHOD_NOT_ALLOWED = 405; - /** - * @var int - */ - const HTTP_NOT_ACCEPTABLE = 406; - /** - * @var int - */ - const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; - /** - * @var int - */ - const HTTP_REQUEST_TIMEOUT = 408; - /** - * @var int - */ - const HTTP_CONFLICT = 409; - /** - * @var int - */ - const HTTP_GONE = 410; - /** - * @var int - */ - const HTTP_LENGTH_REQUIRED = 411; - /** - * @var int - */ - const HTTP_PRECONDITION_FAILED = 412; - /** - * @var int - */ - const HTTP_PAYLOAD_TOO_LARGE = 413; - /** - * @var int - */ - const HTTP_URI_TOO_LONG = 414; - /** - * @var int - */ - const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; - /** - * @var int - */ - const HTTP_RANGE_NOT_SATISFIABLE = 416; - /** - * @var int - */ - const HTTP_EXPECTATION_FAILED = 417; - /** - * @var int - */ - const HTTP_IM_A_TEAPOT = 418; - /** - * @var int - */ - const HTTP_MISDIRECTED_REQUEST = 421; - /** - * @var int - */ - const HTTP_UNPROCESSABLE_ENTITY = 422; - /** - * @var int - */ - const HTTP_LOCKED = 423; - /** - * @var int - */ - const HTTP_FAILED_DEPENDENCY = 424; - /** - * @var int - */ - const HTTP_TOO_EARLY = 425; - /** - * @var int - */ - const HTTP_UPGRADE_REQUIRED = 426; - /** - * @var int - */ - const HTTP_PRECONDITION_REQUIRED = 428; - /** - * @var int - */ - const HTTP_TOO_MANY_REQUESTS = 429; - /** - * @var int - */ + const HTTP_CONTINUE = 100; + const HTTP_SWITCHING_PROTOCOLS = 101; + const HTTP_PROCESSING = 102; + const HTTP_EARLY_HINTS = 103; + const HTTP_OK = 200; + const HTTP_CREATED = 201; + const HTTP_ACCEPTED = 202; + const HTTP_NONAUTHORITATIVE_INFORMATION = 203; + const HTTP_NO_CONTENT = 204; + const HTTP_RESET_CONTENT = 205; + const HTTP_PARTIAL_CONTENT = 206; + const HTTP_MULTI_STATUS = 207; + const HTTP_ALREADY_REPORTED = 208; + const HTTP_IM_USED = 226; + const HTTP_MULTIPLE_CHOICES = 300; + const HTTP_MOVED_PERMANENTLY = 301; + const HTTP_FOUND = 302; + const HTTP_SEE_OTHER = 303; + const HTTP_NOT_MODIFIED = 304; + const HTTP_USE_PROXY = 305; + const HTTP_SWITCH_PROXY = 306; + const HTTP_TEMPORARY_REDIRECT = 307; + const HTTP_PERMANENT_REDIRECT = 308; + const HTTP_BAD_REQUEST = 400; + const HTTP_UNAUTHORIZED = 401; + const HTTP_PAYMENT_REQUIRED = 402; + const HTTP_FORBIDDEN = 403; + const HTTP_NOT_FOUND = 404; + const HTTP_METHOD_NOT_ALLOWED = 405; + const HTTP_NOT_ACCEPTABLE = 406; + const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; + const HTTP_REQUEST_TIMEOUT = 408; + const HTTP_CONFLICT = 409; + const HTTP_GONE = 410; + const HTTP_LENGTH_REQUIRED = 411; + const HTTP_PRECONDITION_FAILED = 412; + const HTTP_PAYLOAD_TOO_LARGE = 413; + const HTTP_URI_TOO_LONG = 414; + const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; + const HTTP_RANGE_NOT_SATISFIABLE = 416; + const HTTP_EXPECTATION_FAILED = 417; + const HTTP_IM_A_TEAPOT = 418; + const HTTP_MISDIRECTED_REQUEST = 421; + const HTTP_UNPROCESSABLE_ENTITY = 422; + const HTTP_LOCKED = 423; + const HTTP_FAILED_DEPENDENCY = 424; + const HTTP_TOO_EARLY = 425; + const HTTP_UPGRADE_REQUIRED = 426; + const HTTP_PRECONDITION_REQUIRED = 428; + const HTTP_TOO_MANY_REQUESTS = 429; const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; - /** - * @var int - */ - const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; - /** - * @var int - */ - const HTTP_CLIENT_CLOSED_REQUEST = 499; - // Server Error - /** - * @var int - */ - const HTTP_INTERNAL_SERVER_ERROR = 500; - /** - * @var int - */ - const HTTP_NOT_IMPLEMENTED = 501; - /** - * @var int - */ - const HTTP_BAD_GATEWAY = 502; - /** - * @var int - */ - const HTTP_SERVICE_UNAVAILABLE = 503; - /** - * @var int - */ - const HTTP_GATEWAY_TIMEOUT = 504; - /** - * @var int - */ - const HTTP_HTTP_VERSION_NOT_SUPPORTED = 505; - /** - * @var int - */ - const HTTP_VARIANT_ALSO_NEGOTIATES = 506; - /** - * @var int - */ - const HTTP_INSUFFICIENT_STORAGE = 507; - /** - * @var int - */ - const HTTP_LOOP_DETECTED = 508; - /** - * @var int - */ - const HTTP_NOT_EXTENDED = 510; - /** - * @var int - */ + const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + const HTTP_CLIENT_CLOSED_REQUEST = 499; + const HTTP_INTERNAL_SERVER_ERROR = 500; + const HTTP_NOT_IMPLEMENTED = 501; + const HTTP_BAD_GATEWAY = 502; + const HTTP_SERVICE_UNAVAILABLE = 503; + const HTTP_GATEWAY_TIMEOUT = 504; + const HTTP_HTTP_VERSION_NOT_SUPPORTED = 505; + const HTTP_VARIANT_ALSO_NEGOTIATES = 506; + const HTTP_INSUFFICIENT_STORAGE = 507; + const HTTP_LOOP_DETECTED = 508; + const HTTP_NOT_EXTENDED = 510; const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; - /** - * @var int - */ - const HTTP_NETWORK_CONNECT_TIMEOUT_ERROR = 599; + const HTTP_NETWORK_CONNECT_TIMEOUT_ERROR = 599; /** * Gets the response status code. diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index 509621eb307a..3fc44343f73a 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -21,15 +21,11 @@ class URI { /** * Sub-delimiters used in query strings and fragments. - * - * @var string */ const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; /** * Unreserved characters used in paths, query strings, and fragments. - * - * @var string */ const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; diff --git a/system/Log/Handlers/ChromeLoggerHandler.php b/system/Log/Handlers/ChromeLoggerHandler.php index 73c301f91503..21a1bd71f04c 100644 --- a/system/Log/Handlers/ChromeLoggerHandler.php +++ b/system/Log/Handlers/ChromeLoggerHandler.php @@ -26,8 +26,6 @@ class ChromeLoggerHandler extends BaseHandler { /** * Version of this library - for ChromeLogger use. - * - * @var float */ const VERSION = 1.0; diff --git a/system/Log/Handlers/ErrorlogHandler.php b/system/Log/Handlers/ErrorlogHandler.php index fd744138173e..fb5d1a478327 100644 --- a/system/Log/Handlers/ErrorlogHandler.php +++ b/system/Log/Handlers/ErrorlogHandler.php @@ -22,15 +22,11 @@ class ErrorlogHandler extends BaseHandler * Message is sent to PHP's system logger, using the Operating System's * system logging mechanism or a file, depending on what the error_log * configuration directive is set to. - * - * @var int */ public const TYPE_OS = 0; /** * Message is sent directly to the SAPI logging handler. - * - * @var int */ public const TYPE_SAPI = 4; diff --git a/tests/system/Validation/FormatRulesTest.php b/tests/system/Validation/FormatRulesTest.php index dd3e013842a0..8154c6035882 100644 --- a/tests/system/Validation/FormatRulesTest.php +++ b/tests/system/Validation/FormatRulesTest.php @@ -9,13 +9,7 @@ class FormatRulesTest extends CIUnitTestCase { - /** - * @var string - */ - const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ'; - /** - * @var string - */ + const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ'; const ALPHANUMERIC = 'abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789'; /** diff --git a/utils/Rector/PassStrictParameterToFunctionParameterRector.php b/utils/Rector/PassStrictParameterToFunctionParameterRector.php index 62d1877e8767..0c406d70b24e 100644 --- a/utils/Rector/PassStrictParameterToFunctionParameterRector.php +++ b/utils/Rector/PassStrictParameterToFunctionParameterRector.php @@ -18,9 +18,6 @@ */ final class PassStrictParameterToFunctionParameterRector extends AbstractRector { - /** - * @var array - */ private const FUNCTION_WITH_ARG_POSITION = [ // position start from 0 'array_search' => 2, diff --git a/utils/Rector/RemoveVarTagFromClassConstantRector.php b/utils/Rector/RemoveVarTagFromClassConstantRector.php new file mode 100644 index 000000000000..0a4689fac17a --- /dev/null +++ b/utils/Rector/RemoveVarTagFromClassConstantRector.php @@ -0,0 +1,60 @@ +phpDocInfoFactory->createFromNodeOrEmpty($node); + $varTagValueNode = $phpDocInfo->getVarTagValueNode(); + if (! $varTagValueNode instanceof VarTagValueNode) + { + return null; + } + + $phpDocInfo->removeByType(VarTagValueNode::class); + return $node; + } +} diff --git a/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php b/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php index 5ba205ce43c2..0d670b617f26 100644 --- a/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php +++ b/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php @@ -24,7 +24,6 @@ final class UnderscoreToCamelCaseVariableNameRector extends AbstractRector { /** - * @var string * @see https://regex101.com/r/OtFn8I/1 */ private const PARAM_NAME_REGEX = '#(?@param\s.*\s+\$)(?%s)#ms'; From 8fbba76346ad867cf503934b4cf619d2fe8b1847 Mon Sep 17 00:00:00 2001 From: obelisk-services <50045374+obelisk-services@users.noreply.github.com> Date: Wed, 2 Jun 2021 20:18:49 +0200 Subject: [PATCH 50/53] Set WarningsReturnAsErrors = 0 before connection (#4762) * Set WarningsReturnAsErrors = 0 before connection If there is a warning establishing the connection, it will treat it as an error and Codeigniter will throw an exception. It should be configured prior the first sql command. * Removed extra whitespace --- system/Database/SQLSRV/Connection.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system/Database/SQLSRV/Connection.php b/system/Database/SQLSRV/Connection.php index 9c8e42f794d2..0e039a005669 100755 --- a/system/Database/SQLSRV/Connection.php +++ b/system/Database/SQLSRV/Connection.php @@ -129,12 +129,11 @@ public function connect(bool $persistent = false) unset($connection['UID'], $connection['PWD']); } + sqlsrv_configure('WarningsReturnAsErrors', 0); $this->connID = sqlsrv_connect($this->hostname, $connection); if ($this->connID !== false) { - sqlsrv_configure('WarningsReturnAsErrors', 0); - // Determine how identifiers are escaped $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); $query = $query->getResultObject(); From 3f3f5a0151af43b75f5d6244e38fd1112b0867b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Jun 2021 06:48:38 +0000 Subject: [PATCH 51/53] Update rector/rector requirement from 0.11.7 to 0.11.8 (#4772) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b9dac5fb3a09..ef2e937e7dce 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "phpstan/phpstan": "0.12.88", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.11.7", + "rector/rector": "0.11.8", "squizlabs/php_codesniffer": "^3.3", "symplify/package-builder": "^9.3" }, From a5fc431c84f9b46024716ed6c1bd35d22c6be059 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" <51850998+paulbalandan@users.noreply.github.com> Date: Fri, 4 Jun 2021 20:33:34 +0800 Subject: [PATCH 52/53] Expand Query named binds recognition (#4769) --- system/Database/Query.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Database/Query.php b/system/Database/Query.php index e548dfc189d1..ba84ac47e055 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -315,13 +315,13 @@ public function getOriginalQuery(): string * * @return void * - * @see https://regex101.com/r/EUEhay/1 Test + * @see https://regex101.com/r/EUEhay/4 */ protected function compileBinds() { $sql = $this->finalQueryString; - $hasNamedBinds = preg_match('/:[a-z\d.)_(]+:/i', $sql) === 1; + $hasNamedBinds = preg_match('/:((?!=).+):/', $sql) === 1; if (empty($this->binds) || empty($this->bindMarker) From 714049fef90de4b61c511f67842df100545d76e1 Mon Sep 17 00:00:00 2001 From: MGatner Date: Sat, 5 Jun 2021 23:55:40 +0000 Subject: [PATCH 53/53] Prep for 4.1.3 release --- CHANGELOG.md | 58 ++++++++++++++++++- system/CodeIgniter.php | 2 +- user_guide_src/source/changelogs/index.rst | 1 + user_guide_src/source/changelogs/v4.1.3.rst | 21 ++++++- user_guide_src/source/changelogs/v4.1.4.rst | 6 ++ user_guide_src/source/conf.py | 2 +- .../source/installation/upgrade_413.rst | 20 +++++++ .../source/installation/upgrading.rst | 1 + 8 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 user_guide_src/source/changelogs/v4.1.4.rst create mode 100644 user_guide_src/source/installation/upgrade_413.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index 31cf6ad44a0b..86777d7fccab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,63 @@ [Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.1.2...HEAD) -## [v4.1.2](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.2) (2021-05-17) +**Fixed bugs:** + +- Bug: Error using SQLITE3 strftime in CodeIgniter 4.1.2 [\#4760](https://github.com/codeigniter4/CodeIgniter4/issues/4760) +- Bug: Caching something through cron, is not accessible in the web application [\#4751](https://github.com/codeigniter4/CodeIgniter4/issues/4751) +- Bug: SQLite Drop Column [\#4746](https://github.com/codeigniter4/CodeIgniter4/issues/4746) +- Bug: CURL Class - BaseURI options notworking [\#4713](https://github.com/codeigniter4/CodeIgniter4/issues/4713) +- Bug: autorouting [\#4711](https://github.com/codeigniter4/CodeIgniter4/issues/4711) +- Bug: curlrequest not using baseURI on localhost [\#4707](https://github.com/codeigniter4/CodeIgniter4/issues/4707) +- Bug: cli not working with cron [\#4699](https://github.com/codeigniter4/CodeIgniter4/issues/4699) + +**Closed issues:** + +- Bug: Class 'Locale' not found [\#4775](https://github.com/codeigniter4/CodeIgniter4/issues/4775) +- Bug: deprecated notice on CodeIgniter\HTTP\RequestInterface::getMethod\(\) [\#4717](https://github.com/codeigniter4/CodeIgniter4/issues/4717) +- Allow to join models between primary keys and foreign keys [\#4714](https://github.com/codeigniter4/CodeIgniter4/issues/4714) +- DateTime::\_\_construct\(\): Failed to parse time string \(\) at position 0 \(�\): Unexpected character [\#4708](https://github.com/codeigniter4/CodeIgniter4/issues/4708) +- Bug: Query Builder breaks with SQL function LENGTH\(\) and column name "row" [\#4687](https://github.com/codeigniter4/CodeIgniter4/issues/4687) + +**Merged pull requests:** + +- Expand Query named binds recognition [\#4769](https://github.com/codeigniter4/CodeIgniter4/pull/4769) ([paulbalandan](https://github.com/paulbalandan)) +- \[Rector\] Remove @var from class constant [\#4766](https://github.com/codeigniter4/CodeIgniter4/pull/4766) ([samsonasik](https://github.com/samsonasik)) +- Set WarningsReturnAsErrors = 0 before connection [\#4762](https://github.com/codeigniter4/CodeIgniter4/pull/4762) ([obelisk-services](https://github.com/obelisk-services)) +- \[Rector\] Apply Rector: VarConstantCommentRector [\#4759](https://github.com/codeigniter4/CodeIgniter4/pull/4759) ([samsonasik](https://github.com/samsonasik)) +- \[Autoloader\] include\_once is not needed on Autoloader::loadClass\(\) with no namespace [\#4756](https://github.com/codeigniter4/CodeIgniter4/pull/4756) ([samsonasik](https://github.com/samsonasik)) +- Fix imagemagick build [\#4755](https://github.com/codeigniter4/CodeIgniter4/pull/4755) ([michalsn](https://github.com/michalsn)) +- \[Rector\] Apply Rector: MoveVariableDeclarationNearReferenceRector [\#4752](https://github.com/codeigniter4/CodeIgniter4/pull/4752) ([samsonasik](https://github.com/samsonasik)) +- SQLite3 "nullable" [\#4749](https://github.com/codeigniter4/CodeIgniter4/pull/4749) ([MGatner](https://github.com/MGatner)) +- Remove $response variable at ControllerResponse::\_\_construct\(\) as never defined [\#4747](https://github.com/codeigniter4/CodeIgniter4/pull/4747) ([samsonasik](https://github.com/samsonasik)) +- Use variable for Config/Paths config to reduce repetitive definition [\#4745](https://github.com/codeigniter4/CodeIgniter4/pull/4745) ([samsonasik](https://github.com/samsonasik)) +- \[Rector\] Apply Rector : ListToArrayDestructRector [\#4743](https://github.com/codeigniter4/CodeIgniter4/pull/4743) ([samsonasik](https://github.com/samsonasik)) +- Add default TTL [\#4742](https://github.com/codeigniter4/CodeIgniter4/pull/4742) ([MGatner](https://github.com/MGatner)) +- update return sample of `dot array\_search\(\)` [\#4740](https://github.com/codeigniter4/CodeIgniter4/pull/4740) ([totoprayogo1916](https://github.com/totoprayogo1916)) +- Additional check for `$argv` variable when detecting CLI [\#4739](https://github.com/codeigniter4/CodeIgniter4/pull/4739) ([paulbalandan](https://github.com/paulbalandan)) +- Ensure variable declarations [\#4737](https://github.com/codeigniter4/CodeIgniter4/pull/4737) ([jeromegamez](https://github.com/jeromegamez)) +- Fix setting of value in Cookie's flag attributes [\#4736](https://github.com/codeigniter4/CodeIgniter4/pull/4736) ([paulbalandan](https://github.com/paulbalandan)) +- Add missing imports [\#4735](https://github.com/codeigniter4/CodeIgniter4/pull/4735) ([jeromegamez](https://github.com/jeromegamez)) +- Add environment spark command [\#4734](https://github.com/codeigniter4/CodeIgniter4/pull/4734) ([paulbalandan](https://github.com/paulbalandan)) +- Remove explicit condition that is always true [\#4731](https://github.com/codeigniter4/CodeIgniter4/pull/4731) ([jeromegamez](https://github.com/jeromegamez)) +- Deduplicate code [\#4730](https://github.com/codeigniter4/CodeIgniter4/pull/4730) ([jeromegamez](https://github.com/jeromegamez)) +- Replace `isset\(\)` with the `??` null coalesce operator [\#4729](https://github.com/codeigniter4/CodeIgniter4/pull/4729) ([jeromegamez](https://github.com/jeromegamez)) +- Remove unused imports [\#4728](https://github.com/codeigniter4/CodeIgniter4/pull/4728) ([jeromegamez](https://github.com/jeromegamez)) +- Fix truncated SCRIPT\_NAME [\#4726](https://github.com/codeigniter4/CodeIgniter4/pull/4726) ([MGatner](https://github.com/MGatner)) +- Expand CLI detection [\#4725](https://github.com/codeigniter4/CodeIgniter4/pull/4725) ([paulbalandan](https://github.com/paulbalandan)) +- \[Rector\] Add custom Rector Rule: RemoveErrorSuppressInTryCatchStmtsRector rector rule [\#4724](https://github.com/codeigniter4/CodeIgniter4/pull/4724) ([samsonasik](https://github.com/samsonasik)) +- Test with MySQL 8 [\#4721](https://github.com/codeigniter4/CodeIgniter4/pull/4721) ([jeromegamez](https://github.com/jeromegamez)) +- Replace URI string casts [\#4716](https://github.com/codeigniter4/CodeIgniter4/pull/4716) ([MGatner](https://github.com/MGatner)) +- Format URI directly [\#4715](https://github.com/codeigniter4/CodeIgniter4/pull/4715) ([MGatner](https://github.com/MGatner)) +- Additional File functions [\#4712](https://github.com/codeigniter4/CodeIgniter4/pull/4712) ([MGatner](https://github.com/MGatner)) +- Remove unused private rowOffset property in Database/SQLSRV/Result.php [\#4709](https://github.com/codeigniter4/CodeIgniter4/pull/4709) ([samsonasik](https://github.com/samsonasik)) +- Check for configured instead of hard-coded database in DbUtilsTest [\#4705](https://github.com/codeigniter4/CodeIgniter4/pull/4705) ([jeromegamez](https://github.com/jeromegamez)) +- Revert UG margins [\#4704](https://github.com/codeigniter4/CodeIgniter4/pull/4704) ([MGatner](https://github.com/MGatner)) +- Create .git/hooks directory if not already present [\#4703](https://github.com/codeigniter4/CodeIgniter4/pull/4703) ([jeromegamez](https://github.com/jeromegamez)) +- Annotate specifically designed slow tests with custom limits [\#4698](https://github.com/codeigniter4/CodeIgniter4/pull/4698) ([paulbalandan](https://github.com/paulbalandan)) +- Cache robustness [\#4697](https://github.com/codeigniter4/CodeIgniter4/pull/4697) ([MGatner](https://github.com/MGatner)) + +## [v4.1.2](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.2) (2021-05-18) [Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.1.1...v4.1.2) diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 866ec65ec0d2..92bb010f6bd0 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -44,7 +44,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - const CI_VERSION = '4.1.2'; + const CI_VERSION = '4.1.3'; private const MIN_PHP_VERSION = '7.3'; diff --git a/user_guide_src/source/changelogs/index.rst b/user_guide_src/source/changelogs/index.rst index 51e2e2c0ebc9..038d259e4189 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.4 v4.1.3 v4.1.2 v4.1.1 diff --git a/user_guide_src/source/changelogs/v4.1.3.rst b/user_guide_src/source/changelogs/v4.1.3.rst index 379371ced12c..d041b784a9b9 100644 --- a/user_guide_src/source/changelogs/v4.1.3.rst +++ b/user_guide_src/source/changelogs/v4.1.3.rst @@ -1,6 +1,25 @@ Version 4.1.3 ============= -Release Date: Not released +Release Date: June 6, 2021 **4.1.3 release of CodeIgniter4** + +Enhancements: + +- New functions in the File Helper: ``directory_mirror()`` and ``same_file()`` +- Implemented NexusPHP's ``Tachycardia`` for slow test identification +- Added a new ``$ttl`` option to ``Cache`` config for future use + +Changes: + +- Added MySQL 8.0 to the test matrix +- Improved environment detection from ``$_SERVER`` +- Numerous sweeping code improvements via Rector and analysis + +Bugs Fixed: + +- Fixed a bug where ``CURLRequest`` would try to use a project URI instead of its base +- Fixed a bug where CLI mode was not detected under ``cgi-fcgi`` +- Fixed a logic bug in Cookie construction +- Fixed numerous issues in SQLite3's ``Forge`` class related to an incorrect attribute name diff --git a/user_guide_src/source/changelogs/v4.1.4.rst b/user_guide_src/source/changelogs/v4.1.4.rst new file mode 100644 index 000000000000..e431b242c06b --- /dev/null +++ b/user_guide_src/source/changelogs/v4.1.4.rst @@ -0,0 +1,6 @@ +Version 4.1.4 +============= + +Release Date: Not released + +**4.1.4 release of CodeIgniter4** diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py index c18880de0297..63fd4dcf46bc 100644 --- a/user_guide_src/source/conf.py +++ b/user_guide_src/source/conf.py @@ -24,7 +24,7 @@ version = '4.1' # The full version, including alpha/beta/rc tags. -release = '4.1.2' +release = '4.1.3' # -- General configuration --------------------------------------------------- diff --git a/user_guide_src/source/installation/upgrade_413.rst b/user_guide_src/source/installation/upgrade_413.rst new file mode 100644 index 000000000000..9be19f1542ab --- /dev/null +++ b/user_guide_src/source/installation/upgrade_413.rst @@ -0,0 +1,20 @@ +############################# +Upgrading from 4.1.1 to 4.1.2 +############################# + +**Cache TTL** + +There is a new value in **app/Config/Cache.php**: ``$ttl``. This is not used by framework +handlers where 60 seconds is hard-coded, but may be useful to projects and modules. +In a future release this value will replace the hard-coded version, so either leave this as +``60`` or stop relying on the hard-coded version. + +Project Files +============= + +Only a few 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. +The following files received changes and it is recommended that you merge the updated versions with your application: + +* ``app/Config/Cache.php`` +* ``spark`` diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index c3d897c79363..333f0a0f8e66 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.2 to 4.1.3 Upgrading from 4.1.1 to 4.1.2 Upgrading from 4.0.5 to 4.1.0 or 4.1.1 Upgrading from 4.0.4 to 4.0.5