From 9acc52dcdd418054a0e8e0931a10d4943864796d Mon Sep 17 00:00:00 2001 From: obozdag Date: Sat, 4 May 2024 16:33:01 +0200 Subject: [PATCH 01/83] docs: Fix typos and add missing preferences in libraries/email.rst Fix typos and add missing preferences in libraries/email.rst --- user_guide_src/source/libraries/email.rst | 92 ++++++++++++----------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index c506a9044757..4bcf84c4aec9 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -113,35 +113,39 @@ sending email. =================== =================== ============================ ======================================================================= Preference Default Value Options Description =================== =================== ============================ ======================================================================= -**userAgent** CodeIgniter None The "user agent". -**protocol** mail ``mail``, ``sendmail``, The mail sending protocol. +**$fromEmail** The email address to be set in the "from" header. +**$fromName** The name to be set in the "from" header. +**$recipients** The email addresses of the recipients, as a comma separated string or + an array +**$userAgent** CodeIgniter The "user agent". +**$protocol** mail ``mail``, ``sendmail``, The mail sending protocol. or ``smtp`` -**mailPath** /usr/sbin/sendmail None The server path to Sendmail. -**SMTPHost** No Default None SMTP Server Hostname. -**SMTPUser** No Default None SMTP Username. -**SMTPPass** No Default None SMTP Password. -**SMTPPort** 25 None SMTP Port. (If set to ``465``, TLS will be used for the connection +**$mailPath** /usr/sbin/sendmail The server path to Sendmail. +**$SMTPHost** SMTP Server Hostname. +**$SMTPUser** SMTP Username. +**$SMTPPass** SMTP Password. +**$SMTPPort** 25 SMTP Port. (If set to ``465``, TLS will be used for the connection regardless of ``SMTPCrypto`` setting.) -**SMTPTimeout** 5 None SMTP Timeout (in seconds). -**SMTPKeepAlive** false ``true``/``false`` (boolean) Enable persistent SMTP connections. -**SMTPCrypto** tls ``tls``, ``ssl``, or SMTP Encryption. Setting this to ``ssl`` will create a secure +**$SMTPTimeout** 5 SMTP Timeout (in seconds). +**$SMTPKeepAlive** false ``true``/``false`` Enable persistent SMTP connections. +**$SMTPCrypto** tls ``tls``, ``ssl``, or SMTP Encryption. Setting this to ``ssl`` will create a secure empty string (``''``) channel to the server using SSL, and ``tls`` will issue a ``STARTTLS`` command to the server. Connection on port ``465`` should set this to an empty string (``''``). See also :ref:`email-ssl-tls-for-smtp`. -**wordWrap** true ``true``/``false`` (boolean) Enable word-wrap. -**wrapChars** 76 Character count to wrap at. -**mailType** text ``text`` or ``html`` Type of mail. If you send HTML email you must send it as a complete web +**$wordWrap** true ``true``/``false`` Enable word-wrap. +**$wrapChars** 76 Character count to wrap at. +**$mailType** text ``text`` or ``html`` Type of mail. If you send HTML email you must send it as a complete web page. Make sure you don't have any relative links or relative image paths otherwise they will not work. -**charset** utf-8 Character set (``utf-8``, ``iso-8859-1``, etc.). -**validate** true ``true``/``false`` (boolean) Whether to validate the email address. -**priority** 3 1, 2, 3, 4, 5 Email Priority. ``1`` = highest. ``5`` = lowest. ``3`` = normal. -**CRLF** \\n ``\r\n`` or ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). -**newline** \\n ``\r\n`` or ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). -**BCCBatchMode** false ``true``/``false`` (boolean) Enable BCC Batch Mode. -**BCCBatchSize** 200 None Number of emails in each BCC batch. -**DSN** false ``true``/``false`` (boolean) Enable notify message from server. +**$charset** UTF-8 Character set (``utf-8``, ``iso-8859-1``, etc.). +**$validate** true ``true``/``false`` Whether to validate the email address. +**$priority** 3 1, 2, 3, 4, 5 Email Priority. ``1`` = highest. ``5`` = lowest. ``3`` = normal. +**$CRLF** \\r\\n ``\r\n``, ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). +**$newline** \\r\\n ``\r\n``, ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). +**$BCCBatchMode** false ``true``/``false`` Enable BCC Batch Mode. +**$BCCBatchSize** 200 Number of emails in each BCC batch. +**$DSN** false ``true``/``false`` Enable notify message from server. =================== =================== ============================ ======================================================================= Overriding Word Wrapping @@ -173,9 +177,9 @@ Class Reference .. php:method:: setFrom($from[, $name = ''[, $returnPath = null]]) - :param string $from: "From" e-mail address + :param string $from: "From" email address :param string $name: "From" display name - :param string $returnPath: Optional email address to redirect undelivered e-mail to + :param string $returnPath: Optional email address to redirect undelivered email to :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email @@ -192,8 +196,8 @@ Class Reference .. php:method:: setReplyTo($replyto[, $name = '']) - :param string $replyto: E-mail address for replies - :param string $name: Display name for the reply-to e-mail address + :param string $replyto: Email address for replies + :param string $name: Display name for the reply-to email address :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email @@ -204,12 +208,12 @@ Class Reference .. php:method:: setTo($to) - :param mixed $to: Comma-delimited string or an array of e-mail addresses + :param mixed $to: Comma separated string or an array of email addresses :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email - Sets the email address(s) of the recipient(s). Can be a single e-mail, - a comma-delimited list or an array: + Sets the email address(es) of the recipient(s). Can be a single email, + a comma separated list or an array: .. literalinclude:: email/006.php @@ -219,22 +223,22 @@ Class Reference .. php:method:: setCC($cc) - :param mixed $cc: Comma-delimited string or an array of e-mail addresses + :param mixed $cc: Comma separated string or an array of email addresses :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email - Sets the CC email address(s). Just like the "to", can be a single e-mail, - a comma-delimited list or an array. + Sets the CC email address(es). Just like the "to", can be a single email, + a comma separated list or an array. .. php:method:: setBCC($bcc[, $limit = '']) - :param mixed $bcc: Comma-delimited string or an array of e-mail addresses - :param int $limit: Maximum number of e-mails to send per batch + :param mixed $bcc: Comma separated string or an array of email addresses + :param int $limit: Maximum number of emails to send per batch :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email - Sets the BCC email address(s). Just like the ``setTo()`` method, can be a single - e-mail, a comma-delimited list or an array. + Sets the BCC email address(es). Just like the ``setTo()`` method, can be a single + email, a comma separated list or an array. If ``$limit`` is set, "batch mode" will be enabled, which will send the emails to batches, with each batch not exceeding the specified @@ -242,7 +246,7 @@ Class Reference .. php:method:: setSubject($subject) - :param string $subject: E-mail subject line + :param string $subject: Email subject line :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email @@ -252,21 +256,21 @@ Class Reference .. php:method:: setMessage($body) - :param string $body: E-mail message body + :param string $body: Email message body :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email - Sets the e-mail message body: + Sets the email message body: .. literalinclude:: email/010.php .. php:method:: setAltMessage($str) - :param string $str: Alternative e-mail message body + :param string $str: Alternative email message body :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email - Sets the alternative e-mail message body: + Sets the alternative email message body: .. literalinclude:: email/011.php @@ -284,7 +288,7 @@ Class Reference :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email - Appends additional headers to the e-mail: + Appends additional headers to the email: .. literalinclude:: email/012.php @@ -311,7 +315,7 @@ Class Reference :returns: true on success, false on failure :rtype: bool - The e-mail sending method. Returns boolean true or false based on + The email sending method. Returns boolean true or false based on success or failure, enabling it to be used conditionally: .. literalinclude:: email/015.php @@ -334,7 +338,7 @@ Class Reference :param string $disposition: 'disposition' of the attachment. Most email clients make their own decision regardless of the MIME specification used here. https://www.iana.org/assignments/cont-disp/cont-disp.xhtml - :param string $newname: Custom file name to use in the e-mail + :param string $newname: Custom file name to use in the email :param string $mime: MIME type to use (useful for buffered data) :returns: CodeIgniter\\Email\\Email instance (method chaining) :rtype: CodeIgniter\\Email\\Email @@ -375,7 +379,7 @@ Class Reference .. literalinclude:: email/022.php - .. note:: Content-ID for each e-mail must be re-created for it to be unique. + .. note:: Content-ID for each email must be re-created for it to be unique. .. php:method:: printDebugger($include = ['headers', 'subject', 'body']) From 611e701f7eb21a275c108694fba9b341862044c3 Mon Sep 17 00:00:00 2001 From: obozdag Date: Mon, 10 Jun 2024 11:57:43 +0200 Subject: [PATCH 02/83] docs: Remove recipients from preferences list in libraries/email.rst Remove recipients from preferences list in libraries/email.rst --- user_guide_src/source/libraries/email.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 4bcf84c4aec9..f71ff693d87f 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -115,8 +115,6 @@ Preference Default Value Options Description =================== =================== ============================ ======================================================================= **$fromEmail** The email address to be set in the "from" header. **$fromName** The name to be set in the "from" header. -**$recipients** The email addresses of the recipients, as a comma separated string or - an array **$userAgent** CodeIgniter The "user agent". **$protocol** mail ``mail``, ``sendmail``, The mail sending protocol. or ``smtp`` From 2ce73cd5cf76df5d435e3e8d9b25967e45e3459d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 11:34:36 +0900 Subject: [PATCH 03/83] docs: add changelog and upgrade for v4.5.4 --- user_guide_src/source/changelogs/index.rst | 1 + user_guide_src/source/changelogs/v4.5.4.rst | 35 ++++++++++++ .../source/installation/upgrade_454.rst | 55 +++++++++++++++++++ .../source/installation/upgrading.rst | 1 + 4 files changed, 92 insertions(+) create mode 100644 user_guide_src/source/changelogs/v4.5.4.rst create mode 100644 user_guide_src/source/installation/upgrade_454.rst diff --git a/user_guide_src/source/changelogs/index.rst b/user_guide_src/source/changelogs/index.rst index d97ccaa0b0ac..3dc5cb698f75 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.5.4 v4.5.3 v4.5.2 v4.5.1 diff --git a/user_guide_src/source/changelogs/v4.5.4.rst b/user_guide_src/source/changelogs/v4.5.4.rst new file mode 100644 index 000000000000..bf737a99a335 --- /dev/null +++ b/user_guide_src/source/changelogs/v4.5.4.rst @@ -0,0 +1,35 @@ +############# +Version 4.5.4 +############# + +Release Date: Unreleased + +**4.5.4 release of CodeIgniter4** + +.. contents:: + :local: + :depth: 3 + +******** +BREAKING +******** + +*************** +Message Changes +*************** + +******* +Changes +******* + +************ +Deprecations +************ + +********** +Bugs Fixed +********** + +See the repo's +`CHANGELOG.md `_ +for a complete list of bugs fixed. diff --git a/user_guide_src/source/installation/upgrade_454.rst b/user_guide_src/source/installation/upgrade_454.rst new file mode 100644 index 000000000000..393324c3b40c --- /dev/null +++ b/user_guide_src/source/installation/upgrade_454.rst @@ -0,0 +1,55 @@ +############################# +Upgrading from 4.5.3 to 4.5.4 +############################# + +Please refer to the upgrade instructions corresponding to your installation method. + +- :ref:`Composer Installation App Starter Upgrading ` +- :ref:`Composer Installation Adding CodeIgniter4 to an Existing Project Upgrading ` +- :ref:`Manual Installation Upgrading ` + +.. contents:: + :local: + :depth: 2 + +********************** +Mandatory File Changes +********************** + +**************** +Breaking Changes +**************** + +********************* +Breaking Enhancements +********************* + +************* +Project Files +************* + +Some 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. + +.. note:: There are some third-party CodeIgniter modules available to assist + with merging changes to the project space: + `Explore on Packagist `_. + +Content Changes +=============== + +The following files received significant changes (including deprecations or visual adjustments) +and it is recommended that you merge the updated versions with your application: + +Config +------ + +- @TODO + +All Changes +=========== + +This is a list of all files in the **project space** that received changes; +many will be simple comments or formatting that have no effect on the runtime: + +- @TODO diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index 2615c49fe10a..0daa9309cddc 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -16,6 +16,7 @@ See also :doc:`./backward_compatibility_notes`. backward_compatibility_notes + upgrade_454 upgrade_453 upgrade_452 upgrade_451 From bbfb37c40ef5c5ccc6a310bd68a7402f43809796 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 11:37:35 +0900 Subject: [PATCH 04/83] docs: change version notation --- admin/RELEASE.md | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/admin/RELEASE.md b/admin/RELEASE.md index 8c5f463355fb..4f199a821177 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -6,16 +6,22 @@ > > -MGatner, kenjis -## Merge `develop` branch into next minor version branch `4.x` +## Notation + +- `4.x.x`: The new release version. (e.g., `4.5.3`) +- `4.y`: The next minor version. (e.g., `4.6`) +- `4.z`: The next next minor version. (e.g., `4.7`) + +## Merge `develop` branch into next minor version branch `4.y` Before starting release process, if there are commits in `develop` branch that -are not merged into `4.x` branch, merge them. This is because if conflicts occur, +are not merged into `4.y` branch, merge them. This is because if conflicts occur, merging will take time. ```console git fetch upstream -git switch 4.x -git merge upstream/4.x +git switch 4.y +git merge upstream/4.y git merge upstream/develop git push upstream HEAD ``` @@ -24,11 +30,10 @@ git push upstream HEAD If you release a new minor version. -* [ ] Create PR to merge `4.x` into `develop` and merge it +* [ ] Create PR to merge `4.y` into `develop` and merge it * [ ] Rename the current minor version (e.g., `4.5`) in Setting > Branches > "Branch protection rules" to the next minor version. E.g. `4.5` → `4.6` -* [ ] Delete the merged `4.x` branch (This closes all PRs to the branch) -* Do the regular release process. Go to the next "Changelog" section +* [ ] Delete the merged `4.y` branch (This closes all PRs to the branch) ## Changelog @@ -90,8 +95,8 @@ Work off direct clones of the repos so the release branches persist for a time. * [ ] Replace **CHANGELOG.md** with the new version generated above * [ ] Update **user_guide_src/source/changelogs/v4.x.x.rst** * Remove the section titles that have no items -* [ ] Update **user_guide_src/source/installation/upgrade_{ver}.rst** - * [ ] fill in the "All Changes" section, and add it to **upgrading.rst** +* [ ] Update **user_guide_src/source/installation/upgrade_4xx.rst** + * [ ] fill in the "All Changes" section, and add it to **upgrade_4xx.rst** * git diff --name-status origin/master -- . ':!system' ':!tests' ':!user_guide_src' * Note: `tests/` is not used for distribution repos. See `admin/starter/tests/` * [ ] Remove the section titles that have no items @@ -137,7 +142,7 @@ Work off direct clones of the repos so the release branches persist for a time. ## New Contributors * - **Full Changelog**: https://github.com/codeigniter4/CodeIgniter4/compare/v4.x.x...v4.x.x + **Full Changelog**: https://github.com/codeigniter4/CodeIgniter4/compare/v4.x.w...v4.x.x ``` Click the "Generate release notes" button, and get the "New Contributors". * [ ] Watch for the "Deploy Distributable Repos" action to make sure **framework**, @@ -164,19 +169,19 @@ Work off direct clones of the repos so the release branches persist for a time. git merge origin/master git push origin HEAD ``` -* [ ] Update the next minor version branch `4.x`: +* [ ] Update the next minor version branch `4.y`: ```console git fetch origin - git checkout 4.x - git merge origin/4.x + git checkout 4.y + git merge origin/4.y git merge origin/develop git push origin HEAD ``` -* [ ] [Minor version only] Create the new next minor version branch `4.x`: +* [ ] [Minor version only] Create the new next minor version branch `4.z`: ```console git fetch origin git switch develop - git switch -c 4.x + git switch -c 4.z git push origin HEAD ``` * [ ] Request CVEs and Publish any Security Advisories that were resolved from private forks From 23d09bd57d58c0e6fc7c24da0d75ed7561c5ebab Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 13:33:49 +0900 Subject: [PATCH 05/83] chore: add missing / at the end It seems better to put / at the end of directories. See https://getcomposer.org/doc/04-schema.md#psr-4 --- admin/starter/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/starter/composer.json b/admin/starter/composer.json index b84684d82a4f..38a51e29fb64 100644 --- a/admin/starter/composer.json +++ b/admin/starter/composer.json @@ -21,7 +21,7 @@ "autoload": { "psr-4": { "App\\": "app/", - "Config\\": "app/Config" + "Config\\": "app/Config/" }, "exclude-from-classmap": [ "**/Database/Migrations/**" From d171ac348fc905d5553406b7a8a8e44961ac022c Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 13:38:16 +0900 Subject: [PATCH 06/83] docs: add note to upgrade_420.rst --- user_guide_src/source/installation/upgrade_420.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/installation/upgrade_420.rst b/user_guide_src/source/installation/upgrade_420.rst index 03aebabb015c..d86800f58dbc 100644 --- a/user_guide_src/source/installation/upgrade_420.rst +++ b/user_guide_src/source/installation/upgrade_420.rst @@ -43,6 +43,8 @@ The constants ``EVENT_PRIORITY_LOW``, ``EVENT_PRIORITY_NORMAL`` and ``EVENT_PRIO composer.json ============= +.. note:: This procedure is not required in v4.5.0 or later. + If you use Composer, when you installed CodeIgniter v4.1.9 or before, and if there are ``App\\`` and ``Config\\`` namespaces in your ``/composer.json``'s ``autoload.psr-4`` like the following, you need to remove these lines, and run ``composer dump-autoload``. From a69c876fceb5260394ebe6dad1efbd9156322c8c Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 14:23:23 +0900 Subject: [PATCH 07/83] docs: update outdated description for HTTP method names --- user_guide_src/source/incoming/filters.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 4425ce03d3bf..6d8204d948e9 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -186,15 +186,15 @@ $methods because :ref:`auto-routing-legacy` permits any HTTP method to access a controller. Accessing the controller with a method you don't expect could bypass the filter. -You can apply filters to all requests of a certain HTTP method, like POST, GET, PUT, etc. In this array, you would -specify the method name in **lowercase**. It's value would be an array of filters to run: +You can apply filters to all requests of a certain HTTP method, like ``POST``, ``GET``, ``PUT``, etc. +It's value would be an array of filters to run: .. literalinclude:: filters/008.php .. note:: Unlike the ``$globals`` or the ``$filters`` properties, these will only run as before filters. -In addition to the standard HTTP methods, this also supports one special case: ``cli``. The ``cli`` method would apply to +In addition to the standard HTTP methods, this also supports one special case: ``CLI``. The ``CLI`` method would apply to all requests that were run from the command line. $filters From 33dc973e43192634e9dc2017124768f089225a69 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 14:24:30 +0900 Subject: [PATCH 08/83] docs: add empty lines --- user_guide_src/source/incoming/filters.rst | 4 +++- user_guide_src/source/incoming/routing.rst | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 6d8204d948e9..3cbb4af9e993 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -106,7 +106,9 @@ filters to run: .. literalinclude:: filters/003.php -Aliases are mandatory and if you try to use a full class name later, the system will throw an error. Defining them +Aliases are mandatory and if you try to use a full class name later, the system will throw an error. + +Defining them in this way makes it simple to switch out the class used. Great for when you decided you need to change to a different authentication system since you only change the filter's class and you're done. diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 867983437acd..8c930a59f37e 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -388,6 +388,7 @@ Applying Filters ================ You can alter the behavior of specific routes by supplying filters to run before or after the controller. This is especially handy during authentication or api logging. + The value for the filter can be a string or an array of strings: * matching the aliases defined in **app/Config/Filters.php**. From 75a935033593640c20b6481fb5ca30b4a283507d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 14:25:08 +0900 Subject: [PATCH 09/83] docs: small improvements --- user_guide_src/source/incoming/filters.rst | 8 +++++--- user_guide_src/source/incoming/routing.rst | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 3cbb4af9e993..350f6e540f90 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -82,7 +82,7 @@ Configuring Filters There are two ways to configure filters when they get run. One is done in **app/Config/Filters.php**, the other is done in **app/Config/Routes.php**. -If you want to specify filter to a specific route, use **app/Config/Routes.php** +If you want to specify filters to defined routes, use **app/Config/Routes.php** and see :ref:`URI Routing `. .. Note:: The safest way to apply filters is to :ref:`disable auto-routing `, and :ref:`set filters to routes `. @@ -95,9 +95,11 @@ configure exactly when the filters run. .. Warning:: It is recommended that you should always add ``*`` at the end of a URI in the filter settings. Because a controller method might be accessible by different URLs than you think. - For example, when :ref:`auto-routing-legacy` is enabled, if you have ``Blog::index``, + For example, when :ref:`auto-routing-legacy` is enabled, if you have ``Blog::index()``, it can be accessible with ``blog``, ``blog/index``, and ``blog/index/1``, etc. +.. _filters-aliases: + $aliases -------- @@ -172,7 +174,7 @@ an array with the ``except`` key and a URI path (relative to BaseURL) to match a and the URI paths specified in the filter could be different. See :ref:`upgrade-447-filter-paths` for details. -Any place you can use a URI path (relative to BaseURL) in the filter settings, you can use a regular expression or, like in this example, use +Any place you can use a URI path (relative to BaseURL) in the filter settings, you can use a regular expression or, like in this example above, use an asterisk (``*``) for a wildcard that will match all characters after that. In this example, any URI path starting with ``api/`` would be exempted from CSRF protection, but the site's forms would all be protected. diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 8c930a59f37e..b822d4cce17e 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -394,7 +394,7 @@ The value for the filter can be a string or an array of strings: * matching the aliases defined in **app/Config/Filters.php**. * filter classnames -See :doc:`Controller Filters ` for more information on setting up filters. +See :ref:`Controller Filters ` for more information on defining aliases. .. Warning:: If you set filters to routes in **app/Config/Routes.php** (not in **app/Config/Filters.php**), it is recommended to disable Auto Routing (Legacy). @@ -406,7 +406,7 @@ See :doc:`Controller Filters ` for more information on setting up filte Alias Filter ------------ -You specify an alias defined in **app/Config/Filters.php** for the filter value: +You specify an alias :ref:`defined in app/Config/Filters.php ` for the filter value: .. literalinclude:: routing/034.php @@ -419,7 +419,7 @@ Classname Filter .. versionadded:: 4.1.5 -You specify a filter classname for the filter value: +You can specify a filter classname for the filter value: .. literalinclude:: routing/036.php @@ -436,7 +436,7 @@ Multiple Filters :ref:`Upgrading from 4.1.4 to 4.1.5 ` for the details. -You specify an array for the filter value: +You can specify an array for the filter value: .. literalinclude:: routing/037.php From 9a9a9a05bc3a79eb186be137dabd72501d3f01df Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 25 Jun 2024 14:30:35 +0900 Subject: [PATCH 10/83] docs: add note for HTTP method names lowercase --- user_guide_src/source/incoming/filters.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 350f6e540f90..737fd191392a 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -201,6 +201,8 @@ It's value would be an array of filters to run: In addition to the standard HTTP methods, this also supports one special case: ``CLI``. The ``CLI`` method would apply to all requests that were run from the command line. +.. note:: Prior to v4.5.0, due to a bug, you needed to specify the HTTP method names in **lowercase**. + $filters -------- From 2d5d8a577cd71e7f47f8d10b569b457b5143ad9d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 26 Jun 2024 00:36:20 +0700 Subject: [PATCH 11/83] chore: update to new RectorConfig::configure() syntax for config --- rector.php | 128 ++++++++++++++++++++++++----------------------------- 1 file changed, 59 insertions(+), 69 deletions(-) diff --git a/rector.php b/rector.php index 1a12e38f3223..d43741a39712 100644 --- a/rector.php +++ b/rector.php @@ -53,8 +53,6 @@ use Rector\PHPUnit\CodeQuality\Rector\Class_\YieldDataProviderRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector; -use Rector\Set\ValueObject\LevelSetList; -use Rector\Set\ValueObject\SetList; use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; use Rector\Strict\Rector\If_\BooleanInIfConditionRuleFixerRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; @@ -64,38 +62,34 @@ use Utils\Rector\RemoveErrorSuppressInTryCatchStmtsRector; use Utils\Rector\UnderscoreToCamelCaseVariableNameRector; -return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([ - SetList::DEAD_CODE, - LevelSetList::UP_TO_PHP_81, +return RectorConfig::configure() + ->withPhpSets(php81: true) + ->withPreparedSets(deadCode: true) + ->withSets([ PHPUnitSetList::PHPUNIT_CODE_QUALITY, PHPUnitSetList::PHPUNIT_100, - ]); - - $rectorConfig->parallel(120, 8, 10); - - // Github action cache - $rectorConfig->cacheClass(FileCacheStorage::class); - if (is_dir('/tmp')) { - $rectorConfig->cacheDirectory('/tmp/rector'); - } - + ]) + ->withParallel(120, 8, 10) + ->withCache( + // Github action cache or local + is_dir('/tmp') ? '/tmp/rector' : sys_get_temp_dir() . '/rector', + FileCacheStorage::class + ) // paths to refactor; solid alternative to CLI arguments - $rectorConfig->paths([__DIR__ . '/app', __DIR__ . '/system', __DIR__ . '/tests', __DIR__ . '/utils']); - + ->withPaths( + [__DIR__ . '/app', __DIR__ . '/system', __DIR__ . '/tests', __DIR__ . '/utils'] + ) // do you need to include constants, class aliases or custom autoloader? files listed will be executed - $rectorConfig->bootstrapFiles([ + ->withBootstrapFiles([ __DIR__ . '/system/Test/bootstrap.php', - ]); - - $rectorConfig->phpstanConfigs([ + ]) + ->withPHPStanConfigs([ __DIR__ . '/phpstan.neon.dist', __DIR__ . '/vendor/codeigniter/phpstan-codeigniter/extension.neon', __DIR__ . '/vendor/phpstan/phpstan-strict-rules/rules.neon', - ]); - + ]) // is there a file you need to skip? - $rectorConfig->skip([ + ->withSkip([ __DIR__ . '/system/Debug/Toolbar/Views/toolbar.tpl.php', __DIR__ . '/system/ThirdParty', __DIR__ . '/tests/system/Config/fixtures', @@ -187,48 +181,44 @@ AnnotationWithValueToAttributeRector::class, AnnotationToAttributeRector::class, CoversAnnotationWithValueToAttributeRector::class, - ]); - + ]) // auto import fully qualified class names - $rectorConfig->importNames(); - $rectorConfig->removeUnusedImports(); - - $rectorConfig->rule(DeclareStrictTypesRector::class); - $rectorConfig->rule(UnderscoreToCamelCaseVariableNameRector::class); - $rectorConfig->rule(SimplifyUselessVariableRector::class); - $rectorConfig->rule(RemoveAlwaysElseRector::class); - $rectorConfig->rule(PassStrictParameterToFunctionParameterRector::class); - $rectorConfig->rule(CountArrayToEmptyArrayComparisonRector::class); - $rectorConfig->rule(ChangeNestedForeachIfsToEarlyContinueRector::class); - $rectorConfig->rule(ChangeIfElseValueAssignToEarlyReturnRector::class); - $rectorConfig->rule(SimplifyStrposLowerRector::class); - $rectorConfig->rule(CombineIfRector::class); - $rectorConfig->rule(SimplifyIfReturnBoolRector::class); - $rectorConfig->rule(InlineIfToExplicitIfRector::class); - $rectorConfig->rule(PreparedValueToEarlyReturnRector::class); - $rectorConfig->rule(ShortenElseIfRector::class); - $rectorConfig->rule(SimplifyIfElseToTernaryRector::class); - $rectorConfig->rule(UnusedForeachValueToArrayKeysRector::class); - $rectorConfig->rule(ChangeArrayPushToArrayAssignRector::class); - $rectorConfig->rule(UnnecessaryTernaryExpressionRector::class); - $rectorConfig->rule(RemoveErrorSuppressInTryCatchStmtsRector::class); - $rectorConfig->rule(FuncGetArgsToVariadicParamRector::class); - $rectorConfig->rule(MakeInheritedMethodVisibilitySameAsParentRector::class); - $rectorConfig->rule(SimplifyEmptyArrayCheckRector::class); - $rectorConfig->rule(SimplifyEmptyCheckOnEmptyArrayRector::class); - $rectorConfig->rule(TernaryEmptyArrayArrayDimFetchToCoalesceRector::class); - $rectorConfig->rule(EmptyOnNullableObjectToInstanceOfRector::class); - $rectorConfig->rule(DisallowedEmptyRuleFixerRector::class); - $rectorConfig->rule(PrivatizeFinalClassPropertyRector::class); - $rectorConfig->rule(CompleteDynamicPropertiesRector::class); - $rectorConfig->rule(BooleanInIfConditionRuleFixerRector::class); - $rectorConfig->rule(SingleInArrayToCompareRector::class); - $rectorConfig->rule(VersionCompareFuncCallToConstantRector::class); - $rectorConfig->rule(ExplicitBoolCompareRector::class); - - $rectorConfig - ->ruleWithConfiguration(StringClassNameToClassConstantRector::class, [ - // keep '\\' prefix string on string '\Foo\Bar' - StringClassNameToClassConstantRector::SHOULD_KEEP_PRE_SLASH => true, - ]); -}; + ->withImportNames(removeUnusedImports: true) + ->withRules([ + DeclareStrictTypesRector::class, + UnderscoreToCamelCaseVariableNameRector::class, + SimplifyUselessVariableRector::class, + RemoveAlwaysElseRector::class, + PassStrictParameterToFunctionParameterRector::class, + CountArrayToEmptyArrayComparisonRector::class, + ChangeNestedForeachIfsToEarlyContinueRector::class, + ChangeIfElseValueAssignToEarlyReturnRector::class, + SimplifyStrposLowerRector::class, + CombineIfRector::class, + SimplifyIfReturnBoolRector::class, + InlineIfToExplicitIfRector::class, + PreparedValueToEarlyReturnRector::class, + ShortenElseIfRector::class, + SimplifyIfElseToTernaryRector::class, + UnusedForeachValueToArrayKeysRector::class, + ChangeArrayPushToArrayAssignRector::class, + UnnecessaryTernaryExpressionRector::class, + RemoveErrorSuppressInTryCatchStmtsRector::class, + FuncGetArgsToVariadicParamRector::class, + MakeInheritedMethodVisibilitySameAsParentRector::class, + SimplifyEmptyArrayCheckRector::class, + SimplifyEmptyCheckOnEmptyArrayRector::class, + TernaryEmptyArrayArrayDimFetchToCoalesceRector::class, + EmptyOnNullableObjectToInstanceOfRector::class, + DisallowedEmptyRuleFixerRector::class, + PrivatizeFinalClassPropertyRector::class, + CompleteDynamicPropertiesRector::class, + BooleanInIfConditionRuleFixerRector::class, + SingleInArrayToCompareRector::class, + VersionCompareFuncCallToConstantRector::class, + ExplicitBoolCompareRector::class, + ]) + ->withConfiguredRule(StringClassNameToClassConstantRector::class, [ + // keep '\\' prefix string on string '\Foo\Bar' + StringClassNameToClassConstantRector::SHOULD_KEEP_PRE_SLASH => true, + ]); From 86480f498af77afff0482194f5f9207ceb2685ee Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 26 Jun 2024 07:36:11 +0700 Subject: [PATCH 12/83] chore: fallback null on cache directory to use default rector cache directory --- rector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rector.php b/rector.php index d43741a39712..6eeabe396a04 100644 --- a/rector.php +++ b/rector.php @@ -72,7 +72,7 @@ ->withParallel(120, 8, 10) ->withCache( // Github action cache or local - is_dir('/tmp') ? '/tmp/rector' : sys_get_temp_dir() . '/rector', + is_dir('/tmp') ? '/tmp/rector' : null, FileCacheStorage::class ) // paths to refactor; solid alternative to CLI arguments From 073306c0dc9ddd2c1340878bf284659f41975bb4 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 26 Jun 2024 11:59:01 +0700 Subject: [PATCH 13/83] refactor: use first class callable on function call --- system/CLI/BaseCommand.php | 4 ++-- system/CLI/CLI.php | 2 +- system/CLI/GeneratorTrait.php | 2 +- system/Commands/ListCommands.php | 2 +- system/Commands/Utilities/Routes.php | 8 ++++---- .../Routes/AutoRouterImproved/AutoRouteCollector.php | 4 ++-- system/Cookie/Cookie.php | 2 +- system/DataCaster/DataCaster.php | 2 +- system/Database/BaseConnection.php | 2 +- system/Database/Forge.php | 6 +++--- system/Database/MigrationRunner.php | 2 +- system/Database/OCI8/Forge.php | 2 +- system/Database/SQLite3/Forge.php | 2 +- system/Images/Handlers/GDHandler.php | 2 +- system/Router/RouteCollection.php | 4 ++-- system/Validation/Rules.php | 2 +- 16 files changed, 24 insertions(+), 24 deletions(-) diff --git a/system/CLI/BaseCommand.php b/system/CLI/BaseCommand.php index 86ba504feaa6..afeb80eb5267 100644 --- a/system/CLI/BaseCommand.php +++ b/system/CLI/BaseCommand.php @@ -163,7 +163,7 @@ public function showHelp() if ($this->arguments !== []) { CLI::newLine(); CLI::write(lang('CLI.helpArguments'), 'yellow'); - $length = max(array_map('strlen', array_keys($this->arguments))); + $length = max(array_map(strlen(...), array_keys($this->arguments))); foreach ($this->arguments as $argument => $description) { CLI::write(CLI::color($this->setPad($argument, $length, 2, 2), 'green') . $description); @@ -173,7 +173,7 @@ public function showHelp() if ($this->options !== []) { CLI::newLine(); CLI::write(lang('CLI.helpOptions'), 'yellow'); - $length = max(array_map('strlen', array_keys($this->options))); + $length = max(array_map(strlen(...), array_keys($this->options))); foreach ($this->options as $option => $description) { CLI::write(CLI::color($this->setPad($option, $length, 2, 2), 'green') . $description); diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index 7badf1807dcd..6adc9f839367 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -393,7 +393,7 @@ private static function isZeroOptions(array $options): void private static function printKeysAndValues(array $options): void { // +2 for the square brackets around the key - $keyMaxLength = max(array_map('mb_strwidth', array_keys($options))) + 2; + $keyMaxLength = max(array_map(mb_strwidth(...), array_keys($options))) + 2; foreach ($options as $key => $description) { $name = str_pad(' [' . $key . '] ', $keyMaxLength + 4, ' '); diff --git a/system/CLI/GeneratorTrait.php b/system/CLI/GeneratorTrait.php index 065197be5090..6a061a36b8b3 100644 --- a/system/CLI/GeneratorTrait.php +++ b/system/CLI/GeneratorTrait.php @@ -325,7 +325,7 @@ private function normalizeInputClassName(): string implode( '\\', array_map( - 'pascalize', + pascalize(...), explode('\\', str_replace('/', '\\', trim($class))) ) ), diff --git a/system/Commands/ListCommands.php b/system/Commands/ListCommands.php index 87c3e96b824a..3411b103430d 100644 --- a/system/Commands/ListCommands.php +++ b/system/Commands/ListCommands.php @@ -101,7 +101,7 @@ protected function listFull(array $commands) $groups[$command['group']][$title] = $command; } - $length = max(array_map('strlen', array_keys($commands))); + $length = max(array_map(strlen(...), array_keys($commands))); ksort($groups); diff --git a/system/Commands/Utilities/Routes.php b/system/Commands/Utilities/Routes.php index f9575c063973..9adcc1bc39e7 100644 --- a/system/Commands/Utilities/Routes.php +++ b/system/Commands/Utilities/Routes.php @@ -119,8 +119,8 @@ public function run(array $params) $route['route'], $routeName, $route['handler'], - implode(' ', array_map('class_basename', $filters['before'])), - implode(' ', array_map('class_basename', $filters['after'])), + implode(' ', array_map(class_basename(...), $filters['before'])), + implode(' ', array_map(class_basename(...), $filters['after'])), ]; } @@ -166,8 +166,8 @@ public function run(array $params) // There is no `AUTO` method, but it is intentional not to get route filters. $filters = $filterCollector->get('AUTO', $uriGenerator->get($routes[1])); - $routes[] = implode(' ', array_map('class_basename', $filters['before'])); - $routes[] = implode(' ', array_map('class_basename', $filters['after'])); + $routes[] = implode(' ', array_map(class_basename(...), $filters['before'])); + $routes[] = implode(' ', array_map(class_basename(...), $filters['after'])); } } diff --git a/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php b/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php index 0d426a3b1716..579969346637 100644 --- a/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php +++ b/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php @@ -125,8 +125,8 @@ private function addFilters($routes) $filters['before'] = array_intersect($filtersLongest['before'], $filtersShortest['before']); $filters['after'] = array_intersect($filtersLongest['after'], $filtersShortest['after']); - $route['before'] = implode(' ', array_map('class_basename', $filters['before'])); - $route['after'] = implode(' ', array_map('class_basename', $filters['after'])); + $route['before'] = implode(' ', array_map(class_basename(...), $filters['before'])); + $route['after'] = implode(' ', array_map(class_basename(...), $filters['after'])); } return $routes; diff --git a/system/Cookie/Cookie.php b/system/Cookie/Cookie.php index 78dc44258eb9..01b10db19b65 100644 --- a/system/Cookie/Cookie.php +++ b/system/Cookie/Cookie.php @@ -283,7 +283,7 @@ public function getPrefixedName(): string $name .= $this->getName(); } else { $search = str_split(self::$reservedCharsList); - $replace = array_map('rawurlencode', $search); + $replace = array_map(rawurlencode(...), $search); $name .= str_replace($search, $replace, $this->getName()); } diff --git a/system/DataCaster/DataCaster.php b/system/DataCaster/DataCaster.php index 29de3987faa9..5a6786a03331 100644 --- a/system/DataCaster/DataCaster.php +++ b/system/DataCaster/DataCaster.php @@ -156,7 +156,7 @@ public function castAs(mixed $value, string $field, string $method = 'get'): mix // type[param, param2,param3] if (preg_match('/\A(.+)\[(.+)\]\z/', $type, $matches)) { $type = $matches[1]; - $params = array_map('trim', explode(',', $matches[2])); + $params = array_map(trim(...), explode(',', $matches[2])); } if ($isNullable && ! $this->strict) { diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 6581dc7c5ac0..dce399bdefb5 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1519,7 +1519,7 @@ public function tableExists(string $tableName, bool $cached = true): bool if (! empty($this->dataCache['table_names'])) { $key = array_search( strtolower($tableName), - array_map('strtolower', $this->dataCache['table_names']), + array_map(strtolower(...), $this->dataCache['table_names']), true ); diff --git a/system/Database/Forge.php b/system/Database/Forge.php index 797b685e861c..595cd6156b5f 100644 --- a/system/Database/Forge.php +++ b/system/Database/Forge.php @@ -306,7 +306,7 @@ public function dropDatabase(string $dbName): bool if (! empty($this->db->dataCache['db_names'])) { $key = array_search( strtolower($dbName), - array_map('strtolower', $this->db->dataCache['db_names']), + array_map(strtolower(...), $this->db->dataCache['db_names']), true ); if ($key !== false) { @@ -667,7 +667,7 @@ public function dropTable(string $tableName, bool $ifExists = false, bool $casca if ($query && ! empty($this->db->dataCache['table_names'])) { $key = array_search( strtolower($this->db->DBPrefix . $tableName), - array_map('strtolower', $this->db->dataCache['table_names']), + array_map(strtolower(...), $this->db->dataCache['table_names']), true ); @@ -729,7 +729,7 @@ public function renameTable(string $tableName, string $newTableName) if ($result && ! empty($this->db->dataCache['table_names'])) { $key = array_search( strtolower($this->db->DBPrefix . $tableName), - array_map('strtolower', $this->db->dataCache['table_names']), + array_map(strtolower(...), $this->db->dataCache['table_names']), true ); diff --git a/system/Database/MigrationRunner.php b/system/Database/MigrationRunner.php index 719d45c15592..055b8ba6eaf3 100644 --- a/system/Database/MigrationRunner.php +++ b/system/Database/MigrationRunner.php @@ -686,7 +686,7 @@ public function getBatches(): array ->get() ->getResultArray(); - return array_map('intval', array_column($batches, 'batch')); + return array_map(intval(...), array_column($batches, 'batch')); } /** diff --git a/system/Database/OCI8/Forge.php b/system/Database/OCI8/Forge.php index 69a42ed1dbeb..5a10363be769 100644 --- a/system/Database/OCI8/Forge.php +++ b/system/Database/OCI8/Forge.php @@ -202,7 +202,7 @@ protected function _processColumn(array $processedField): string $constraint = ' CHECK(' . $this->db->escapeIdentifiers($processedField['name']) . ' IN ' . $processedField['length'] . ')'; - $processedField['length'] = '(' . max(array_map('mb_strlen', explode("','", mb_substr($processedField['length'], 2, -2)))) . ')' . $constraint; + $processedField['length'] = '(' . max(array_map(mb_strlen(...), explode("','", mb_substr($processedField['length'], 2, -2)))) . ')' . $constraint; } elseif (isset($this->primaryKeys['fields']) && count($this->primaryKeys['fields']) === 1 && $processedField['name'] === $this->primaryKeys['fields'][0]) { $processedField['unique'] = ''; } diff --git a/system/Database/SQLite3/Forge.php b/system/Database/SQLite3/Forge.php index 32e447829c29..48e9abcc425c 100644 --- a/system/Database/SQLite3/Forge.php +++ b/system/Database/SQLite3/Forge.php @@ -101,7 +101,7 @@ public function dropDatabase(string $dbName): bool } if (! empty($this->db->dataCache['db_names'])) { - $key = array_search(strtolower($dbName), array_map('strtolower', $this->db->dataCache['db_names']), true); + $key = array_search(strtolower($dbName), array_map(strtolower(...), $this->db->dataCache['db_names']), true); if ($key !== false) { unset($this->db->dataCache['db_names'][$key]); } diff --git a/system/Images/Handlers/GDHandler.php b/system/Images/Handlers/GDHandler.php index 350dbc2306a8..062a69d89212 100644 --- a/system/Images/Handlers/GDHandler.php +++ b/system/Images/Handlers/GDHandler.php @@ -471,7 +471,7 @@ protected function textOverlay(string $text, array $options = [], bool $isShadow // shorthand hex, #f00 if (strlen($color) === 3) { - $color = implode('', array_map('str_repeat', str_split($color), [2, 2, 2])); + $color = implode('', array_map(str_repeat(...), str_split($color), [2, 2, 2])); } $color = str_split(substr($color, 0, 6), 2); diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 3198d342aa9d..322987dc791b 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -853,7 +853,7 @@ public function resource(string $name, ?array $options = null): RouteCollectionI // In order to allow customization of the route the // resources are sent to, we need to have a new name // to store the values in. - $newName = implode('\\', array_map('ucfirst', explode('/', $name))); + $newName = implode('\\', array_map(ucfirst(...), explode('/', $name))); // If a new controller is specified, then we replace the // $name value with the name of the new controller. @@ -947,7 +947,7 @@ public function presenter(string $name, ?array $options = null): RouteCollection // In order to allow customization of the route the // resources are sent to, we need to have a new name // to store the values in. - $newName = implode('\\', array_map('ucfirst', explode('/', $name))); + $newName = implode('\\', array_map(ucfirst(...), explode('/', $name))); // If a new controller is specified, then we replace the // $name value with the name of the new controller. diff --git a/system/Validation/Rules.php b/system/Validation/Rules.php index 272b2dcf61fe..04e8a0546e77 100644 --- a/system/Validation/Rules.php +++ b/system/Validation/Rules.php @@ -159,7 +159,7 @@ public function in_list($value, string $list): bool $value = (string) $value; } - $list = array_map('trim', explode(',', $list)); + $list = array_map(trim(...), explode(',', $list)); return in_array($value, $list, true); } From 8c603af8a1fcbdb5543ea12f7f2921d2c24a1512 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 27 Jun 2024 09:41:21 +0900 Subject: [PATCH 14/83] test: add tests for isValidDSN() --- .../Database/Live/OCI8/ConnectionTest.php | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/system/Database/Live/OCI8/ConnectionTest.php diff --git a/tests/system/Database/Live/OCI8/ConnectionTest.php b/tests/system/Database/Live/OCI8/ConnectionTest.php new file mode 100644 index 000000000000..caf97ed632fd --- /dev/null +++ b/tests/system/Database/Live/OCI8/ConnectionTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Database\Live\OCI8; + +use CodeIgniter\Database\OCI8\Connection; +use CodeIgniter\Test\CIUnitTestCase; +use Config\Database as DbConfig; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; + +/** + * @internal + */ +#[Group('DatabaseLive')] +final class ConnectionTest extends CIUnitTestCase +{ + /** + * @var array Database connection settings + */ + private array $settings = []; + + protected function setUp(): void + { + $dbConfig = config(DbConfig::class); + $this->settings = $dbConfig->{$this->DBGroup}; + + if ($this->settings['DBDriver'] !== 'OCI8') { + $this->markTestSkipped('This test is only for OCI8.'); + } + } + + #[DataProvider('provideIsValidDSN')] + public function testIsValidDSN(string $dsn): void + { + $this->settings['DSN'] = $dsn; + + $db = new Connection($this->settings); + + $isValidDSN = $this->getPrivateMethodInvoker($db, 'isValidDSN'); + + $this->assertTrue($isValidDSN()); + } + + /** + * @return array> + */ + public static function provideIsValidDSN(): iterable + { + yield from [ + // Easy Connect string + // See https://docs.oracle.com/en/database/oracle/oracle-database/23/netag/configuring-naming-methods.html#GUID-36F3A17D-843C-490A-8A23-FB0FE005F8E8 + 'HostOnly' => ['sales-server'], + 'Host:Port' => ['sales-server:3456'], + 'Host/ServiceName' => ['sales-server/sales'], + 'IPv6Address:Port/ServiceName' => ['[2001:0db8:0:0::200C:417A]:80/sales'], + 'Host:Port/ServiceName' => ['sales-server:80/sales'], + 'Host/ServiceName:ServerType/InstanceName' => ['sales-server/sales:dedicated/inst1'], + 'Host:InstanceName' => ['sales-server//inst1'], + 'Host/ServiceNameWithDots' => ['myhost/my.service.name'], + 'Host:Port/ServiceNameWithDots' => ['myhost:1521/my.service.name'], + ]; + } +} From 6c61938fc57786e664068b5303de24ac04a82eba Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 27 Jun 2024 09:43:21 +0900 Subject: [PATCH 15/83] fix: regex pattern for Easy Connect string --- system/Database/OCI8/Connection.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/system/Database/OCI8/Connection.php b/system/Database/OCI8/Connection.php index f7983a695c0c..2b870b755b44 100644 --- a/system/Database/OCI8/Connection.php +++ b/system/Database/OCI8/Connection.php @@ -53,10 +53,24 @@ class Connection extends BaseConnection ]; protected $validDSNs = [ - 'tns' => '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', // TNS - // Easy Connect string (Oracle 10g+) - 'ec' => '/^(\/\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\/[a-z0-9$_]+)?(:[^\/])?(\/[a-z0-9$_]+)?$/i', - 'in' => '/^[a-z0-9$_]+$/i', // Instance name (defined in tnsnames.ora) + // TNS + 'tns' => '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', + // Easy Connect string (Oracle 10g+). + // https://docs.oracle.com/en/database/oracle/oracle-database/23/netag/configuring-naming-methods.html#GUID-36F3A17D-843C-490A-8A23-FB0FE005F8E8 + // [//]host[:port][/[service_name][:server_type][/instance_name]] + 'ec' => '/^ + (\/\/)? + (\[)?[a-z0-9.:_-]+(\])? # Host or IP address + (:[1-9][0-9]{0,4})? # Port + ( + (\/) + ([a-z0-9.$_]+)? # Service name + (:[a-z]+)? # Server type + (\/[a-z0-9$_]+)? # Instance name + )? + $/ix', + // Instance name (defined in tnsnames.ora) + 'in' => '/^[a-z0-9$_]+$/i', ]; /** From 9e4777a0c83e56cf5e1d9e0de6cc352742a44f3c Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 27 Jun 2024 22:19:28 +0700 Subject: [PATCH 16/83] refactor: enable AddClosureVoidReturnTypeWhereNoReturnRector to add void return on closure --- app/Config/Events.php | 4 ++-- rector.php | 2 ++ system/Autoloader/Autoloader.php | 2 +- system/CLI/CLI.php | 2 +- system/CodeIgniter.php | 2 +- system/DataConverter/DataConverter.php | 2 +- system/Database/Postgre/Builder.php | 2 +- system/Database/Query.php | 4 ++-- system/Database/SQLSRV/Builder.php | 2 +- system/Database/SQLite3/Result.php | 2 +- system/Debug/Toolbar.php | 2 +- system/Filters/Filters.php | 2 +- system/HTTP/IncomingRequest.php | 4 ++-- system/HTTP/RequestTrait.php | 2 +- 14 files changed, 18 insertions(+), 16 deletions(-) diff --git a/app/Config/Events.php b/app/Config/Events.php index 993abd24ebc7..62a7b86d46c8 100644 --- a/app/Config/Events.php +++ b/app/Config/Events.php @@ -23,7 +23,7 @@ * Events::on('create', [$myInstance, 'myMethod']); */ -Events::on('pre_system', static function () { +Events::on('pre_system', static function (): void { if (ENVIRONMENT !== 'testing') { if (ini_get('zlib.output_compression')) { throw FrameworkException::forEnabledZlibOutputCompression(); @@ -47,7 +47,7 @@ Services::toolbar()->respond(); // Hot Reload route - for framework use on the hot reloader. if (ENVIRONMENT === 'development') { - Services::routes()->get('__hot-reload', static function () { + Services::routes()->get('__hot-reload', static function (): void { (new HotReloader())->run(); }); } diff --git a/rector.php b/rector.php index 6eeabe396a04..c3c43879019d 100644 --- a/rector.php +++ b/rector.php @@ -56,6 +56,7 @@ use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; use Rector\Strict\Rector\If_\BooleanInIfConditionRuleFixerRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; +use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector; use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector; use Utils\Rector\PassStrictParameterToFunctionParameterRector; @@ -217,6 +218,7 @@ SingleInArrayToCompareRector::class, VersionCompareFuncCallToConstantRector::class, ExplicitBoolCompareRector::class, + AddClosureVoidReturnTypeWhereNoReturnRector::class, ]) ->withConfiguredRule(StringClassNameToClassConstantRector::class, [ // keep '\\' prefix string on string '\Foo\Bar' diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 78d31eae0d7f..28c183f12552 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -507,7 +507,7 @@ private function autoloadKint(): void { // If we have KINT_DIR it means it's already loaded via composer if (! defined('KINT_DIR')) { - spl_autoload_register(function ($class) { + spl_autoload_register(function ($class): void { $class = explode('\\', $class); if (array_shift($class) !== 'Kint') { diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index 6adc9f839367..bfe1511eed02 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -857,7 +857,7 @@ public static function wrap(?string $string = null, int $max = 0, int $padLeft = $first = true; - array_walk($lines, static function (&$line) use ($padLeft, &$first) { + array_walk($lines, static function (&$line) use ($padLeft, &$first): void { if (! $first) { $line = str_repeat(' ', $padLeft) . $line; } else { diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 95feae8160a1..0bb101cc7990 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -253,7 +253,7 @@ private function autoloadKint(): void { // If we have KINT_DIR it means it's already loaded via composer if (! defined('KINT_DIR')) { - spl_autoload_register(function ($class) { + spl_autoload_register(function ($class): void { $class = explode('\\', $class); if (array_shift($class) !== 'Kint') { diff --git a/system/DataConverter/DataConverter.php b/system/DataConverter/DataConverter.php index b79ede5b08ff..43b42a08bbdf 100644 --- a/system/DataConverter/DataConverter.php +++ b/system/DataConverter/DataConverter.php @@ -140,7 +140,7 @@ public function reconstruct(string $classname, array $row): object return $classObj; } - $classSet = Closure::bind(function ($key, $value) { + $classSet = Closure::bind(function ($key, $value): void { $this->{$key} = $value; }, $classObj, $classname); diff --git a/system/Database/Postgre/Builder.php b/system/Database/Postgre/Builder.php index 857760930275..1071dfedf06b 100644 --- a/system/Database/Postgre/Builder.php +++ b/system/Database/Postgre/Builder.php @@ -159,7 +159,7 @@ public function replace(?array $set = null) $table = $this->QBFrom[0]; $set = $this->binds; - array_walk($set, static function (array &$item) { + array_walk($set, static function (array &$item): void { $item = $item[0]; }); diff --git a/system/Database/Query.php b/system/Database/Query.php index 11085a91f6a0..ba8e9066063f 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -118,7 +118,7 @@ public function setQuery(string $sql, $binds = null, bool $setEscape = true) } if ($setEscape) { - array_walk($binds, static function (&$item) { + array_walk($binds, static function (&$item): void { $item = [ $item, true, @@ -141,7 +141,7 @@ public function setQuery(string $sql, $binds = null, bool $setEscape = true) public function setBinds(array $binds, bool $setEscape = true) { if ($setEscape) { - array_walk($binds, static function (&$item) { + array_walk($binds, static function (&$item): void { $item = [$item, true]; }); } diff --git a/system/Database/SQLSRV/Builder.php b/system/Database/SQLSRV/Builder.php index e2301f7ee2ab..a6d0b8e85ccd 100644 --- a/system/Database/SQLSRV/Builder.php +++ b/system/Database/SQLSRV/Builder.php @@ -420,7 +420,7 @@ protected function _replace(string $table, array $keys, array $values): string // Get the binds $binds = $this->binds; - array_walk($binds, static function (&$item) { + array_walk($binds, static function (&$item): void { $item = $item[0]; }); diff --git a/system/Database/SQLite3/Result.php b/system/Database/SQLite3/Result.php index 70d8dc47d2b6..aa5abf28682a 100644 --- a/system/Database/SQLite3/Result.php +++ b/system/Database/SQLite3/Result.php @@ -147,7 +147,7 @@ protected function fetchObject(string $className = 'stdClass') return $classObj->injectRawData($row); } - $classSet = Closure::bind(function ($key, $value) { + $classSet = Closure::bind(function ($key, $value): void { $this->{$key} = $value; }, $classObj, $className); diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index 115016225062..9f20f987f59c 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -294,7 +294,7 @@ protected function collectTimelineData($collectors): array array_multisort(...$sortArray); // Add end time to each element - array_walk($data, static function (&$row) { + array_walk($data, static function (&$row): void { $row['end'] = $row['start'] + $row['duration']; }); diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index d8e22835e2ed..1255e0c4055d 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -522,7 +522,7 @@ private function getCleanName(string $name): array [$name, $arguments] = explode(':', $name); $arguments = explode(',', $arguments); - array_walk($arguments, static function (&$item) { + array_walk($arguments, static function (&$item): void { $item = trim($item); }); } diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index ec13e40f6ff5..c905de0a3ae3 100644 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -586,7 +586,7 @@ public function getJsonVar($index = null, bool $assoc = false, ?int $filter = nu ) { if (is_array($data)) { // Iterate over array and append filter and flags - array_walk_recursive($data, static function (&$val) use ($filter, $flags) { + array_walk_recursive($data, static function (&$val) use ($filter, $flags): void { $valType = gettype($val); $val = filter_var($val, $filter, $flags); @@ -672,7 +672,7 @@ public function getRawInputVar($index = null, ?int $filter = null, $flags = null ) ) { // Iterate over array and append filter and flags - array_walk_recursive($output, static function (&$val) use ($filter, $flags) { + array_walk_recursive($output, static function (&$val) use ($filter, $flags): void { $val = filter_var($val, $filter, $flags); }); diff --git a/system/HTTP/RequestTrait.php b/system/HTTP/RequestTrait.php index cfdc52b55f69..43a4f23a0e87 100644 --- a/system/HTTP/RequestTrait.php +++ b/system/HTTP/RequestTrait.php @@ -322,7 +322,7 @@ public function fetchGlobal(string $name, $index = null, ?int $filter = null, $f ) ) { // Iterate over array and append filter and flags - array_walk_recursive($value, static function (&$val) use ($filter, $flags) { + array_walk_recursive($value, static function (&$val) use ($filter, $flags): void { $val = filter_var($val, $filter, $flags); }); From 43ce1350f64b48c8de7cffab5d7cadc49fa51443 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 08:55:41 +0900 Subject: [PATCH 17/83] test: add test for select() with RawSql --- tests/system/Database/Builder/SelectTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/system/Database/Builder/SelectTest.php b/tests/system/Database/Builder/SelectTest.php index cd3f39029f6b..569d78803aee 100644 --- a/tests/system/Database/Builder/SelectTest.php +++ b/tests/system/Database/Builder/SelectTest.php @@ -67,6 +67,21 @@ public function testSelectAcceptsArray(): void $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); } + public function testSelectAcceptsArrayWithRawSql(): void + { + $builder = new BaseBuilder('employees', $this->db); + + $builder->select([ + 'employee_id', + new RawSql("IF(salary > 5000, 'High', 'Low') AS salary_level"), + ]); + + $expected = <<<'SQL' + SELECT "employee_id", IF(salary > 5000, 'High', 'Low') AS salary_level FROM "employees" + SQL; + $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); + } + public function testSelectAcceptsMultipleColumns(): void { $builder = new BaseBuilder('users', $this->db); From 1962e8c82c46b5c4d4ea3c0235cbae590efe59a6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 08:56:39 +0900 Subject: [PATCH 18/83] fix: select() may cause TypeError TypeError: trim(): Argument #1 ($string) must be of type string, CodeIgniter\Database\RawSql given --- system/Database/BaseBuilder.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 4e6e422b2a6f..00d75b0b7873 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -390,7 +390,7 @@ public function ignore(bool $ignore = true) /** * Generates the SELECT portion of the query * - * @param array|RawSql|string $select + * @param list|RawSql|string $select * * @return $this */ @@ -402,16 +402,21 @@ public function select($select = '*', ?bool $escape = null) } if ($select instanceof RawSql) { - $this->QBSelect[] = $select; - - return $this; + $select = [$select]; } if (is_string($select)) { - $select = $escape === false ? [$select] : explode(',', $select); + $select = ($escape === false) ? [$select] : explode(',', $select); } foreach ($select as $val) { + if ($val instanceof RawSql) { + $this->QBSelect[] = $val; + $this->QBNoEscape[] = false; + + continue; + } + $val = trim($val); if ($val !== '') { From 73d67fb659b54b25d5d0ab51b919daebb678f9a7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 09:17:18 +0900 Subject: [PATCH 19/83] refactor: rename variable name --- system/Database/BaseBuilder.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 00d75b0b7873..c892033fd9ae 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -124,9 +124,9 @@ class BaseBuilder protected array $QBUnion = []; /** - * QB NO ESCAPE data + * Whether to protect identifiers in SELECT * - * @var array + * @var list true=protect, false=not protect */ public $QBNoEscape = []; @@ -391,6 +391,7 @@ public function ignore(bool $ignore = true) * Generates the SELECT portion of the query * * @param list|RawSql|string $select + * @param bool|null $escape Whether to protect identifiers * * @return $this */ @@ -3066,8 +3067,8 @@ protected function compileSelect($selectOverride = false): string // The reason we protect identifiers here rather than in the select() function // is because until the user calls the from() function we don't know if there are aliases foreach ($this->QBSelect as $key => $val) { - $noEscape = $this->QBNoEscape[$key] ?? null; - $this->QBSelect[$key] = $this->db->protectIdentifiers($val, false, $noEscape); + $protect = $this->QBNoEscape[$key] ?? null; + $this->QBSelect[$key] = $this->db->protectIdentifiers($val, false, $protect); } $sql .= implode(', ', $this->QBSelect); From 3f24caff8f0695c6a5ac185f046e67682d2648b1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 09:33:32 +0900 Subject: [PATCH 20/83] test: add tests for `SELECT NULL as` --- tests/system/Database/Builder/SelectTest.php | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/system/Database/Builder/SelectTest.php b/tests/system/Database/Builder/SelectTest.php index cd3f39029f6b..a761706dd3df 100644 --- a/tests/system/Database/Builder/SelectTest.php +++ b/tests/system/Database/Builder/SelectTest.php @@ -100,6 +100,28 @@ public function testSelectWorksWithComplexSelects(): void $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); } + public function testSelectNullAsInString(): void + { + $builder = new BaseBuilder('users', $this->db); + + $builder->select('NULL as field_alias, name'); + + $expected = 'SELECT NULL as field_alias, "name" FROM "users"'; + + $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); + } + + public function testSelectNullAsInArray(): void + { + $builder = new BaseBuilder('users', $this->db); + + $builder->select(['NULL as field_alias', 'name']); + + $expected = 'SELECT NULL as field_alias, "name" FROM "users"'; + + $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); + } + /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/4355 */ From 6ba48cf061e28321986b0cc389e0bab41380082d Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 09:34:14 +0900 Subject: [PATCH 21/83] fix: select() does not escape after `NULL as` --- system/Database/BaseBuilder.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 4e6e422b2a6f..fab19b60dab8 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -425,7 +425,9 @@ public function select($select = '*', ?bool $escape = null) * @see https://github.com/codeigniter4/CodeIgniter4/issues/1169 */ if (mb_stripos(trim($val), 'NULL') === 0) { - $escape = false; + $this->QBNoEscape[] = false; + + continue; } $this->QBNoEscape[] = $escape; From 227f53a6cdaf1f1a7156c0e588e70625214ce920 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 09:39:06 +0900 Subject: [PATCH 22/83] refactor: remove duplicated `trim()` It is already trimmed in Line 415. --- system/Database/BaseBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index fab19b60dab8..acfaa9e9183c 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -424,7 +424,7 @@ public function select($select = '*', ?bool $escape = null) * This prevents NULL being escaped * @see https://github.com/codeigniter4/CodeIgniter4/issues/1169 */ - if (mb_stripos(trim($val), 'NULL') === 0) { + if (mb_stripos($val, 'NULL') === 0) { $this->QBNoEscape[] = false; continue; From 51f94576e618cc881230bfd49b4a6ed107290d7b Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 09:45:42 +0900 Subject: [PATCH 23/83] chore: update phpstan-baseline.php --- phpstan-baseline.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 5a39d840a54d..bd665e22f5f7 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -1819,12 +1819,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Database/BaseBuilder.php', ]; -$ignoreErrors[] = [ - // identifier: missingType.iterableValue - 'message' => '#^Method CodeIgniter\\\\Database\\\\BaseBuilder\\:\\:select\\(\\) has parameter \\$select with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Database/BaseBuilder.php', -]; $ignoreErrors[] = [ // identifier: missingType.iterableValue 'message' => '#^Method CodeIgniter\\\\Database\\\\BaseBuilder\\:\\:set\\(\\) has parameter \\$key with no value type specified in iterable type array\\.$#', @@ -1993,12 +1987,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Database/BaseBuilder.php', ]; -$ignoreErrors[] = [ - // identifier: missingType.iterableValue - 'message' => '#^Property CodeIgniter\\\\Database\\\\BaseBuilder\\:\\:\\$QBNoEscape type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Database/BaseBuilder.php', -]; $ignoreErrors[] = [ // identifier: missingType.iterableValue 'message' => '#^Property CodeIgniter\\\\Database\\\\BaseBuilder\\:\\:\\$QBOptions type has no value type specified in iterable type array\\.$#', From fd5bf15ca5039174a3efd48535c552bc07d37ab6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 19:20:15 +0900 Subject: [PATCH 24/83] fix: select() with first param as RawSql --- system/Database/BaseBuilder.php | 10 ++++++---- tests/system/Database/Builder/SelectTest.php | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index c892033fd9ae..02f288bd2fdf 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -3060,15 +3060,17 @@ protected function compileSelect($selectOverride = false): string if (empty($this->QBSelect)) { $sql .= '*'; - } elseif ($this->QBSelect[0] instanceof RawSql) { - $sql .= (string) $this->QBSelect[0]; } else { // Cycle through the "select" portion of the query and prep each column name. // The reason we protect identifiers here rather than in the select() function // is because until the user calls the from() function we don't know if there are aliases foreach ($this->QBSelect as $key => $val) { - $protect = $this->QBNoEscape[$key] ?? null; - $this->QBSelect[$key] = $this->db->protectIdentifiers($val, false, $protect); + if ($val instanceof RawSql) { + $this->QBSelect[$key] = (string) $this->QBSelect[0]; + } else { + $protect = $this->QBNoEscape[$key] ?? null; + $this->QBSelect[$key] = $this->db->protectIdentifiers($val, false, $protect); + } } $sql .= implode(', ', $this->QBSelect); diff --git a/tests/system/Database/Builder/SelectTest.php b/tests/system/Database/Builder/SelectTest.php index 569d78803aee..34cade794df8 100644 --- a/tests/system/Database/Builder/SelectTest.php +++ b/tests/system/Database/Builder/SelectTest.php @@ -72,12 +72,12 @@ public function testSelectAcceptsArrayWithRawSql(): void $builder = new BaseBuilder('employees', $this->db); $builder->select([ - 'employee_id', new RawSql("IF(salary > 5000, 'High', 'Low') AS salary_level"), + 'employee_id', ]); $expected = <<<'SQL' - SELECT "employee_id", IF(salary > 5000, 'High', 'Low') AS salary_level FROM "employees" + SELECT IF(salary > 5000, 'High', 'Low') AS salary_level, "employee_id" FROM "employees" SQL; $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); } From 8534e8fcb4bf7809d6f7377e7276454ad4524c3c Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 20:20:20 +0900 Subject: [PATCH 25/83] fix: wrong variable and add tests --- system/Database/BaseBuilder.php | 2 +- tests/system/Database/Builder/SelectTest.php | 58 +++++++++++++++++--- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 02f288bd2fdf..4d153fca1dc1 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -3066,7 +3066,7 @@ protected function compileSelect($selectOverride = false): string // is because until the user calls the from() function we don't know if there are aliases foreach ($this->QBSelect as $key => $val) { if ($val instanceof RawSql) { - $this->QBSelect[$key] = (string) $this->QBSelect[0]; + $this->QBSelect[$key] = (string) $val; } else { $protect = $this->QBNoEscape[$key] ?? null; $this->QBSelect[$key] = $this->db->protectIdentifiers($val, false, $protect); diff --git a/tests/system/Database/Builder/SelectTest.php b/tests/system/Database/Builder/SelectTest.php index 34cade794df8..5f1fe5fdc8da 100644 --- a/tests/system/Database/Builder/SelectTest.php +++ b/tests/system/Database/Builder/SelectTest.php @@ -19,6 +19,7 @@ use CodeIgniter\Database\SQLSRV\Builder as SQLSRVBuilder; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\Mock\MockConnection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; /** @@ -67,21 +68,62 @@ public function testSelectAcceptsArray(): void $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); } - public function testSelectAcceptsArrayWithRawSql(): void + #[DataProvider('provideSelectAcceptsArrayWithRawSql')] + public function testSelectAcceptsArrayWithRawSql(array $select, string $expected): void { $builder = new BaseBuilder('employees', $this->db); - $builder->select([ - new RawSql("IF(salary > 5000, 'High', 'Low') AS salary_level"), - 'employee_id', - ]); + $builder->select($select); - $expected = <<<'SQL' - SELECT IF(salary > 5000, 'High', 'Low') AS salary_level, "employee_id" FROM "employees" - SQL; $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); } + /** + * @return list|string> + */ + public static function provideSelectAcceptsArrayWithRawSql(): iterable + { + yield from [ + [ + [ + new RawSql("IF(salary > 5000, 'High', 'Low') AS salary_level"), + 'employee_id', + ], + <<<'SQL' + SELECT IF(salary > 5000, 'High', 'Low') AS salary_level, "employee_id" FROM "employees" + SQL, + ], + [ + [ + 'employee_id', + new RawSql("IF(salary > 5000, 'High', 'Low') AS salary_level"), + ], + <<<'SQL' + SELECT "employee_id", IF(salary > 5000, 'High', 'Low') AS salary_level FROM "employees" + SQL, + ], + [ + [ + new RawSql("CONCAT(first_name, ' ', last_name) AS full_name"), + new RawSql("IF(salary > 5000, 'High', 'Low') AS salary_level"), + ], + <<<'SQL' + SELECT CONCAT(first_name, ' ', last_name) AS full_name, IF(salary > 5000, 'High', 'Low') AS salary_level FROM "employees" + SQL, + ], + [ + [ + new RawSql("CONCAT(first_name, ' ', last_name) AS full_name"), + 'employee_id', + new RawSql("IF(salary > 5000, 'High', 'Low') AS salary_level"), + ], + <<<'SQL' + SELECT CONCAT(first_name, ' ', last_name) AS full_name, "employee_id", IF(salary > 5000, 'High', 'Low') AS salary_level FROM "employees" + SQL, + ], + ]; + } + public function testSelectAcceptsMultipleColumns(): void { $builder = new BaseBuilder('users', $this->db); From c022dd32e55e3f8fc0655296fa1fca638dcf40d3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 28 Jun 2024 20:23:43 +0900 Subject: [PATCH 26/83] test: add @param --- tests/system/Database/Builder/SelectTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/system/Database/Builder/SelectTest.php b/tests/system/Database/Builder/SelectTest.php index 5f1fe5fdc8da..fe4ad5b80178 100644 --- a/tests/system/Database/Builder/SelectTest.php +++ b/tests/system/Database/Builder/SelectTest.php @@ -68,6 +68,9 @@ public function testSelectAcceptsArray(): void $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); } + /** + * @param list $select + */ #[DataProvider('provideSelectAcceptsArrayWithRawSql')] public function testSelectAcceptsArrayWithRawSql(array $select, string $expected): void { From 9d83fd7b62b0f3e4ff8415cfd57c909bab7b2e15 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 30 Jun 2024 10:06:55 +0900 Subject: [PATCH 27/83] docs: change rule order Alphabetical order. --- .../source/libraries/validation.rst | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index 899389d2d004..88db25b81db8 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -897,15 +897,11 @@ Rule Parameter Description ======================= ========== ============================================= =================================================== alpha No Fails if field has anything other than alphabetic characters in ASCII. -alpha_space No Fails if field contains anything other than - alphabetic characters or spaces in ASCII. alpha_dash No Fails if field contains anything other than alphanumeric characters, underscores or dashes in ASCII. alpha_numeric No Fails if field contains anything other than alphanumeric characters in ASCII. -alpha_numeric_space No Fails if field contains anything other than - alphanumeric or space characters in ASCII. alpha_numeric_punct No Fails if field contains anything other than alphanumeric, space, or this limited set of punctuation characters: ``~`` (tilde), @@ -916,6 +912,10 @@ alpha_numeric_punct No Fails if field contains anything other than ``_`` (underscore), ``+`` (plus), ``=`` (equals), ``|`` (vertical bar), ``:`` (colon), ``.`` (period). +alpha_numeric_space No Fails if field contains anything other than + alphanumeric or space characters in ASCII. +alpha_space No Fails if field contains anything other than + alphabetic characters or spaces in ASCII. decimal No Fails if field contains anything other than a decimal number. Also accepts a ``+`` or ``-`` sign for the number. @@ -964,10 +964,10 @@ not_in_list Yes Fails if field is within a predetermined list. numeric No Fails if field contains anything other than numeric characters. -regex_match Yes Fails if field does not match the regular ``regex_match[/regex/]`` - expression. permit_empty No Allows the field to receive an empty array, empty string, null or false. +regex_match Yes Fails if field does not match the regular ``regex_match[/regex/]`` + expression. required No Fails if the field is an empty array, empty string, null or false. required_with Yes The field is required when any of the other ``required_with[field1,field2]`` @@ -980,31 +980,6 @@ timezone No Fails if field does not match a timezone per `timezone_identifiers_list()`_ valid_base64 No Fails if field contains anything other than valid Base64 characters. -valid_json No Fails if field does not contain a valid JSON - string. -valid_email No Fails if field does not contain a valid - email address. -valid_emails No Fails if any value provided in a comma - separated list is not a valid email. -valid_ip Yes Fails if the supplied IP is not valid. ``valid_ip[ipv6]`` - Accepts an optional parameter of ``ipv4`` or - ``ipv6`` to specify an IP format. -valid_url No Fails if field does not contain (loosely) a - URL. Includes simple strings that could be - hostnames, like "codeigniter". - **Normally,** ``valid_url_strict`` **should - be used.** -valid_url_strict Yes Fails if field does not contain a valid URL. ``valid_url_strict[https]`` - You can optionally specify a list of valid - schemas. If not specified, ``http,https`` - are valid. This rule uses PHP's - ``FILTER_VALIDATE_URL``. -valid_date Yes Fails if field does not contain a valid date. ``valid_date[d/m/Y]`` - Any string that `strtotime()`_ accepts is - valid if you don't specify an optional - parameter that matches a date format. - **So it is usually necessary to specify - the parameter.** valid_cc_number Yes Verifies that the credit card number matches ``valid_cc_number[amex]`` the format used by the specified provider. Current supported providers are: @@ -1025,6 +1000,31 @@ valid_cc_number Yes Verifies that the credit card number matches Scotiabank Scotia Card (``scotia``), BMO ABM Card (``bmoabm``), HSBC Canada Card (``hsbc``) +valid_date Yes Fails if field does not contain a valid date. ``valid_date[d/m/Y]`` + Any string that `strtotime()`_ accepts is + valid if you don't specify an optional + parameter that matches a date format. + **So it is usually necessary to specify + the parameter.** +valid_email No Fails if field does not contain a valid + email address. +valid_emails No Fails if any value provided in a comma + separated list is not a valid email. +valid_ip Yes Fails if the supplied IP is not valid. ``valid_ip[ipv6]`` + Accepts an optional parameter of ``ipv4`` or + ``ipv6`` to specify an IP format. +valid_json No Fails if field does not contain a valid JSON + string. +valid_url No Fails if field does not contain (loosely) a + URL. Includes simple strings that could be + hostnames, like "codeigniter". + **Normally,** ``valid_url_strict`` **should + be used.** +valid_url_strict Yes Fails if field does not contain a valid URL. ``valid_url_strict[https]`` + You can optionally specify a list of valid + schemas. If not specified, ``http,https`` + are valid. This rule uses PHP's + ``FILTER_VALIDATE_URL``. ======================= ========== ============================================= =================================================== .. note:: You can also use any native PHP functions that return boolean and From 0e56433deb12ee9e36361a4a7182c10b17377239 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 30 Jun 2024 10:13:45 +0900 Subject: [PATCH 28/83] docs: decorate words --- user_guide_src/source/libraries/validation.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index 88db25b81db8..7a6035734c1f 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -940,9 +940,11 @@ in_list Yes Fails if field is not within a predetermined integer No Fails if field contains anything other than an integer. is_natural No Fails if field contains anything other than - a natural number: 0, 1, 2, 3, etc. + a natural number: ``0``, ``1``, ``2``, ``3`` + , etc. is_natural_no_zero No Fails if field contains anything other than - a natural number, except zero: 1, 2, 3, etc. + a natural number, except zero: ``1``, ``2``, + ``3``, etc. is_not_unique Yes Checks the database to see if the given value ``is_not_unique[table.field,where_field,where_value]`` exists. Can ignore records by field/value to filter (currently accept only one filter). @@ -974,7 +976,7 @@ required_with Yes The field is required when any of the other fields is not `empty()`_ in the data. required_without Yes The field is required when any of the other ``required_without[field1,field2]`` fields is `empty()`_ in the data. -string No A generic alternative to the alpha* rules +string No A generic alternative to the **alpha*** rules that confirms the element is a string timezone No Fails if field does not match a timezone per `timezone_identifiers_list()`_ From 6938f4a74838a0555ed447978a082025fc8ff7d7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 30 Jun 2024 10:18:05 +0900 Subject: [PATCH 29/83] docs: add important note --- user_guide_src/source/libraries/validation.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index 7a6035734c1f..7b87954653e1 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -1031,7 +1031,8 @@ valid_url_strict Yes Fails if field does not contain a valid URL. .. note:: You can also use any native PHP functions that return boolean and permit at least one parameter, the field data to validate. - The Validation library **never alters the data** to validate. + +.. important:: The Validation library **never alters the data** to validate. .. _timezone_identifiers_list(): https://www.php.net/manual/en/function.timezone-identifiers-list.php .. _strtotime(): https://www.php.net/manual/en/function.strtotime.php From e792d438cf6d5490905ed0c0b26ab316dc5541f2 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 30 Jun 2024 14:39:29 +0700 Subject: [PATCH 30/83] refactor: enable AddFunctionVoidReturnTypeWhereNoReturnRector to add void to functions --- rector.php | 2 ++ system/Common.php | 4 +--- system/Helpers/cookie_helper.php | 6 ++---- system/Helpers/kint_helper.php | 6 ++---- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/rector.php b/rector.php index c3c43879019d..df89a98bf808 100644 --- a/rector.php +++ b/rector.php @@ -58,6 +58,7 @@ use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector; +use Rector\TypeDeclaration\Rector\Function_\AddFunctionVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector; use Utils\Rector\PassStrictParameterToFunctionParameterRector; use Utils\Rector\RemoveErrorSuppressInTryCatchStmtsRector; @@ -219,6 +220,7 @@ VersionCompareFuncCallToConstantRector::class, ExplicitBoolCompareRector::class, AddClosureVoidReturnTypeWhereNoReturnRector::class, + AddFunctionVoidReturnTypeWhereNoReturnRector::class, ]) ->withConfiguredRule(StringClassNameToClassConstantRector::class, [ // keep '\\' prefix string on string '\Foo\Bar' diff --git a/system/Common.php b/system/Common.php index f96e9f100f00..49b3d2896753 100644 --- a/system/Common.php +++ b/system/Common.php @@ -766,10 +766,8 @@ function lang(string $line, array $args = [], ?string $locale = null) * - notice * - info * - debug - * - * @return void */ - function log_message(string $level, string $message, array $context = []) + function log_message(string $level, string $message, array $context = []): void { // When running tests, we want to always ensure that the // TestLogger is running, which provides utilities for diff --git a/system/Helpers/cookie_helper.php b/system/Helpers/cookie_helper.php index 49e568346b68..f19ee0147eb4 100644 --- a/system/Helpers/cookie_helper.php +++ b/system/Helpers/cookie_helper.php @@ -35,7 +35,6 @@ * @param bool|null $httpOnly True makes the cookie accessible via http(s) only (no javascript) * @param string|null $sameSite The cookie SameSite value * - * @return void * * @see \CodeIgniter\HTTP\Response::setCookie() */ @@ -49,7 +48,7 @@ function set_cookie( ?bool $secure = null, ?bool $httpOnly = null, ?string $sameSite = null - ) { + ): void { $response = service('response'); $response->setCookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httpOnly, $sameSite); } @@ -92,11 +91,10 @@ function get_cookie($index, bool $xssClean = false, ?string $prefix = '') * @param string $path the cookie path * @param string $prefix the cookie prefix * - * @return void * * @see \CodeIgniter\HTTP\Response::deleteCookie() */ - function delete_cookie($name, string $domain = '', string $path = '/', string $prefix = '') + function delete_cookie($name, string $domain = '', string $path = '/', string $prefix = ''): void { service('response')->deleteCookie($name, $domain, $path, $prefix); } diff --git a/system/Helpers/kint_helper.php b/system/Helpers/kint_helper.php index 075c162315aa..1f89dc78c55b 100644 --- a/system/Helpers/kint_helper.php +++ b/system/Helpers/kint_helper.php @@ -24,7 +24,7 @@ * * @codeCoverageIgnore Can't be tested ... exits */ - function dd(...$vars) + function dd(...$vars): void { // @codeCoverageIgnoreStart Kint::$aliases[] = 'dd'; @@ -71,10 +71,8 @@ function d(...$vars) */ /** * trace function - * - * @return void */ - function trace() + function trace(): void { Kint::$aliases[] = 'trace'; Kint::trace(); From acefa3c2148226dc0e9cb9da7ef3d7ae4d35dae6 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 30 Jun 2024 14:41:31 +0700 Subject: [PATCH 31/83] cs fix --- system/Helpers/cookie_helper.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/Helpers/cookie_helper.php b/system/Helpers/cookie_helper.php index f19ee0147eb4..27007104e68e 100644 --- a/system/Helpers/cookie_helper.php +++ b/system/Helpers/cookie_helper.php @@ -35,7 +35,6 @@ * @param bool|null $httpOnly True makes the cookie accessible via http(s) only (no javascript) * @param string|null $sameSite The cookie SameSite value * - * * @see \CodeIgniter\HTTP\Response::setCookie() */ function set_cookie( @@ -91,7 +90,6 @@ function get_cookie($index, bool $xssClean = false, ?string $prefix = '') * @param string $path the cookie path * @param string $prefix the cookie prefix * - * * @see \CodeIgniter\HTTP\Response::deleteCookie() */ function delete_cookie($name, string $domain = '', string $path = '/', string $prefix = ''): void From fb7e4f1fedf745af1c086faec987c0734f68e24e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 30 Jun 2024 18:17:12 +0700 Subject: [PATCH 32/83] refactor: Enable phpunit 10 attribute Rector rules --- rector.php | 12 ------------ system/Test/DatabaseTestTrait.php | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/rector.php b/rector.php index df89a98bf808..f3f1f3f12bdc 100644 --- a/rector.php +++ b/rector.php @@ -42,14 +42,9 @@ use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\Php70\Rector\FuncCall\RandomFunctionRector; -use Rector\Php80\Rector\Class_\AnnotationToAttributeRector; use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector; use Rector\Php80\Rector\FunctionLike\MixedTypeRector; use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector; -use Rector\PHPUnit\AnnotationsToAttributes\Rector\Class_\AnnotationWithValueToAttributeRector; -use Rector\PHPUnit\AnnotationsToAttributes\Rector\Class_\CoversAnnotationWithValueToAttributeRector; -use Rector\PHPUnit\AnnotationsToAttributes\Rector\ClassMethod\DataProviderAnnotationToAttributeRector; -use Rector\PHPUnit\AnnotationsToAttributes\Rector\ClassMethod\DependsAnnotationWithValueToAttributeRector; use Rector\PHPUnit\CodeQuality\Rector\Class_\YieldDataProviderRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector; @@ -176,13 +171,6 @@ // Unnecessary (string) is inserted NullToStrictStringFuncCallArgRector::class, - - // PHPUnit 10 (requires PHP 8.1) features - DataProviderAnnotationToAttributeRector::class, - DependsAnnotationWithValueToAttributeRector::class, - AnnotationWithValueToAttributeRector::class, - AnnotationToAttributeRector::class, - CoversAnnotationWithValueToAttributeRector::class, ]) // auto import fully qualified class names ->withImportNames(removeUnusedImports: true) diff --git a/system/Test/DatabaseTestTrait.php b/system/Test/DatabaseTestTrait.php index 863ed542319d..27de14c39c60 100644 --- a/system/Test/DatabaseTestTrait.php +++ b/system/Test/DatabaseTestTrait.php @@ -13,6 +13,7 @@ namespace CodeIgniter\Test; +use PHPUnit\Framework\Attributes\AfterClass; use CodeIgniter\Database\BaseBuilder; use CodeIgniter\Database\Exceptions\DatabaseException; use CodeIgniter\Test\Constraints\SeeInDatabase; @@ -228,14 +229,13 @@ public function seed(string $name) // -------------------------------------------------------------------- // Utility // -------------------------------------------------------------------- - /** * Reset $doneMigration and $doneSeed * - * @afterClass * * @return void */ + #[AfterClass] public static function resetMigrationSeedCount() { self::$doneMigration = false; From 8ab9e40f04b35d64c697247e8a641f0d7252d019 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 30 Jun 2024 18:19:13 +0700 Subject: [PATCH 33/83] cs fix --- system/Test/DatabaseTestTrait.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system/Test/DatabaseTestTrait.php b/system/Test/DatabaseTestTrait.php index 27de14c39c60..c0d4473c7b9e 100644 --- a/system/Test/DatabaseTestTrait.php +++ b/system/Test/DatabaseTestTrait.php @@ -13,13 +13,13 @@ namespace CodeIgniter\Test; -use PHPUnit\Framework\Attributes\AfterClass; use CodeIgniter\Database\BaseBuilder; use CodeIgniter\Database\Exceptions\DatabaseException; use CodeIgniter\Test\Constraints\SeeInDatabase; use Config\Database; use Config\Migrations; use Config\Services; +use PHPUnit\Framework\Attributes\AfterClass; /** * DatabaseTestTrait @@ -232,7 +232,6 @@ public function seed(string $name) /** * Reset $doneMigration and $doneSeed * - * * @return void */ #[AfterClass] From 72ef4a627f15adab97ef9339c15b79b178f98288 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:17:27 +0000 Subject: [PATCH 34/83] chore(deps-dev): update rector/rector requirement from 1.1.1 to 1.2.0 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/1.1.1...1.2.0) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 76020a1f6ea5..ce3316112c49 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "phpunit/phpcov": "^9.0.2", "phpunit/phpunit": "^10.5.16", "predis/predis": "^1.1 || ^2.0", - "rector/rector": "1.1.1", + "rector/rector": "1.2.0", "vimeo/psalm": "^5.0" }, "replace": { From 1a180645de698a667c2b93dbe388200eba6b8490 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 2 Jul 2024 14:13:16 +0700 Subject: [PATCH 35/83] chore: skip tests View fixtures from rector --- rector.php | 1 + 1 file changed, 1 insertion(+) diff --git a/rector.php b/rector.php index f3f1f3f12bdc..7bb54aab325e 100644 --- a/rector.php +++ b/rector.php @@ -93,6 +93,7 @@ __DIR__ . '/tests/system/Filters/fixtures', __DIR__ . '/tests/_support/Commands/Foobar.php', __DIR__ . '/tests/_support/View', + __DIR__ . '/tests/system/View/Views', YieldDataProviderRector::class, From a9b42fedbec77770b135d363973c3dcf8b07f4b4 Mon Sep 17 00:00:00 2001 From: Mattias Sandstrom <1013635+tangix@users.noreply.github.com> Date: Thu, 4 Jul 2024 07:17:07 +0200 Subject: [PATCH 36/83] Allow string as parameter to version As indicated in the docs. --- system/HTTP/CURLRequest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 4b1c9c625399..2305c7f993ea 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -651,11 +651,11 @@ protected function setCURLOptions(array $curlOptions = [], array $config = []) // version if (! empty($config['version'])) { - if ($config['version'] === 1.0) { + if ($config['version'] === 1.0 || $config['version'] === "1.0") { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; - } elseif ($config['version'] === 1.1) { + } elseif ($config['version'] === 1.1 || $config['version'] === "1.1") { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; - } elseif ($config['version'] === 2.0) { + } elseif ($config['version'] === 2.0 || $config['version'] === "2.0") { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0; } } From 20c5c21142130d3e89b73d9d6d50c11ab210ca8a Mon Sep 17 00:00:00 2001 From: Mattias Sandstrom <1013635+tangix@users.noreply.github.com> Date: Thu, 4 Jul 2024 07:24:05 +0200 Subject: [PATCH 37/83] Ran CS fixer --- system/HTTP/CURLRequest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 2305c7f993ea..89adb498b003 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -651,11 +651,11 @@ protected function setCURLOptions(array $curlOptions = [], array $config = []) // version if (! empty($config['version'])) { - if ($config['version'] === 1.0 || $config['version'] === "1.0") { + if ($config['version'] === 1.0 || $config['version'] === '1.0') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; - } elseif ($config['version'] === 1.1 || $config['version'] === "1.1") { + } elseif ($config['version'] === 1.1 || $config['version'] === '1.1') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; - } elseif ($config['version'] === 2.0 || $config['version'] === "2.0") { + } elseif ($config['version'] === 2.0 || $config['version'] === '2.0') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0; } } From 409aa66f155999ff0699bf9b8db373e0f464e928 Mon Sep 17 00:00:00 2001 From: Mattias Sandstrom <1013635+tangix@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:00:17 +0200 Subject: [PATCH 38/83] Added tests for all versions --- tests/system/HTTP/CURLRequestTest.php | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index dc48eb621d80..bd05852a781f 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -1227,4 +1227,35 @@ public function testGetHeaderLineContentType(): void $this->assertSame('text/html; charset=UTF-8', $response->getHeaderLine('Content-Type')); } + + public function testHTTPversionAsString(): void + { + $this->request->request('POST', '/post', [ + 'version' => '1.0', + ]); + + $options = $this->request->curl_options; + + $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); + $this->assertSame(CURL_HTTP_VERSION_1_0, $options[CURLOPT_HTTP_VERSION]); + + $this->request->request('POST', '/post', [ + 'version' => '1.1', + ]); + + $options = $this->request->curl_options; + + $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); + $this->assertSame(CURL_HTTP_VERSION_1_1, $options[CURLOPT_HTTP_VERSION]); + + $this->request->request('POST', '/post', [ + 'version' => '2.0', + ]); + + $options = $this->request->curl_options; + + $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); + $this->assertSame(CURL_HTTP_VERSION_2_0, $options[CURLOPT_HTTP_VERSION]); + + } } From da57987f54543fa84ad2975ab8c1ed83110471e4 Mon Sep 17 00:00:00 2001 From: Mattias Sandstrom <1013635+tangix@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:03:30 +0200 Subject: [PATCH 39/83] Fixed code style --- tests/system/HTTP/CURLRequestTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index bd05852a781f..f14198be2264 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -1256,6 +1256,5 @@ public function testHTTPversionAsString(): void $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); $this->assertSame(CURL_HTTP_VERSION_2_0, $options[CURLOPT_HTTP_VERSION]); - } } From fd16faf1473fc538d1082909fb60541b42143efc Mon Sep 17 00:00:00 2001 From: Mattias Sandstrom <1013635+tangix@users.noreply.github.com> Date: Thu, 4 Jul 2024 18:07:03 +0200 Subject: [PATCH 40/83] Updated logic to convert to string for comparison --- system/HTTP/CURLRequest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 89adb498b003..9f405a7c1667 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -651,11 +651,12 @@ protected function setCURLOptions(array $curlOptions = [], array $config = []) // version if (! empty($config['version'])) { - if ($config['version'] === 1.0 || $config['version'] === '1.0') { + $version = sprintf('%.1f', $config['version']); + if ($version === '1.0') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; - } elseif ($config['version'] === 1.1 || $config['version'] === '1.1') { + } elseif ($version === '1.1') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; - } elseif ($config['version'] === 2.0 || $config['version'] === '2.0') { + } elseif ($version === '2.0') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0; } } From a6a50cc538744f32dfca5e59232093270a7c3713 Mon Sep 17 00:00:00 2001 From: Mattias Sandstrom <1013635+tangix@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:08:44 +0200 Subject: [PATCH 41/83] Added info to change-log --- user_guide_src/source/changelogs/v4.5.4.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/user_guide_src/source/changelogs/v4.5.4.rst b/user_guide_src/source/changelogs/v4.5.4.rst index bf737a99a335..51a9fd74f407 100644 --- a/user_guide_src/source/changelogs/v4.5.4.rst +++ b/user_guide_src/source/changelogs/v4.5.4.rst @@ -30,6 +30,9 @@ Deprecations Bugs Fixed ********** +- **CURLRequest:** Fixed a bug preventing the use of strings for ``version`` in the config array + when making requests. + See the repo's `CHANGELOG.md `_ for a complete list of bugs fixed. From c50ae9da47531f44703f52e5964440ed4e2529ec Mon Sep 17 00:00:00 2001 From: Mattias Sandstrom <1013635+tangix@users.noreply.github.com> Date: Fri, 5 Jul 2024 08:01:05 +0200 Subject: [PATCH 42/83] Fixing locale-aware issue --- system/HTTP/CURLRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 9f405a7c1667..9da231c17716 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -651,7 +651,7 @@ protected function setCURLOptions(array $curlOptions = [], array $config = []) // version if (! empty($config['version'])) { - $version = sprintf('%.1f', $config['version']); + $version = sprintf('%.1F', $config['version']); if ($version === '1.0') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; } elseif ($version === '1.1') { From 847ee236dc38982344ce68d149e48d676159651c Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 7 Jul 2024 11:47:10 +0900 Subject: [PATCH 43/83] fix: `spark phpini:check` may cause TypeError --- system/Security/CheckPhpIni.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system/Security/CheckPhpIni.php b/system/Security/CheckPhpIni.php index 4cef565ad7d6..1e92cdc403aa 100644 --- a/system/Security/CheckPhpIni.php +++ b/system/Security/CheckPhpIni.php @@ -50,17 +50,17 @@ public static function run(bool $isCli = true) private static function outputForCli(array $output, array $thead, array $tbody): void { foreach ($output as $directive => $values) { - $current = $values['current']; + $current = $values['current'] ?? ''; $notRecommended = false; if ($values['recommended'] !== '') { - if ($values['recommended'] !== $values['current']) { + if ($values['recommended'] !== $current) { $notRecommended = true; } $current = $notRecommended - ? CLI::color($values['current'] === '' ? 'n/a' : $values['current'], 'red') - : $values['current']; + ? CLI::color($current === '' ? 'n/a' : $current, 'red') + : $current; } $directive = $notRecommended ? CLI::color($directive, 'red') : $directive; From e9f3369151903404fbee2722f7e11aa60e79db99 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 9 Jul 2024 12:45:03 +0800 Subject: [PATCH 44/83] Remove already effective CS rules --- .php-cs-fixer.dist.php | 9 +-------- .php-cs-fixer.no-header.php | 7 +------ .php-cs-fixer.tests.php | 4 ---- .php-cs-fixer.user-guide.php | 4 ---- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 4ce5e25fbc1d..c0cf8d8fd71a 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -28,8 +28,6 @@ 'ThirdParty', 'Validation/Views', ]) - ->notPath([ - ]) ->notName('#Foobar.php$#') ->append([ __FILE__, @@ -41,12 +39,7 @@ __DIR__ . '/spark', ]); -$overrides = [ - // for updating to coding-standard - 'modernize_strpos' => true, - 'ordered_attributes' => ['order' => [], 'sort_algorithm' => 'alpha'], - 'php_unit_attributes' => true, -]; +$overrides = []; $options = [ 'cacheFile' => 'build/.php-cs-fixer.cache', diff --git a/.php-cs-fixer.no-header.php b/.php-cs-fixer.no-header.php index e7d9647e317e..cd10717aa5a2 100644 --- a/.php-cs-fixer.no-header.php +++ b/.php-cs-fixer.no-header.php @@ -29,12 +29,7 @@ __DIR__ . '/admin/starter/builds', ]); -$overrides = [ - // for updating to coding-standard - 'modernize_strpos' => true, - 'ordered_attributes' => ['order' => [], 'sort_algorithm' => 'alpha'], - 'php_unit_attributes' => true, -]; +$overrides = []; $options = [ 'cacheFile' => 'build/.php-cs-fixer.no-header.cache', diff --git a/.php-cs-fixer.tests.php b/.php-cs-fixer.tests.php index 1b4bfd71e30d..7d5c1fad5e67 100644 --- a/.php-cs-fixer.tests.php +++ b/.php-cs-fixer.tests.php @@ -35,10 +35,6 @@ $overrides = [ 'void_return' => true, - // for updating to coding-standard - 'modernize_strpos' => true, - 'ordered_attributes' => ['order' => [], 'sort_algorithm' => 'alpha'], - 'php_unit_attributes' => true, ]; $options = [ diff --git a/.php-cs-fixer.user-guide.php b/.php-cs-fixer.user-guide.php index 3be7cd45c708..6382201525e4 100644 --- a/.php-cs-fixer.user-guide.php +++ b/.php-cs-fixer.user-guide.php @@ -39,10 +39,6 @@ 'import_symbols' => false, 'leading_backslash_in_global_namespace' => true, ], - // for updating to coding-standard - 'modernize_strpos' => true, - 'ordered_attributes' => ['order' => [], 'sort_algorithm' => 'alpha'], - 'php_unit_attributes' => true, ]; $options = [ From b67971191547d440a6756c33065997d26cd17bd9 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 9 Jul 2024 12:58:32 +0800 Subject: [PATCH 45/83] Depend on main config --- .php-cs-fixer.no-header.php | 24 ++++++++++-------------- .php-cs-fixer.tests.php | 32 +++++++++----------------------- .php-cs-fixer.user-guide.php | 23 +++++++++-------------- 3 files changed, 28 insertions(+), 51 deletions(-) diff --git a/.php-cs-fixer.no-header.php b/.php-cs-fixer.no-header.php index cd10717aa5a2..f3bc97dc78ac 100644 --- a/.php-cs-fixer.no-header.php +++ b/.php-cs-fixer.no-header.php @@ -11,12 +11,12 @@ * the LICENSE file that was distributed with this source code. */ -use CodeIgniter\CodingStandard\CodeIgniter4; -use Nexus\CsConfig\Factory; -use Nexus\CsConfig\Fixer\Comment\NoCodeSeparatorCommentFixer; -use Nexus\CsConfig\FixerGenerator; +use PhpCsFixer\ConfigInterface; use PhpCsFixer\Finder; +/** @var ConfigInterface $config */ +$config = require __DIR__ . '/.php-cs-fixer.dist.php'; + $finder = Finder::create() ->files() ->in([ @@ -29,15 +29,11 @@ __DIR__ . '/admin/starter/builds', ]); -$overrides = []; - -$options = [ - 'cacheFile' => 'build/.php-cs-fixer.no-header.cache', - 'finder' => $finder, - 'customFixers' => FixerGenerator::create('vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer'), - 'customRules' => [ - NoCodeSeparatorCommentFixer::name() => true, - ], +$overrides = [ + 'header_comment' => false, ]; -return Factory::create(new CodeIgniter4(), $overrides, $options)->forProjects(); +return $config + ->setFinder($finder) + ->setCacheFile('build/.php-cs-fixer.no-header.cache') + ->setRules(array_merge($config->getRules(), $overrides)); diff --git a/.php-cs-fixer.tests.php b/.php-cs-fixer.tests.php index 7d5c1fad5e67..28a7124909e5 100644 --- a/.php-cs-fixer.tests.php +++ b/.php-cs-fixer.tests.php @@ -11,43 +11,29 @@ * the LICENSE file that was distributed with this source code. */ -use CodeIgniter\CodingStandard\CodeIgniter4; -use Nexus\CsConfig\Factory; -use Nexus\CsConfig\Fixer\Comment\NoCodeSeparatorCommentFixer; -use Nexus\CsConfig\FixerGenerator; +use PhpCsFixer\ConfigInterface; use PhpCsFixer\Finder; +/** @var ConfigInterface $config */ +$config = require __DIR__ . '/.php-cs-fixer.dist.php'; + $finder = Finder::create() ->files() ->in([ __DIR__ . '/tests', ]) - ->exclude([ - ]) ->notPath([ '_support/View/Cells/multiplier.php', '_support/View/Cells/colors.php', '_support/View/Cells/addition.php', ]) - ->notName('#Foobar.php$#') - ->append([ - ]); + ->notName('#Foobar.php$#'); $overrides = [ 'void_return' => true, ]; -$options = [ - 'cacheFile' => 'build/.php-cs-fixer.tests.cache', - 'finder' => $finder, - 'customFixers' => FixerGenerator::create('vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer'), - 'customRules' => [ - NoCodeSeparatorCommentFixer::name() => true, - ], -]; - -return Factory::create(new CodeIgniter4(), $overrides, $options)->forLibrary( - 'CodeIgniter 4 framework', - 'CodeIgniter Foundation', - 'admin@codeigniter.com' -); +return $config + ->setFinder($finder) + ->setCacheFile('build/.php-cs-fixer.tests.cache') + ->setRules(array_merge($config->getRules(), $overrides)); diff --git a/.php-cs-fixer.user-guide.php b/.php-cs-fixer.user-guide.php index 6382201525e4..6b925ee8b0b7 100644 --- a/.php-cs-fixer.user-guide.php +++ b/.php-cs-fixer.user-guide.php @@ -11,12 +11,12 @@ * the LICENSE file that was distributed with this source code. */ -use CodeIgniter\CodingStandard\CodeIgniter4; -use Nexus\CsConfig\Factory; -use Nexus\CsConfig\Fixer\Comment\NoCodeSeparatorCommentFixer; -use Nexus\CsConfig\FixerGenerator; +use PhpCsFixer\ConfigInterface; use PhpCsFixer\Finder; +/** @var ConfigInterface $config */ +$config = require __DIR__ . '/.php-cs-fixer.dist.php'; + $finder = Finder::create() ->files() ->in([ @@ -32,6 +32,7 @@ $overrides = [ 'echo_tag_syntax' => false, + 'header_comment' => false, 'php_unit_internal_class' => false, 'no_unused_imports' => false, 'class_attributes_separation' => false, @@ -41,13 +42,7 @@ ], ]; -$options = [ - 'cacheFile' => 'build/.php-cs-fixer.user-guide.cache', - 'finder' => $finder, - 'customFixers' => FixerGenerator::create('vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer'), - 'customRules' => [ - NoCodeSeparatorCommentFixer::name() => true, - ], -]; - -return Factory::create(new CodeIgniter4(), $overrides, $options)->forProjects(); +return $config + ->setFinder($finder) + ->setCacheFile('build/.php-cs-fixer.user-guide.cache') + ->setRules(array_merge($config->getRules(), $overrides)); From 04e7e6bdc57d44ad829ddd47826b0c9da70f1d2d Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 9 Jul 2024 14:23:12 +0800 Subject: [PATCH 46/83] fix: Prevent invalid session handlers --- system/Config/BaseService.php | 3 ++- system/Config/Services.php | 17 ++++++++++++---- tests/system/Config/ServicesTest.php | 29 ++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/system/Config/BaseService.php b/system/Config/BaseService.php index 5bd55403beba..687044be0713 100644 --- a/system/Config/BaseService.php +++ b/system/Config/BaseService.php @@ -75,6 +75,7 @@ use Config\Optimize; use Config\Pager as ConfigPager; use Config\Services as AppServices; +use Config\Session as ConfigSession; use Config\Toolbar as ConfigToolbar; use Config\Validation as ConfigValidation; use Config\View as ConfigView; @@ -130,7 +131,7 @@ * @method static Router router(RouteCollectionInterface $routes = null, Request $request = null, $getShared = true) * @method static RouteCollection routes($getShared = true) * @method static Security security(App $config = null, $getShared = true) - * @method static Session session(App $config = null, $getShared = true) + * @method static Session session(ConfigSession $config = null, $getShared = true) * @method static SiteURIFactory siteurifactory(App $config = null, Superglobals $superglobals = null, $getShared = true) * @method static Superglobals superglobals(array $server = null, array $get = null, bool $getShared = true) * @method static Throttler throttler($getShared = true) diff --git a/system/Config/Services.php b/system/Config/Services.php index 422799e0b87c..e37b1278e9a7 100644 --- a/system/Config/Services.php +++ b/system/Config/Services.php @@ -51,6 +51,7 @@ use CodeIgniter\Router\RouteCollectionInterface; use CodeIgniter\Router\Router; use CodeIgniter\Security\Security; +use CodeIgniter\Session\Handlers\BaseHandler as SessionBaseHandler; use CodeIgniter\Session\Handlers\Database\MySQLiHandler; use CodeIgniter\Session\Handlers\Database\PostgreHandler; use CodeIgniter\Session\Handlers\DatabaseHandler; @@ -88,6 +89,7 @@ use Config\Toolbar as ToolbarConfig; use Config\Validation as ValidationConfig; use Config\View as ViewConfig; +use InvalidArgumentException; use Locale; /** @@ -674,17 +676,24 @@ public static function session(?SessionConfig $config = null, bool $getShared = if ($driverName === DatabaseHandler::class) { $DBGroup = $config->DBGroup ?? config(Database::class)->defaultGroup; - $db = Database::connect($DBGroup); - $driver = $db->getPlatform(); + $driverPlatform = Database::connect($DBGroup)->getPlatform(); - if ($driver === 'MySQLi') { + if ($driverPlatform === 'MySQLi') { $driverName = MySQLiHandler::class; - } elseif ($driver === 'Postgre') { + } elseif ($driverPlatform === 'Postgre') { $driverName = PostgreHandler::class; } } + if (! class_exists($driverName) || ! is_a($driverName, SessionBaseHandler::class, true)) { + throw new InvalidArgumentException(sprintf( + 'Invalid session handler "%s" provided.', + $driverName + )); + } + + /** @var SessionBaseHandler $driver */ $driver = new $driverName($config, AppServices::get('request')->getIPAddress()); $driver->setLogger($logger); diff --git a/tests/system/Config/ServicesTest.php b/tests/system/Config/ServicesTest.php index 7825687841c7..e80e2d394eeb 100644 --- a/tests/system/Config/ServicesTest.php +++ b/tests/system/Config/ServicesTest.php @@ -46,6 +46,9 @@ use Config\App; use Config\Exceptions; use Config\Security as SecurityConfig; +use Config\Session as ConfigSession; +use InvalidArgumentException; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\PreserveGlobalState; use PHPUnit\Framework\Attributes\RunInSeparateProcess; @@ -259,6 +262,32 @@ public function testNewSessionWithNullConfig(): void $this->assertInstanceOf(Session::class, $actual); } + #[DataProvider('provideNewSessionInvalid')] + #[PreserveGlobalState(false)] + #[RunInSeparateProcess] + public function testNewSessionWithInvalidHandler(string $driver): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(sprintf('Invalid session handler "%s" provided.', $driver)); + + $config = new ConfigSession(); + + $config->driver = $driver; + Services::session($config, false); + } + + /** + * @return iterable + */ + public static function provideNewSessionInvalid(): iterable + { + yield 'just a string' => ['file']; + + yield 'inexistent class' => ['Foo']; + + yield 'other class' => [self::class]; + } + #[PreserveGlobalState(false)] #[RunInSeparateProcess] public function testCallStatic(): void From 98ee5d4adba8973b64848f9515ca1760d38e5620 Mon Sep 17 00:00:00 2001 From: christianberkman <39840601+christianberkman@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:32:48 +0300 Subject: [PATCH 47/83] doc: add exception to docblock --- system/Files/File.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Files/File.php b/system/Files/File.php index 02c8f181b19b..3ac2ffd9f1aa 100644 --- a/system/Files/File.php +++ b/system/Files/File.php @@ -59,7 +59,8 @@ public function __construct(string $path, bool $checkFile = false) * * Implementations SHOULD return the value stored in the "size" key of * the file in the $_FILES array if available, as PHP calculates this based - * on the actual size transmitted. + * on the actual size transmitted. A RuntimeException will be thrown if the file + * does not exist or an error occurs. * * @return false|int The file size in bytes, or false on failure */ From a7190d504354b8fd1b4881dfbef1c3b300291e34 Mon Sep 17 00:00:00 2001 From: christianberkman <39840601+christianberkman@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:34:00 +0300 Subject: [PATCH 48/83] doc: add posibility of exception --- user_guide_src/source/libraries/files.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index 0b55982692c2..f30e067f57c4 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -46,6 +46,8 @@ Returns the size of the uploaded file in bytes: .. literalinclude:: files/004.php +A RuntimeException will be thrown if the file does not exist or an error occurs. + getSizeByUnit() =============== @@ -54,6 +56,8 @@ the results in kilobytes or megabytes, respectively: .. literalinclude:: files/005.php +A RuntimeException will be thrown if the file does not exist or an error occurs. + getMimeType() ============= From c4396c321f174ddd3ffe98470cc982aa46d348b0 Mon Sep 17 00:00:00 2001 From: christianberkman <39840601+christianberkman@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:32:45 +0300 Subject: [PATCH 49/83] delete stray empty space --- system/Files/File.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Files/File.php b/system/Files/File.php index 3ac2ffd9f1aa..15b53262e9c2 100644 --- a/system/Files/File.php +++ b/system/Files/File.php @@ -60,7 +60,7 @@ public function __construct(string $path, bool $checkFile = false) * Implementations SHOULD return the value stored in the "size" key of * the file in the $_FILES array if available, as PHP calculates this based * on the actual size transmitted. A RuntimeException will be thrown if the file - * does not exist or an error occurs. + * does not exist or an error occurs. * * @return false|int The file size in bytes, or false on failure */ From 77609b1c9a3d751fe36ca2d04b2617d6f891323c Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Jul 2024 17:54:59 +0900 Subject: [PATCH 50/83] fix: DebugBar CSS for daisyUI --- admin/css/debug-toolbar/toolbar.scss | 5 +++++ system/Debug/Toolbar/Views/toolbar.css | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/admin/css/debug-toolbar/toolbar.scss b/admin/css/debug-toolbar/toolbar.scss index 97a92690b937..eec3d25546e3 100644 --- a/admin/css/debug-toolbar/toolbar.scss +++ b/admin/css/debug-toolbar/toolbar.scss @@ -95,6 +95,7 @@ } h2 { + font-weight: bold; font-size: $base-size; margin: 0; padding: 5px 0 10px 0; @@ -292,6 +293,8 @@ // The tabs container .tab { + height: fit-content; + text-align: left; bottom: 35px; display: none; left: 0; @@ -306,6 +309,8 @@ // The "Timeline" tab .timeline { + position: static; + display: table; margin-left: 0; width: 100%; diff --git a/system/Debug/Toolbar/Views/toolbar.css b/system/Debug/Toolbar/Views/toolbar.css index 2e165b825e99..b9f13c51ff2e 100644 --- a/system/Debug/Toolbar/Views/toolbar.css +++ b/system/Debug/Toolbar/Views/toolbar.css @@ -60,6 +60,7 @@ margin-right: 5px; } #debug-bar h2 { + font-weight: bold; font-size: 16px; margin: 0; padding: 5px 0 10px 0; @@ -213,6 +214,8 @@ white-space: nowrap; } #debug-bar .tab { + height: fit-content; + text-align: left; bottom: 35px; display: none; left: 0; @@ -225,6 +228,8 @@ z-index: 9999; } #debug-bar .timeline { + position: static; + display: table; margin-left: 0; width: 100%; } From ecf37d9db8844ddc9c2c469d31f68faa3dc20f7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:44:53 +0000 Subject: [PATCH 51/83] chore(deps-dev): update rector/rector requirement from 1.2.0 to 1.2.1 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/1.2.0...1.2.1) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ce3316112c49..bd2fe5688873 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "phpunit/phpcov": "^9.0.2", "phpunit/phpunit": "^10.5.16", "predis/predis": "^1.1 || ^2.0", - "rector/rector": "1.2.0", + "rector/rector": "1.2.1", "vimeo/psalm": "^5.0" }, "replace": { From d7a9c95ebb7899bdec70c77735883908c58ba85f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 16 Jul 2024 23:14:02 +0700 Subject: [PATCH 52/83] re-run rector --- system/Helpers/text_helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Helpers/text_helper.php b/system/Helpers/text_helper.php index 7f5fb2cf2d3f..ae6b6f111c81 100644 --- a/system/Helpers/text_helper.php +++ b/system/Helpers/text_helper.php @@ -310,7 +310,7 @@ function convert_accented_characters(string $str): string if (! is_array($arrayFrom)) { $config = new ForeignCharacters(); - if (empty($config->characterList) || ! is_array($config->characterList)) { + if ($config->characterList === [] || ! is_array($config->characterList)) { $arrayFrom = []; $arrayTo = []; From 68459896aae356cbde1d5ff0cb626c53c688179b Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 16 Jul 2024 23:16:59 +0700 Subject: [PATCH 53/83] regenerate phpstan-baseline --- phpstan-baseline.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index bd665e22f5f7..ae7e70c68f26 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -7453,12 +7453,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Helpers/test_helper.php', ]; -$ignoreErrors[] = [ - // identifier: empty.notAllowed - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Helpers/text_helper.php', -]; $ignoreErrors[] = [ // identifier: missingType.iterableValue 'message' => '#^Function strip_slashes\\(\\) has parameter \\$str with no value type specified in iterable type array\\.$#', From 49ffabbf376596f4fdb8694a5b654f68388bb366 Mon Sep 17 00:00:00 2001 From: Toto Date: Mon, 22 Jul 2024 21:04:26 +0700 Subject: [PATCH 54/83] docs: referrer is undefined --- user_guide_src/source/libraries/user_agent/005.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/user_agent/005.php b/user_guide_src/source/libraries/user_agent/005.php index 944c70975971..80aad0f42c59 100644 --- a/user_guide_src/source/libraries/user_agent/005.php +++ b/user_guide_src/source/libraries/user_agent/005.php @@ -1,5 +1,5 @@ isReferral()) { - echo $agent->referrer(); + echo $agent->getReferrer(); } From ecb6c1bcde479853ce6be2d2ed391e5f4cff5d2b Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 23 Jul 2024 00:53:15 +0800 Subject: [PATCH 55/83] refactor: use `PgSql` classes --- system/Database/Postgre/Connection.php | 6 ++---- system/Database/Postgre/PreparedQuery.php | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index d3af2380156e..ec886dbd4d8b 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -58,8 +58,7 @@ class Connection extends BaseConnection /** * Connect to the database. * - * @return false|resource - * @phpstan-return false|PgSqlConnection + * @return false|PgSqlConnection */ public function connect(bool $persistent = false) { @@ -197,8 +196,7 @@ public function getVersion(): string /** * Executes the query against the database. * - * @return false|resource - * @phpstan-return false|PgSqlResult + * @return false|PgSqlResult */ protected function execute(string $sql) { diff --git a/system/Database/Postgre/PreparedQuery.php b/system/Database/Postgre/PreparedQuery.php index 832108675ab9..fbea6ac14f3a 100644 --- a/system/Database/Postgre/PreparedQuery.php +++ b/system/Database/Postgre/PreparedQuery.php @@ -95,8 +95,7 @@ public function _execute(array $data): bool /** * Returns the result object for the prepared query or false on failure. * - * @return resource|null - * @phpstan-return PgSqlResult|null + * @return PgSqlResult|null */ public function _getResult() { From f540b0dea6cc7206b7528dbef12231a22fe68d53 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Jul 2024 16:35:54 +0900 Subject: [PATCH 56/83] test: add test for route group filter and route filter --- tests/system/Router/RouteCollectionTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/system/Router/RouteCollectionTest.php b/tests/system/Router/RouteCollectionTest.php index 89959cd5f33e..5c06154a5d31 100644 --- a/tests/system/Router/RouteCollectionTest.php +++ b/tests/system/Router/RouteCollectionTest.php @@ -440,6 +440,22 @@ static function ($routes): void { $this->assertSame($expected, $routes->getRoutesOptions()); } + public function testGroupFilterAndRouteFilter(): void + { + $routes = $this->getCollector(); + + $routes->group('admin', ['filter' => ['csrf']], static function ($routes): void { + $routes->get('profile', 'Admin\Profile::index', ['filter' => ['honeypot']]); + }); + + $expected = [ + 'admin/profile' => [ + 'filter' => ['csrf', 'honeypot'], + ], + ]; + $this->assertSame($expected, $routes->getRoutesOptions()); + } + public function testGroupingWorksWithEmptyStringPrefix(): void { $routes = $this->getCollector(); From 13f02b31f31ea8d646be8403f46935f15e13e466 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Jul 2024 16:44:00 +0900 Subject: [PATCH 57/83] fix: route group filters are not merged into route filters --- system/Router/RouteCollection.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 322987dc791b..8fba39dc03be 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -1456,6 +1456,12 @@ protected function create(string $verb, string $from, $to, ?array $options = nul $to = $this->processArrayCallableSyntax($from, $to); } + // Merge group filters. + if (isset($options['filter'])) { + $currentFilter = (array) ($this->currentOptions['filter'] ?? []); + $options['filter'] = array_merge($currentFilter, (array) $options['filter']); + } + $options = array_merge($this->currentOptions ?? [], $options ?? []); // Route priority detect From e580856404f248b69c919c1608f3e1fdb8824d28 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Jul 2024 16:52:41 +0900 Subject: [PATCH 58/83] docs: add docs --- user_guide_src/source/changelogs/v4.5.4.rst | 2 ++ user_guide_src/source/incoming/routing.rst | 3 +++ 2 files changed, 5 insertions(+) diff --git a/user_guide_src/source/changelogs/v4.5.4.rst b/user_guide_src/source/changelogs/v4.5.4.rst index 51a9fd74f407..d09413124ee0 100644 --- a/user_guide_src/source/changelogs/v4.5.4.rst +++ b/user_guide_src/source/changelogs/v4.5.4.rst @@ -30,6 +30,8 @@ Deprecations Bugs Fixed ********** +- **Routing:** Fixed a bug that filters passed to ``$routes->group()`` were not + merged into filters passed to the inner routes. - **CURLRequest:** Fixed a bug preventing the use of strings for ``version`` in the config array when making requests. diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index b822d4cce17e..90c99ad73b61 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -564,6 +564,9 @@ run the filter before or after the controller. This is especially handy during a The value for the filter must match one of the aliases defined within **app/Config/Filters.php**. +.. note:: Prior to v4.5.4, due to a bug, filters passed to the ``group()`` were + not merged into the filters passed to the inner routes. + Setting Other Options ===================== From 8c94deb2ad7e3d9374c0740d7286af9ac5c82614 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Mon, 22 Jul 2024 21:43:26 +0800 Subject: [PATCH 59/83] chore: fix invalid symbol '"' --- .github/workflows/test-psalm.yml | 2 +- admin/starter/.github/workflows/phpunit.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-psalm.yml b/.github/workflows/test-psalm.yml index a623109fbb15..145d984b8389 100644 --- a/.github/workflows/test-psalm.yml +++ b/.github/workflows/test-psalm.yml @@ -24,7 +24,7 @@ jobs: build: name: Psalm Analysis runs-on: ubuntu-latest - if: "!contains(github.event.head_commit.message, '[ci skip]')" + if: (! contains(github.event.head_commit.message, '[ci skip]')) steps: - name: Checkout diff --git a/admin/starter/.github/workflows/phpunit.yml b/admin/starter/.github/workflows/phpunit.yml index f43435df9765..2be22ec16095 100644 --- a/admin/starter/.github/workflows/phpunit.yml +++ b/admin/starter/.github/workflows/phpunit.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest - if: "!contains(github.event.head_commit.message, '[ci skip]')" + if: (! contains(github.event.head_commit.message, '[ci skip]')) steps: - name: Checkout From ed01a7e7f3820f8016c50695a59f30525d0b84f1 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 13 Jul 2024 00:34:17 +0800 Subject: [PATCH 60/83] Move tools' dependencies to separate utils directory --- .gitattributes | 1 - composer.json | 47 ++++++++++++---------------------- tools/phpmetrics/composer.json | 5 ---- utils/composer.json | 30 ++++++++++++++++++++++ 4 files changed, 47 insertions(+), 36 deletions(-) delete mode 100644 tools/phpmetrics/composer.json create mode 100644 utils/composer.json diff --git a/.gitattributes b/.gitattributes index c41e331ff63c..3f67f2e35167 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,7 +17,6 @@ CONTRIBUTING.md export-ignore # contributor/development files tests/ export-ignore -tools/ export-ignore utils/ export-ignore .php-cs-fixer.dist.php export-ignore .php-cs-fixer.no-header.php export-ignore diff --git a/composer.json b/composer.json index bd2fe5688873..2dcc1cd90ce9 100644 --- a/composer.json +++ b/composer.json @@ -17,23 +17,13 @@ "psr/log": "^3.0" }, "require-dev": { - "codeigniter/coding-standard": "^1.7", - "codeigniter/phpstan-codeigniter": "^1.4", - "ergebnis/composer-normalize": "^2.28", "fakerphp/faker": "^1.9", - "friendsofphp/php-cs-fixer": "^3.47.1", "kint-php/kint": "^5.0.4", "mikey179/vfsstream": "^1.6", - "nexusphp/cs-config": "^3.6", "nexusphp/tachycardia": "^2.0", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-strict-rules": "^1.6", "phpunit/phpcov": "^9.0.2", "phpunit/phpunit": "^10.5.16", - "predis/predis": "^1.1 || ^2.0", - "rector/rector": "1.2.1", - "vimeo/psalm": "^5.0" + "predis/predis": "^1.1 || ^2.0" }, "replace": { "codeigniter4/framework": "self.version" @@ -71,15 +61,10 @@ }, "autoload-dev": { "psr-4": { - "CodeIgniter\\": "tests/system/", - "Utils\\": "utils/" + "CodeIgniter\\": "tests/system/" } }, "config": { - "allow-plugins": { - "ergebnis/composer-normalize": true, - "phpstan/extension-installer": true - }, "optimize-autoloader": true, "preferred-install": "dist", "sort-packages": true @@ -90,30 +75,32 @@ } }, "scripts": { + "post-autoload-dump": [ + "@composer update --working-dir=utils" + ], "post-update-cmd": [ - "CodeIgniter\\ComposerScripts::postUpdate", - "composer update --working-dir=tools/phpmetrics" + "CodeIgniter\\ComposerScripts::postUpdate" ], "analyze": [ "Composer\\Config::disableProcessTimeout", - "bash -c \"XDEBUG_MODE=off phpstan analyse\"", - "rector process --dry-run" + "bash -c \"XDEBUG_MODE=off utils/vendor/bin/phpstan analyse\"", + "utils/vendor/bin/rector process --dry-run" ], "cs": [ "Composer\\Config::disableProcessTimeout", - "php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php", - "php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php", - "php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.tests.php", - "php-cs-fixer fix --ansi --verbose --dry-run --diff" + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php", + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php", + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.tests.php", + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff" ], "cs-fix": [ "Composer\\Config::disableProcessTimeout", - "php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.user-guide.php", - "php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.no-header.php", - "php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.tests.php", - "php-cs-fixer fix --ansi --verbose --diff" + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.user-guide.php", + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.no-header.php", + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.tests.php", + "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --diff" ], - "metrics": "tools/phpmetrics/vendor/bin/phpmetrics --config=phpmetrics.json", + "metrics": "utils/vendor/bin/phpmetrics --config=phpmetrics.json", "sa": "@analyze", "style": "@cs-fix", "test": "phpunit" diff --git a/tools/phpmetrics/composer.json b/tools/phpmetrics/composer.json deleted file mode 100644 index eef46d0db139..000000000000 --- a/tools/phpmetrics/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require-dev": { - "phpmetrics/phpmetrics": "^3.0rc6" - } -} diff --git a/utils/composer.json b/utils/composer.json new file mode 100644 index 000000000000..37196a95d194 --- /dev/null +++ b/utils/composer.json @@ -0,0 +1,30 @@ +{ + "require": { + "php": "^8.1", + "codeigniter/coding-standard": "^1.7", + "codeigniter/phpstan-codeigniter": "^1.4", + "ergebnis/composer-normalize": "^2.28", + "friendsofphp/php-cs-fixer": "^3.47.1", + "nexusphp/cs-config": "^3.6", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.11", + "phpmetrics/phpmetrics": "^2.8 || ^3.0rc6", + "phpstan/phpstan-strict-rules": "^1.6", + "rector/rector": "1.2.1", + "vimeo/psalm": "^5.0" + }, + "autoload": { + "psr-4": { + "Utils\\": "src/" + } + }, + "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true, + "phpstan/extension-installer": true + }, + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true + } +} From f91db3bcb8411b214187f082a4e68de13ff97a45 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 13 Jul 2024 00:40:36 +0800 Subject: [PATCH 61/83] Fix admin/pre-commit --- admin/pre-commit | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/admin/pre-commit b/admin/pre-commit index f64268277e72..107adc35a3f7 100644 --- a/admin/pre-commit +++ b/admin/pre-commit @@ -26,9 +26,9 @@ if [ "$FILES" != "" ]; then # Run on whole codebase to skip on unnecessary filtering # Run first on app, admin, public if [ -d /proc/cygdrive ]; then - ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php + ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php else - php ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php + php ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php fi if [ $? != 0 ]; then @@ -38,9 +38,9 @@ if [ "$FILES" != "" ]; then # Next, run on system, tests, utils, and root PHP files if [ -d /proc/cygdrive ]; then - ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff + ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff else - php ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff + php ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff fi if [ $? != 0 ]; then @@ -50,9 +50,9 @@ if [ "$FILES" != "" ]; then # Next, run on user_guide_src/source PHP files if [ -d /proc/cygdrive ]; then - ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php + ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php else - php ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php + php ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php fi if [ $? != 0 ]; then From 368bffa94a06caeba2215bd79b3288229f0d9098 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 13 Jul 2024 00:41:47 +0800 Subject: [PATCH 62/83] Fix phpstan errors --- phpstan-baseline.php | 6 ------ phpstan.neon.dist | 2 +- .../PHPStan/CheckUseStatementsAfterLicenseRule.php | 13 ++++++++++++- 3 files changed, 13 insertions(+), 8 deletions(-) rename utils/{ => src}/PHPStan/CheckUseStatementsAfterLicenseRule.php (79%) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index ae7e70c68f26..1b36c4a8f8ee 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -18793,11 +18793,5 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/View/ViewTest.php', ]; -$ignoreErrors[] = [ - // identifier: method.childParameterType - 'message' => '#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Stmt\\) of method Utils\\\\PHPStan\\\\CheckUseStatementsAfterLicenseRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\\\:\\:processNode\\(\\)$#', - 'count' => 1, - 'path' => __DIR__ . '/utils/PHPStan/CheckUseStatementsAfterLicenseRule.php', -]; return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; diff --git a/phpstan.neon.dist b/phpstan.neon.dist index eccd0f88db75..c67aa93fcb04 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -18,7 +18,7 @@ parameters: - app - system - tests - - utils/PHPStan + - utils/src/PHPStan excludePaths: - app/Views/errors/cli/* - app/Views/errors/html/* diff --git a/utils/PHPStan/CheckUseStatementsAfterLicenseRule.php b/utils/src/PHPStan/CheckUseStatementsAfterLicenseRule.php similarity index 79% rename from utils/PHPStan/CheckUseStatementsAfterLicenseRule.php rename to utils/src/PHPStan/CheckUseStatementsAfterLicenseRule.php index a3ccaf215d6e..4b23d3204ca1 100644 --- a/utils/PHPStan/CheckUseStatementsAfterLicenseRule.php +++ b/utils/src/PHPStan/CheckUseStatementsAfterLicenseRule.php @@ -18,8 +18,13 @@ use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Use_; use PHPStan\Analyser\Scope; +use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; +use PHPStan\Rules\RuleErrorBuilder; +/** + * @implements Rule + */ final class CheckUseStatementsAfterLicenseRule implements Rule { private const ERROR_MESSAGE = 'Use statement must be located after license docblock'; @@ -32,6 +37,8 @@ public function getNodeType(): string /** * @param Stmt $node + * + * @return list */ public function processNode(Node $node, Scope $scope): array { @@ -54,7 +61,11 @@ public function processNode(Node $node, Scope $scope): array while ($previous) { if ($previous instanceof Use_) { - return [self::ERROR_MESSAGE]; + return [ + RuleErrorBuilder::message(self::ERROR_MESSAGE) + ->identifier('codeigniter.useStmtAfterLicense') + ->build(), + ]; } $previous = $previous->getAttribute('previous'); From e7b76864054648da2c49ba241e499a6d7a736ba8 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 13 Jul 2024 00:42:41 +0800 Subject: [PATCH 63/83] Fix rector errors --- rector.php | 13 ++++++++----- ...PassStrictParameterToFunctionParameterRector.php | 0 .../RemoveErrorSuppressInTryCatchStmtsRector.php | 0 .../UnderscoreToCamelCaseVariableNameRector.php | 0 4 files changed, 8 insertions(+), 5 deletions(-) rename utils/{ => src}/Rector/PassStrictParameterToFunctionParameterRector.php (100%) rename utils/{ => src}/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php (100%) rename utils/{ => src}/Rector/UnderscoreToCamelCaseVariableNameRector.php (100%) diff --git a/rector.php b/rector.php index 7bb54aab325e..812e703e3b51 100644 --- a/rector.php +++ b/rector.php @@ -73,17 +73,20 @@ FileCacheStorage::class ) // paths to refactor; solid alternative to CLI arguments - ->withPaths( - [__DIR__ . '/app', __DIR__ . '/system', __DIR__ . '/tests', __DIR__ . '/utils'] - ) + ->withPaths([ + __DIR__ . '/app', + __DIR__ . '/system', + __DIR__ . '/tests', + __DIR__ . '/utils/src', + ]) // do you need to include constants, class aliases or custom autoloader? files listed will be executed ->withBootstrapFiles([ __DIR__ . '/system/Test/bootstrap.php', ]) ->withPHPStanConfigs([ __DIR__ . '/phpstan.neon.dist', - __DIR__ . '/vendor/codeigniter/phpstan-codeigniter/extension.neon', - __DIR__ . '/vendor/phpstan/phpstan-strict-rules/rules.neon', + __DIR__ . '/utils/vendor/codeigniter/phpstan-codeigniter/extension.neon', + __DIR__ . '/utils/vendor/phpstan/phpstan-strict-rules/rules.neon', ]) // is there a file you need to skip? ->withSkip([ diff --git a/utils/Rector/PassStrictParameterToFunctionParameterRector.php b/utils/src/Rector/PassStrictParameterToFunctionParameterRector.php similarity index 100% rename from utils/Rector/PassStrictParameterToFunctionParameterRector.php rename to utils/src/Rector/PassStrictParameterToFunctionParameterRector.php diff --git a/utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php b/utils/src/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php similarity index 100% rename from utils/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php rename to utils/src/Rector/RemoveErrorSuppressInTryCatchStmtsRector.php diff --git a/utils/Rector/UnderscoreToCamelCaseVariableNameRector.php b/utils/src/Rector/UnderscoreToCamelCaseVariableNameRector.php similarity index 100% rename from utils/Rector/UnderscoreToCamelCaseVariableNameRector.php rename to utils/src/Rector/UnderscoreToCamelCaseVariableNameRector.php From 2bbf832dc46621ef570063d431760aa6257d2286 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 13 Jul 2024 00:43:04 +0800 Subject: [PATCH 64/83] Fix php-cs-fixer errors --- .php-cs-fixer.dist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index c0cf8d8fd71a..a50b126db075 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -44,7 +44,7 @@ $options = [ 'cacheFile' => 'build/.php-cs-fixer.cache', 'finder' => $finder, - 'customFixers' => FixerGenerator::create('vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer'), + 'customFixers' => FixerGenerator::create('utils/vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer'), 'customRules' => [ NoCodeSeparatorCommentFixer::name() => true, ], From 8c854b1aa41ef5885526a6b49a5c2abdcd294e3c Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 13 Jul 2024 01:06:57 +0800 Subject: [PATCH 65/83] Fix GH actions --- .github/workflows/reusable-coveralls.yml | 2 ++ .github/workflows/reusable-phpunit-test.yml | 2 ++ .../workflows/reusable-serviceless-phpunit-test.yml | 2 ++ .github/workflows/test-autoreview.yml | 2 ++ .github/workflows/test-coding-standards.yml | 10 ++++++---- .github/workflows/test-deptrac.yml | 2 ++ .github/workflows/test-phpstan.yml | 4 +++- .github/workflows/test-psalm.yml | 4 +++- .github/workflows/test-rector.yml | 4 +++- 9 files changed, 25 insertions(+), 7 deletions(-) diff --git a/.github/workflows/reusable-coveralls.yml b/.github/workflows/reusable-coveralls.yml index af1fd2f5b6c1..c6db84b66f35 100644 --- a/.github/workflows/reusable-coveralls.yml +++ b/.github/workflows/reusable-coveralls.yml @@ -15,6 +15,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/reusable-phpunit-test.yml b/.github/workflows/reusable-phpunit-test.yml index 4943d3f3ac2c..f1e1e4b96933 100644 --- a/.github/workflows/reusable-phpunit-test.yml +++ b/.github/workflows/reusable-phpunit-test.yml @@ -150,6 +150,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/reusable-serviceless-phpunit-test.yml b/.github/workflows/reusable-serviceless-phpunit-test.yml index 8a9f00c5e2e6..a585972ddb63 100644 --- a/.github/workflows/reusable-serviceless-phpunit-test.yml +++ b/.github/workflows/reusable-serviceless-phpunit-test.yml @@ -62,6 +62,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-autoreview.yml b/.github/workflows/test-autoreview.yml index 69545ca6af01..3c208ebf6125 100644 --- a/.github/workflows/test-autoreview.yml +++ b/.github/workflows/test-autoreview.yml @@ -37,6 +37,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-coding-standards.yml b/.github/workflows/test-coding-standards.yml index 7e5f18820288..954d25b45f77 100644 --- a/.github/workflows/test-coding-standards.yml +++ b/.github/workflows/test-coding-standards.yml @@ -34,6 +34,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -58,13 +60,13 @@ jobs: run: composer update --ansi --no-interaction - name: Run lint on `app/`, `admin/`, `public/` - run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.no-header.php --using-cache=no --diff + run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.no-header.php --using-cache=no --diff - name: Run lint on `system/`, `utils/`, and root PHP files - run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --using-cache=no --diff + run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --using-cache=no --diff - name: Run lint on `tests` - run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.tests.php --using-cache=no --diff + run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.tests.php --using-cache=no --diff - name: Run lint on `user_guide_src/source/` - run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.user-guide.php --using-cache=no --diff + run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.user-guide.php --using-cache=no --diff diff --git a/.github/workflows/test-deptrac.yml b/.github/workflows/test-deptrac.yml index fecb289b1b63..796f1ef40147 100644 --- a/.github/workflows/test-deptrac.yml +++ b/.github/workflows/test-deptrac.yml @@ -38,6 +38,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-phpstan.yml b/.github/workflows/test-phpstan.yml index 360b403ac923..f184eefc1ffa 100644 --- a/.github/workflows/test-phpstan.yml +++ b/.github/workflows/test-phpstan.yml @@ -47,6 +47,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -85,4 +87,4 @@ jobs: run: composer update --ansi --no-interaction - name: Run static analysis - run: vendor/bin/phpstan analyse + run: utils/vendor/bin/phpstan analyse diff --git a/.github/workflows/test-psalm.yml b/.github/workflows/test-psalm.yml index 145d984b8389..98df2215fbd0 100644 --- a/.github/workflows/test-psalm.yml +++ b/.github/workflows/test-psalm.yml @@ -29,6 +29,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -68,4 +70,4 @@ jobs: fi - name: Run Psalm analysis - run: vendor/bin/psalm + run: utils/vendor/bin/psalm diff --git a/.github/workflows/test-rector.yml b/.github/workflows/test-rector.yml index 286ca76cab42..8e1600ba95d6 100644 --- a/.github/workflows/test-rector.yml +++ b/.github/workflows/test-rector.yml @@ -49,6 +49,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -85,4 +87,4 @@ jobs: - run: mkdir -p /tmp/rector - name: Run static analysis - run: vendor/bin/rector process --dry-run --no-progress-bar + run: utils/vendor/bin/rector process --dry-run --no-progress-bar From 8609136924a42213af6142261a6594c4d2469f38 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sat, 13 Jul 2024 01:24:28 +0800 Subject: [PATCH 66/83] Fix psalm errors --- utils/composer.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/utils/composer.json b/utils/composer.json index 37196a95d194..83d833e579a9 100644 --- a/utils/composer.json +++ b/utils/composer.json @@ -3,16 +3,23 @@ "php": "^8.1", "codeigniter/coding-standard": "^1.7", "codeigniter/phpstan-codeigniter": "^1.4", + "codeigniter4/codeigniter4": "4.x-dev", "ergebnis/composer-normalize": "^2.28", "friendsofphp/php-cs-fixer": "^3.47.1", "nexusphp/cs-config": "^3.6", + "phpmetrics/phpmetrics": "^2.8 || ^3.0rc6", "phpstan/extension-installer": "^1.3", "phpstan/phpstan": "^1.11", - "phpmetrics/phpmetrics": "^2.8 || ^3.0rc6", "phpstan/phpstan-strict-rules": "^1.6", "rector/rector": "1.2.1", "vimeo/psalm": "^5.0" }, + "repositories": [ + { + "type": "path", + "url": "../" + } + ], "autoload": { "psr-4": { "Utils\\": "src/" From 90ea5c7cc19518fcd87dfee711dee48c3183da7a Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 23 Jul 2024 20:51:44 +0800 Subject: [PATCH 67/83] Move phpstan and rector to root composer.json --- .github/workflows/reusable-coveralls.yml | 2 -- .github/workflows/reusable-phpunit-test.yml | 2 -- .../reusable-serviceless-phpunit-test.yml | 2 -- .github/workflows/test-autoreview.yml | 2 -- .github/workflows/test-coding-standards.yml | 2 -- .github/workflows/test-deptrac.yml | 2 -- .github/workflows/test-phpstan.yml | 4 +--- .github/workflows/test-psalm.yml | 2 -- .github/workflows/test-rector.yml | 4 +--- composer.json | 23 +++++++++++++------ rector.php | 4 ++-- utils/composer.json | 15 +----------- 12 files changed, 21 insertions(+), 43 deletions(-) diff --git a/.github/workflows/reusable-coveralls.yml b/.github/workflows/reusable-coveralls.yml index c6db84b66f35..af1fd2f5b6c1 100644 --- a/.github/workflows/reusable-coveralls.yml +++ b/.github/workflows/reusable-coveralls.yml @@ -15,8 +15,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/reusable-phpunit-test.yml b/.github/workflows/reusable-phpunit-test.yml index f1e1e4b96933..4943d3f3ac2c 100644 --- a/.github/workflows/reusable-phpunit-test.yml +++ b/.github/workflows/reusable-phpunit-test.yml @@ -150,8 +150,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/reusable-serviceless-phpunit-test.yml b/.github/workflows/reusable-serviceless-phpunit-test.yml index a585972ddb63..8a9f00c5e2e6 100644 --- a/.github/workflows/reusable-serviceless-phpunit-test.yml +++ b/.github/workflows/reusable-serviceless-phpunit-test.yml @@ -62,8 +62,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-autoreview.yml b/.github/workflows/test-autoreview.yml index 3c208ebf6125..69545ca6af01 100644 --- a/.github/workflows/test-autoreview.yml +++ b/.github/workflows/test-autoreview.yml @@ -37,8 +37,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-coding-standards.yml b/.github/workflows/test-coding-standards.yml index 954d25b45f77..2146b27b9420 100644 --- a/.github/workflows/test-coding-standards.yml +++ b/.github/workflows/test-coding-standards.yml @@ -34,8 +34,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-deptrac.yml b/.github/workflows/test-deptrac.yml index 796f1ef40147..fecb289b1b63 100644 --- a/.github/workflows/test-deptrac.yml +++ b/.github/workflows/test-deptrac.yml @@ -38,8 +38,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-phpstan.yml b/.github/workflows/test-phpstan.yml index f184eefc1ffa..360b403ac923 100644 --- a/.github/workflows/test-phpstan.yml +++ b/.github/workflows/test-phpstan.yml @@ -47,8 +47,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -87,4 +85,4 @@ jobs: run: composer update --ansi --no-interaction - name: Run static analysis - run: utils/vendor/bin/phpstan analyse + run: vendor/bin/phpstan analyse diff --git a/.github/workflows/test-psalm.yml b/.github/workflows/test-psalm.yml index 98df2215fbd0..b1f5891a46d9 100644 --- a/.github/workflows/test-psalm.yml +++ b/.github/workflows/test-psalm.yml @@ -29,8 +29,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/test-rector.yml b/.github/workflows/test-rector.yml index 8e1600ba95d6..286ca76cab42 100644 --- a/.github/workflows/test-rector.yml +++ b/.github/workflows/test-rector.yml @@ -49,8 +49,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -87,4 +85,4 @@ jobs: - run: mkdir -p /tmp/rector - name: Run static analysis - run: utils/vendor/bin/rector process --dry-run --no-progress-bar + run: vendor/bin/rector process --dry-run --no-progress-bar diff --git a/composer.json b/composer.json index 2dcc1cd90ce9..93f75cea3998 100644 --- a/composer.json +++ b/composer.json @@ -17,13 +17,18 @@ "psr/log": "^3.0" }, "require-dev": { + "codeigniter/phpstan-codeigniter": "^1.4", "fakerphp/faker": "^1.9", "kint-php/kint": "^5.0.4", "mikey179/vfsstream": "^1.6", "nexusphp/tachycardia": "^2.0", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-strict-rules": "^1.6", "phpunit/phpcov": "^9.0.2", "phpunit/phpunit": "^10.5.16", - "predis/predis": "^1.1 || ^2.0" + "predis/predis": "^1.1 || ^2.0", + "rector/rector": "1.2.1" }, "replace": { "codeigniter4/framework": "self.version" @@ -61,10 +66,14 @@ }, "autoload-dev": { "psr-4": { - "CodeIgniter\\": "tests/system/" + "CodeIgniter\\": "tests/system/", + "Utils\\": "utils/src/" } }, "config": { + "allow-plugins": { + "phpstan/extension-installer": true + }, "optimize-autoloader": true, "preferred-install": "dist", "sort-packages": true @@ -75,16 +84,16 @@ } }, "scripts": { - "post-autoload-dump": [ - "@composer update --working-dir=utils" - ], "post-update-cmd": [ "CodeIgniter\\ComposerScripts::postUpdate" ], + "post-autoload-dump": [ + "@composer update --working-dir=utils" + ], "analyze": [ "Composer\\Config::disableProcessTimeout", - "bash -c \"XDEBUG_MODE=off utils/vendor/bin/phpstan analyse\"", - "utils/vendor/bin/rector process --dry-run" + "bash -c \"XDEBUG_MODE=off vendor/bin/phpstan analyse\"", + "vendor/bin/rector process --dry-run" ], "cs": [ "Composer\\Config::disableProcessTimeout", diff --git a/rector.php b/rector.php index 812e703e3b51..d8ab56f3cc8e 100644 --- a/rector.php +++ b/rector.php @@ -85,8 +85,8 @@ ]) ->withPHPStanConfigs([ __DIR__ . '/phpstan.neon.dist', - __DIR__ . '/utils/vendor/codeigniter/phpstan-codeigniter/extension.neon', - __DIR__ . '/utils/vendor/phpstan/phpstan-strict-rules/rules.neon', + __DIR__ . '/vendor/codeigniter/phpstan-codeigniter/extension.neon', + __DIR__ . '/vendor/phpstan/phpstan-strict-rules/rules.neon', ]) // is there a file you need to skip? ->withSkip([ diff --git a/utils/composer.json b/utils/composer.json index 83d833e579a9..65137621e0ba 100644 --- a/utils/composer.json +++ b/utils/composer.json @@ -2,24 +2,12 @@ "require": { "php": "^8.1", "codeigniter/coding-standard": "^1.7", - "codeigniter/phpstan-codeigniter": "^1.4", - "codeigniter4/codeigniter4": "4.x-dev", "ergebnis/composer-normalize": "^2.28", "friendsofphp/php-cs-fixer": "^3.47.1", "nexusphp/cs-config": "^3.6", "phpmetrics/phpmetrics": "^2.8 || ^3.0rc6", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-strict-rules": "^1.6", - "rector/rector": "1.2.1", "vimeo/psalm": "^5.0" }, - "repositories": [ - { - "type": "path", - "url": "../" - } - ], "autoload": { "psr-4": { "Utils\\": "src/" @@ -27,8 +15,7 @@ }, "config": { "allow-plugins": { - "ergebnis/composer-normalize": true, - "phpstan/extension-installer": true + "ergebnis/composer-normalize": true }, "optimize-autoloader": true, "preferred-install": "dist", From ac82913b7ab0b1e7ff8f14c7fa6b3fa1111f321d Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Jul 2024 10:11:48 +0900 Subject: [PATCH 68/83] docs: remove ` Date: Wed, 24 Jul 2024 10:12:26 +0900 Subject: [PATCH 69/83] docs: remove "uploaded" The File class is not only for uploaded files. --- user_guide_src/source/libraries/files.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index b4c69e6c0177..b0e832b78e7d 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -45,7 +45,7 @@ method. This is especially useful to rename files when moving it so that the fil getSize() ========= -Returns the size of the uploaded file in bytes: +Returns the size of the file in bytes: .. literalinclude:: files/004.php :lines: 2- @@ -53,7 +53,7 @@ Returns the size of the uploaded file in bytes: getSizeByUnit() =============== -Returns the size of the uploaded file default in bytes. You can pass in either 'kb' or 'mb' as the first parameter to get +Returns the size of the file default in bytes. You can pass in either ``'kb'`` or ``'mb'`` as the first parameter to get the results in kilobytes or megabytes, respectively: .. literalinclude:: files/005.php From f44e97c166c4c0f5fc80ecf482f3fceca79040df Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Jul 2024 10:13:15 +0900 Subject: [PATCH 70/83] docs: decorate method name --- user_guide_src/source/libraries/files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index b0e832b78e7d..89bfd13ab550 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -92,7 +92,7 @@ By default, the original filename was used. You can specify a new filename by pa .. literalinclude:: files/009.php :lines: 2- -The move() method returns a new File instance that for the relocated file, so you must capture the result if the +The ``move()`` method returns a new File instance that for the relocated file, so you must capture the result if the resulting location is needed: .. literalinclude:: files/010.php From 5340d8d59979d90f2074c0fc9be0a63233958946 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 24 Jul 2024 10:13:56 +0900 Subject: [PATCH 71/83] docs: move sentence down --- user_guide_src/source/libraries/files.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index 89bfd13ab550..8594fd8156c5 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -14,12 +14,13 @@ Getting a File instance *********************** You create a new File instance by passing in the path to the file in the constructor. -By default, the file does not need to exist. However, you can pass an additional argument of "true" -to check that the file exists and throw ``FileNotFoundException()`` if it does not. .. literalinclude:: files/001.php :lines: 2- +By default, the file does not need to exist. However, you can pass an additional argument of ``true`` +to check that the file exists and throw ``FileNotFoundException()`` if it does not. + Taking Advantage of Spl *********************** From 8eb777e2cddda3b5170c917c8ceebe9c31f14661 Mon Sep 17 00:00:00 2001 From: Osman Bozdag Date: Wed, 24 Jul 2024 05:14:48 +0200 Subject: [PATCH 72/83] docs: Remove $ marks in libraries/email.rst Remove $ marks in Preference in libraries/email.rst --- user_guide_src/source/libraries/email.rst | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index f71ff693d87f..ec21b79ddcf2 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -113,37 +113,37 @@ sending email. =================== =================== ============================ ======================================================================= Preference Default Value Options Description =================== =================== ============================ ======================================================================= -**$fromEmail** The email address to be set in the "from" header. -**$fromName** The name to be set in the "from" header. -**$userAgent** CodeIgniter The "user agent". -**$protocol** mail ``mail``, ``sendmail``, The mail sending protocol. +**fromEmail** The email address to be set in the "from" header. +**fromName** The name to be set in the "from" header. +**userAgent** CodeIgniter The "user agent". +**protocol** mail ``mail``, ``sendmail``, The mail sending protocol. or ``smtp`` -**$mailPath** /usr/sbin/sendmail The server path to Sendmail. -**$SMTPHost** SMTP Server Hostname. -**$SMTPUser** SMTP Username. -**$SMTPPass** SMTP Password. -**$SMTPPort** 25 SMTP Port. (If set to ``465``, TLS will be used for the connection +**mailPath** /usr/sbin/sendmail The server path to Sendmail. +**SMTPHost** SMTP Server Hostname. +**SMTPUser** SMTP Username. +**SMTPPass** SMTP Password. +**SMTPPort** 25 SMTP Port. (If set to ``465``, TLS will be used for the connection regardless of ``SMTPCrypto`` setting.) -**$SMTPTimeout** 5 SMTP Timeout (in seconds). -**$SMTPKeepAlive** false ``true``/``false`` Enable persistent SMTP connections. -**$SMTPCrypto** tls ``tls``, ``ssl``, or SMTP Encryption. Setting this to ``ssl`` will create a secure +**SMTPTimeout** 5 SMTP Timeout (in seconds). +**SMTPKeepAlive** false ``true``/``false`` Enable persistent SMTP connections. +**SMTPCrypto** tls ``tls``, ``ssl``, or SMTP Encryption. Setting this to ``ssl`` will create a secure empty string (``''``) channel to the server using SSL, and ``tls`` will issue a ``STARTTLS`` command to the server. Connection on port ``465`` should set this to an empty string (``''``). See also :ref:`email-ssl-tls-for-smtp`. -**$wordWrap** true ``true``/``false`` Enable word-wrap. -**$wrapChars** 76 Character count to wrap at. -**$mailType** text ``text`` or ``html`` Type of mail. If you send HTML email you must send it as a complete web +**wordWrap** true ``true``/``false`` Enable word-wrap. +**wrapChars** 76 Character count to wrap at. +**mailType** text ``text`` or ``html`` Type of mail. If you send HTML email you must send it as a complete web page. Make sure you don't have any relative links or relative image paths otherwise they will not work. -**$charset** UTF-8 Character set (``utf-8``, ``iso-8859-1``, etc.). -**$validate** true ``true``/``false`` Whether to validate the email address. -**$priority** 3 1, 2, 3, 4, 5 Email Priority. ``1`` = highest. ``5`` = lowest. ``3`` = normal. -**$CRLF** \\r\\n ``\r\n``, ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). -**$newline** \\r\\n ``\r\n``, ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). -**$BCCBatchMode** false ``true``/``false`` Enable BCC Batch Mode. -**$BCCBatchSize** 200 Number of emails in each BCC batch. -**$DSN** false ``true``/``false`` Enable notify message from server. +**charset** UTF-8 Character set (``utf-8``, ``iso-8859-1``, etc.). +**validate** true ``true``/``false`` Whether to validate the email address. +**priority** 3 1, 2, 3, 4, 5 Email Priority. ``1`` = highest. ``5`` = lowest. ``3`` = normal. +**CRLF** \\r\\n ``\r\n``, ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). +**newline** \\r\\n ``\r\n``, ``\n`` or ``\r`` Newline character. (Use ``\r\n`` to comply with RFC 822). +**BCCBatchMode** false ``true``/``false`` Enable BCC Batch Mode. +**BCCBatchSize** 200 Number of emails in each BCC batch. +**DSN** false ``true``/``false`` Enable notify message from server. =================== =================== ============================ ======================================================================= Overriding Word Wrapping From 80c50301790142caa0992f2409b63fd8e4482699 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 25 Jul 2024 09:37:28 +0900 Subject: [PATCH 73/83] chore: update config for mcr.microsoft.com/mssql/server:2022-latest --- .github/workflows/reusable-phpunit-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-phpunit-test.yml b/.github/workflows/reusable-phpunit-test.yml index 4943d3f3ac2c..7889d3147b0f 100644 --- a/.github/workflows/reusable-phpunit-test.yml +++ b/.github/workflows/reusable-phpunit-test.yml @@ -95,13 +95,13 @@ jobs: mssql: image: mcr.microsoft.com/mssql/server:2022-latest env: - SA_PASSWORD: 1Secure*Password1 + MSSQL_SA_PASSWORD: 1Secure*Password1 ACCEPT_EULA: Y MSSQL_PID: Developer ports: - 1433:1433 options: >- - --health-cmd="/opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q 'SELECT @@VERSION'" + --health-cmd="/opt/mssql-tools18/bin/sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q 'SELECT @@VERSION'" --health-interval=10s --health-timeout=5s --health-retries=3 From ddb60ede57fc92a3acb5362b84426d0e673ade74 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 25 Jul 2024 09:42:56 +0900 Subject: [PATCH 74/83] chore: add -C option --- .github/workflows/reusable-phpunit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-phpunit-test.yml b/.github/workflows/reusable-phpunit-test.yml index 7889d3147b0f..84ade1d08862 100644 --- a/.github/workflows/reusable-phpunit-test.yml +++ b/.github/workflows/reusable-phpunit-test.yml @@ -101,7 +101,7 @@ jobs: ports: - 1433:1433 options: >- - --health-cmd="/opt/mssql-tools18/bin/sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q 'SELECT @@VERSION'" + --health-cmd="/opt/mssql-tools18/bin/sqlcmd -C -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q 'SELECT @@VERSION'" --health-interval=10s --health-timeout=5s --health-retries=3 From 3d738fc62ac2453e0b7afe6f5c2916634bb83233 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 25 Jul 2024 10:19:06 +0900 Subject: [PATCH 75/83] docs: update descriptions --- user_guide_src/source/database/query_builder.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index 171c354d1120..454fc56c6bbf 100644 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -247,6 +247,8 @@ Use the ``$db->newQuery()`` method to make a subquery the main table: Join ==== +.. _query-builder-join: + $builder->join() ---------------- @@ -270,7 +272,7 @@ RawSql .. versionadded:: 4.2.0 -Since v4.2.0, ``$builder->join()`` accepts a ``CodeIgniter\Database\RawSql`` instance, which expresses raw SQL strings. +Since v4.2.0, ``$builder->join()`` accepts a ``CodeIgniter\Database\RawSql`` instance as the JOIN ON condition, which expresses raw SQL strings. .. literalinclude:: query_builder/102.php @@ -1498,13 +1500,14 @@ Class Reference .. php:method:: join($table, $cond[, $type = ''[, $escape = null]]) :param string $table: Table name to join - :param string $cond: The JOIN ON condition + :param string|RawSql $cond: The JOIN ON condition :param string $type: The JOIN type :param bool $escape: Whether to escape values and identifiers :returns: ``BaseBuilder`` instance (method chaining) :rtype: ``BaseBuilder`` - Adds a ``JOIN`` clause to a query. + Adds a ``JOIN`` clause to a query. Since v4.2.0, ``RawSql`` can be used + as the JOIN ON condition. See also :ref:`query-builder-join`. .. php:method:: where($key[, $value = null[, $escape = null]]) From 80536358cf3a0c729f4480bd6fb34fd96d8a5fd0 Mon Sep 17 00:00:00 2001 From: christianberkman <39840601+christianberkman@users.noreply.github.com> Date: Thu, 25 Jul 2024 08:51:08 +0300 Subject: [PATCH 76/83] Apply suggestions from code review Co-authored-by: kenjis --- user_guide_src/source/libraries/files.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index f30e067f57c4..8d2e90c9df46 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -46,7 +46,7 @@ Returns the size of the uploaded file in bytes: .. literalinclude:: files/004.php -A RuntimeException will be thrown if the file does not exist or an error occurs. +A ``RuntimeException`` will be thrown if the file does not exist or an error occurs. getSizeByUnit() =============== @@ -56,7 +56,7 @@ the results in kilobytes or megabytes, respectively: .. literalinclude:: files/005.php -A RuntimeException will be thrown if the file does not exist or an error occurs. +A ``RuntimeException`` will be thrown if the file does not exist or an error occurs. getMimeType() ============= From eeb71f172300725516868b519cbd8091674a9e70 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 24 Jul 2024 19:18:13 +0800 Subject: [PATCH 77/83] refactor: fix `Throttler::check()` $tokens --- system/Throttle/Throttler.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/system/Throttle/Throttler.php b/system/Throttle/Throttler.php index 44d12005a80d..c023b5e4d052 100644 --- a/system/Throttle/Throttler.php +++ b/system/Throttle/Throttler.php @@ -102,8 +102,11 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): // Number of seconds to get one token $refresh = 1 / $rate; + /** @var float|int|null $tokens */ + $tokens = $this->cache->get($tokenName); + // Check to see if the bucket has even been created yet. - if (($tokens = $this->cache->get($tokenName)) === null) { + if ($tokens === null) { // If it hasn't been created, then we'll set it to the maximum // capacity - 1, and save it to the cache. $tokens = $capacity - $cost; @@ -124,7 +127,7 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): // should be refilled, then checked against capacity // to be sure the bucket didn't overflow. $tokens += $rate * $elapsed; - $tokens = $tokens > $capacity ? $capacity : $tokens; + $tokens = min($tokens, $capacity); // If $tokens >= 1, then we are safe to perform the action, but // we need to decrement the number of available tokens. From f804b55a94320d42767ea2e30ab71171999810ce Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 24 Jul 2024 18:48:06 +0800 Subject: [PATCH 78/83] Use `check` as shorthand for `fix --dry-run` --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 93f75cea3998..71983002c180 100644 --- a/composer.json +++ b/composer.json @@ -97,10 +97,10 @@ ], "cs": [ "Composer\\Config::disableProcessTimeout", - "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php", - "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php", - "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.tests.php", - "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run --diff" + "utils/vendor/bin/php-cs-fixer check --ansi --verbose --diff --config=.php-cs-fixer.user-guide.php", + "utils/vendor/bin/php-cs-fixer check --ansi --verbose --diff --config=.php-cs-fixer.no-header.php", + "utils/vendor/bin/php-cs-fixer check --ansi --verbose --diff --config=.php-cs-fixer.tests.php", + "utils/vendor/bin/php-cs-fixer check --ansi --verbose --diff" ], "cs-fix": [ "Composer\\Config::disableProcessTimeout", From 4edba3ae9e4929cdb53bdf3d3ad65c83a6ddd18c Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Wed, 24 Jul 2024 18:49:12 +0800 Subject: [PATCH 79/83] Call `composer cs` instead of individual calls --- .github/workflows/test-coding-standards.yml | 13 ++------ admin/pre-commit | 33 ++------------------- 2 files changed, 4 insertions(+), 42 deletions(-) diff --git a/.github/workflows/test-coding-standards.yml b/.github/workflows/test-coding-standards.yml index 2146b27b9420..f30475a76dba 100644 --- a/.github/workflows/test-coding-standards.yml +++ b/.github/workflows/test-coding-standards.yml @@ -57,14 +57,5 @@ jobs: - name: Install dependencies run: composer update --ansi --no-interaction - - name: Run lint on `app/`, `admin/`, `public/` - run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.no-header.php --using-cache=no --diff - - - name: Run lint on `system/`, `utils/`, and root PHP files - run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --using-cache=no --diff - - - name: Run lint on `tests` - run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.tests.php --using-cache=no --diff - - - name: Run lint on `user_guide_src/source/` - run: utils/vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.php-cs-fixer.user-guide.php --using-cache=no --diff + - name: Run lint + run: composer cs diff --git a/admin/pre-commit b/admin/pre-commit index 107adc35a3f7..19bec4f4726b 100644 --- a/admin/pre-commit +++ b/admin/pre-commit @@ -24,39 +24,10 @@ if [ "$FILES" != "" ]; then echo "Running PHP CS Fixer..." # Run on whole codebase to skip on unnecessary filtering - # Run first on app, admin, public - if [ -d /proc/cygdrive ]; then - ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php - else - php ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php - fi - - if [ $? != 0 ]; then - echo "Files in app, admin, or public are not following the coding standards. Please fix them before commit." - exit 1 - fi - - # Next, run on system, tests, utils, and root PHP files - if [ -d /proc/cygdrive ]; then - ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff - else - php ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff - fi - - if [ $? != 0 ]; then - echo "Files in system, tests, utils, or root are not following the coding standards. Please fix them before commit." - exit 1 - fi - - # Next, run on user_guide_src/source PHP files - if [ -d /proc/cygdrive ]; then - ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php - else - php ./utils/vendor/bin/php-cs-fixer fix --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php - fi + composer cs if [ $? != 0 ]; then - echo "Files in user_guide_src/source are not following the coding standards. Please fix them before commit." + echo "There are PHP files which are not following the coding standards. Please fix them before commit." exit 1 fi fi From cbd502488bad86bd1a1188edb06ff51a319dcb4d Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Thu, 25 Jul 2024 23:29:52 +0800 Subject: [PATCH 80/83] chore: add composer scripts for phpstan --- .github/workflows/test-phpstan.yml | 2 +- composer.json | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-phpstan.yml b/.github/workflows/test-phpstan.yml index 360b403ac923..aca331f30481 100644 --- a/.github/workflows/test-phpstan.yml +++ b/.github/workflows/test-phpstan.yml @@ -85,4 +85,4 @@ jobs: run: composer update --ansi --no-interaction - name: Run static analysis - run: vendor/bin/phpstan analyse + run: composer phpstan:check diff --git a/composer.json b/composer.json index 71983002c180..c129969a49f9 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ ], "analyze": [ "Composer\\Config::disableProcessTimeout", - "bash -c \"XDEBUG_MODE=off vendor/bin/phpstan analyse\"", + "@phpstan:check", "vendor/bin/rector process --dry-run" ], "cs": [ @@ -110,6 +110,8 @@ "utils/vendor/bin/php-cs-fixer fix --ansi --verbose --diff" ], "metrics": "utils/vendor/bin/phpmetrics --config=phpmetrics.json", + "phpstan:baseline": "vendor/bin/phpstan analyse --ansi --generate-baseline=phpstan-baseline.php", + "phpstan:check": "vendor/bin/phpstan analyse --verbose --ansi", "sa": "@analyze", "style": "@cs-fix", "test": "phpunit" @@ -119,6 +121,8 @@ "cs": "Check the coding style", "cs-fix": "Fix the coding style", "metrics": "Run PhpMetrics", + "phpstan:baseline": "Run PHPStan then dump all errors to baseline", + "phpstan:check": "Run PHPStan with support for identifiers", "test": "Run unit tests" } } From 4a4c82367dfde3eae89d1c594870e7394a611d67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:37:40 +0000 Subject: [PATCH 81/83] chore(deps-dev): update rector/rector requirement from 1.2.1 to 1.2.2 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/1.2.1...1.2.2) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 71983002c180..3e2e5225d014 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "phpunit/phpcov": "^9.0.2", "phpunit/phpunit": "^10.5.16", "predis/predis": "^1.1 || ^2.0", - "rector/rector": "1.2.1" + "rector/rector": "1.2.2" }, "replace": { "codeigniter4/framework": "self.version" From 868961d8fa43bfa263eadd0621ee6ee4ae3065fc Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Jul 2024 10:40:53 +0900 Subject: [PATCH 82/83] docs: add note for Registrars --- user_guide_src/source/general/configuration.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/user_guide_src/source/general/configuration.rst b/user_guide_src/source/general/configuration.rst index bfb4b0f1b4ef..cc24b3f3723c 100644 --- a/user_guide_src/source/general/configuration.rst +++ b/user_guide_src/source/general/configuration.rst @@ -314,6 +314,10 @@ Registrars provide a means of altering a configuration at runtime across namespa Registrars work if :ref:`auto-discovery` is enabled in :doc:`Modules `. It alters configuration properties when the Config object is instantiated. +.. note:: This feature is implemented in the ``CodeIgniter\Config\BaseConfig`` + class. So it will not work with a few files in the **app/Config** folder + that do not extends the class. + There are two ways to implement a Registrar: **implicit** and **explicit**. .. note:: Values from **.env** always take priority over Registrars. From 94d0aaed0eacaed98f2a3dc3253a3885a392b260 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 27 Jul 2024 17:02:01 +0900 Subject: [PATCH 83/83] Prep for 4.5.4 release --- CHANGELOG.md | 23 ++++++++++++++++ phpdoc.dist.xml | 2 +- system/CodeIgniter.php | 2 +- user_guide_src/source/changelogs/v4.5.4.rst | 18 +------------ user_guide_src/source/conf.py | 2 +- .../source/installation/upgrade_454.rst | 26 ++----------------- 6 files changed, 29 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9351b205e637..1d2778139204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## [v4.5.4](https://github.com/codeigniter4/CodeIgniter4/tree/v4.5.3) (2024-07-27) +[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.5.3...v4.5.4) + +### Fixed Bugs + +* fix: [OCI8] Easy Connect string validation by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9006 +* fix: [QueryBuilder] select() with RawSql may cause TypeError by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9009 +* fix: [QueryBuilder] `select()` does not escape after `NULL` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9010 +* fix: allow string as parameter to CURLRequest version by @tangix in https://github.com/codeigniter4/CodeIgniter4/pull/9021 +* fix: `spark phpini:check` may cause TypeError by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9026 +* fix: Prevent invalid session handlers by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/9036 +* fix: DebugBar CSS for daisyUI by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9046 +* docs: `referrer` is undefined by @totoprayogo1916 in https://github.com/codeigniter4/CodeIgniter4/pull/9059 +* fix: filters passed to the ``$routes->group()`` are not merged into the filters passed to the inner routes by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9064 + +### Refactoring + +* refactor: use first class callable on function call by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/9004 +* refactor: enable AddClosureVoidReturnTypeWhereNoReturnRector to add void return on closure by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/9008 +* refactor: enable AddFunctionVoidReturnTypeWhereNoReturnRector to add void to functions by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/9014 +* refactor: Enable phpunit 10 attribute Rector rules by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/9015 +* refactor: fix `Throttler::check()` $tokens by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/9067 + ## [v4.5.3](https://github.com/codeigniter4/CodeIgniter4/tree/v4.5.3) (2024-06-25) [Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.5.2...v4.5.3) diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml index 5e5a31cb483a..e67b1b29ed55 100644 --- a/phpdoc.dist.xml +++ b/phpdoc.dist.xml @@ -10,7 +10,7 @@ api/build/ api/cache/ - + system diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 0bb101cc7990..bcfb7bd67976 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -56,7 +56,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - public const CI_VERSION = '4.5.3'; + public const CI_VERSION = '4.5.4'; /** * App startup time. diff --git a/user_guide_src/source/changelogs/v4.5.4.rst b/user_guide_src/source/changelogs/v4.5.4.rst index d09413124ee0..257e42bbfb02 100644 --- a/user_guide_src/source/changelogs/v4.5.4.rst +++ b/user_guide_src/source/changelogs/v4.5.4.rst @@ -2,7 +2,7 @@ Version 4.5.4 ############# -Release Date: Unreleased +Release Date: July 27, 2024 **4.5.4 release of CodeIgniter4** @@ -10,22 +10,6 @@ Release Date: Unreleased :local: :depth: 3 -******** -BREAKING -******** - -*************** -Message Changes -*************** - -******* -Changes -******* - -************ -Deprecations -************ - ********** Bugs Fixed ********** diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py index 442a6f49e0d6..431dc6d57bd9 100644 --- a/user_guide_src/source/conf.py +++ b/user_guide_src/source/conf.py @@ -26,7 +26,7 @@ version = '4.5' # The full version, including alpha/beta/rc tags. -release = '4.5.3' +release = '4.5.4' # -- General configuration --------------------------------------------------- diff --git a/user_guide_src/source/installation/upgrade_454.rst b/user_guide_src/source/installation/upgrade_454.rst index 393324c3b40c..2e460eed3a16 100644 --- a/user_guide_src/source/installation/upgrade_454.rst +++ b/user_guide_src/source/installation/upgrade_454.rst @@ -12,18 +12,6 @@ Please refer to the upgrade instructions corresponding to your installation meth :local: :depth: 2 -********************** -Mandatory File Changes -********************** - -**************** -Breaking Changes -**************** - -********************* -Breaking Enhancements -********************* - ************* Project Files ************* @@ -35,21 +23,11 @@ these files being outside of the **system** scope they will not be changed witho with merging changes to the project space: `Explore on Packagist `_. -Content Changes -=============== - -The following files received significant changes (including deprecations or visual adjustments) -and it is recommended that you merge the updated versions with your application: - -Config ------- - -- @TODO - All Changes =========== This is a list of all files in the **project space** that received changes; many will be simple comments or formatting that have no effect on the runtime: -- @TODO +- app/Config/Events.php +- composer.json