Skip to content

Commit f8e4ec5

Browse files
authored
Merge pull request #7073 from codeigniter4/develop
4.3.0 Ready code
2 parents 558db23 + a7cd7a3 commit f8e4ec5

File tree

627 files changed

+20893
-6755
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

627 files changed

+20893
-6755
lines changed

.github/workflows/test-phpcpd.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,12 @@ jobs:
4646
extensions: dom, mbstring
4747

4848
- name: Detect code duplication
49-
run: phpcpd --exclude system/Test --exclude system/ThirdParty --exclude system/Database/SQLSRV/Builder.php --exclude system/Database/SQLSRV/Forge.php -- app/ public/ system/
49+
run: phpcpd
50+
--exclude system/Test
51+
--exclude system/ThirdParty
52+
--exclude system/Database/SQLSRV/Builder.php
53+
--exclude system/Database/SQLSRV/Forge.php
54+
--exclude system/Database/MySQLi/Builder.php
55+
--exclude system/Database/OCI8/Builder.php
56+
--exclude system/Database/Postgre/Builder.php
57+
-- app/ public/ system/

.github/workflows/test-psalm.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Psalm
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- develop
7+
- '4.*'
8+
paths:
9+
- '**.php'
10+
- 'composer.*'
11+
- 'psalm*'
12+
- '.github/workflows/test-psalm.yml'
13+
push:
14+
branches:
15+
- develop
16+
- '4.*'
17+
paths:
18+
- '**.php'
19+
- 'composer.*'
20+
- 'psalm*'
21+
- '.github/workflows/test-psalm.yml'
22+
23+
jobs:
24+
build:
25+
name: Psalm Analysis
26+
runs-on: ubuntu-latest
27+
if: "!contains(github.event.head_commit.message, '[ci skip]')"
28+
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@v3
32+
33+
- name: Setup PHP
34+
uses: shivammathur/setup-php@v2
35+
with:
36+
php-version: '8.1'
37+
tools: phpstan, phpunit
38+
extensions: intl, json, mbstring, xml, oci8
39+
coverage: none
40+
env:
41+
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42+
43+
- name: Get composer cache directory
44+
run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV
45+
46+
- name: Cache composer dependencies
47+
uses: actions/cache@v3
48+
with:
49+
path: ${{ env.COMPOSER_CACHE_FILES_DIR }}
50+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }}
51+
restore-keys: ${{ runner.os }}-composer-
52+
53+
- name: Create Psalm cache directory
54+
run: mkdir -p build/psalm
55+
56+
- name: Cache Psalm results
57+
uses: actions/cache@v3
58+
with:
59+
path: build/psalm
60+
key: ${{ runner.os }}-psalm-${{ github.sha }}
61+
restore-keys: ${{ runner.os }}-psalm-
62+
63+
- name: Install dependencies
64+
run: |
65+
if [ -f composer.lock ]; then
66+
composer install --no-progress
67+
else
68+
composer update --no-progress
69+
fi
70+
71+
- name: Run Psalm analysis
72+
run: vendor/bin/psalm

CHANGELOG.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,115 @@
11
# Changelog
22

3+
## [v4.3.0](https://github.com/codeigniter4/CodeIgniter4/tree/v4.3.0) (2023-01-10)
4+
[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.2.12...v4.3.0)
5+
6+
### Breaking Changes
7+
8+
* fix: throws DatabaseException in DB connections by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6163
9+
* config: DB Error always throws Exception CI_DBUG by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6183
10+
* Config Property Types by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6214
11+
* refactor: loading app/Config/routes.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6293
12+
* fix: exceptionHandler may return invalid HTTP status code by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6228
13+
* feat: add Form helpers for Validation Errors by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6384
14+
* fix: ValidationInterface by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6253
15+
* [Reverted] Make Unique Index Name Unique by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6516
16+
* fix: types in database classes by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6527
17+
* fix: ResponseInterface (1) by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6556
18+
* Improve BaseConnection::getForeignKeyData() and Forge::addForeignKey() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6468
19+
* Refactor BaseBuilder *Batch() Methods by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6536
20+
* refactor: remove `type="text/javascript"` in <script> tag by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6606
21+
* fix: ResponseInterface (2) by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6569
22+
* Add ability to set index names by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6552
23+
* fix: MessageInterface inheritance by @MGatner in https://github.com/codeigniter4/CodeIgniter4/pull/6695
24+
* fix: add missing getProtocolVersion() in MessageInterface by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6702
25+
* Add Forge::processIndexes() to create indexes on existing table by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6676
26+
* fix: add missing ResultInterface::getNumRows() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6778
27+
* feat: add OutgoingRequestInterface by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6698
28+
* fix: make Time immutable by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6771
29+
* feat: disallow `Model::update()` without WHERE clause by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6883
30+
* feat: do not throw exceptions during transactions by default by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6917
31+
* fix: don't change the variable type and filter all values in JSON request by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/6954
32+
33+
### Fixed Bugs
34+
35+
* fix: SecurityException's HTTP status code by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6408
36+
* Fix UpsertTest::testUpsertWithMultipleSet by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6692
37+
* fix: support for assigning extra data for the view() method in controlled cells by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/6681
38+
* Fix testMode() with upsert() and getCompiledUpsert() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6697
39+
* Fix BaseBuilder setAlias() and RawSql use with key value pairs by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6741
40+
* fix: BasePreparedQuery class to return boolean values for write-type queries by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/6750
41+
* fix: Time::now() does not respect timezone when using setTestNow() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6752
42+
* fix: remove CI_DEBUG check in Model by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6863
43+
* fix: BaseBuilder::getOperator() doesn't recognize LIKE operator in array expression by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6986
44+
* fix: Honeypot field appears when CSP is enabled by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7029
45+
46+
### Enhancements
47+
48+
* Feature: Adding StreamFilterTrait by @iRedds in https://github.com/codeigniter4/CodeIgniter4/pull/6112
49+
* feat: add routes useSupportedLocalesOnly property by @pjsde in https://github.com/codeigniter4/CodeIgniter4/pull/6073
50+
* Feat add events for insertBatch()/updateBatch() by @pjsde in https://github.com/codeigniter4/CodeIgniter4/pull/6125
51+
* feat: improve namespaces command by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6142
52+
* feat: add method to insert empty data in Model by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6109
53+
* feat: Autoloader::sanitizeFilename() throws Exception by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6193
54+
* Language: Make production error message translatable (replaces #6197) by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/6235
55+
* feat: add methods to modify files in Publisher by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6133
56+
* SQLite3 Connection getIndexData() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6221
57+
* feat: `spark filter:check` command by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6283
58+
* feat: Encryption CI3 compatibility by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6277
59+
* feat: `spark routes` shows route name by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6271
60+
* error_404.php translation and design by @sba in https://github.com/codeigniter4/CodeIgniter4/pull/6288
61+
* feat: make `CLI::input()` testable by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6335
62+
* Feature for Timer to measure callable performance by @rumpfc in https://github.com/codeigniter4/CodeIgniter4/pull/6321
63+
* feat: add IntBoolCast for Entity by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6348
64+
* Add new method `promptByMultipleKeys()` in CLI class by @rivalarya in https://github.com/codeigniter4/CodeIgniter4/pull/6302
65+
* Allow calling help info using `spark --help` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/6383
66+
* feat: autoload helpers by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6397
67+
* Add RawSql to BaseConnection->escape() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6332
68+
* feat: add locale param to `route_to()` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6448
69+
* Postgre & SQLSRV - Should Never Have A Field Length For TEXT by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6405
70+
* [4.3] Fix tests. Changed StreamFilterTrait and CITestStreamFilter. by @iRedds in https://github.com/codeigniter4/CodeIgniter4/pull/6450
71+
* Create Forge::dropPrimaryKey() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6488
72+
* feat: add manual config for Composer package auto-discovery by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6503
73+
* Added view() method to route collections by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6568
74+
* When/WhenNot methods for db in a trait by @lonnieezell in https://github.com/codeigniter4/CodeIgniter4/pull/6574
75+
* Allow Cells to be auto-located within */Cells directories by @lonnieezell in https://github.com/codeigniter4/CodeIgniter4/pull/6601
76+
* Decamelize function by @lonnieezell in https://github.com/codeigniter4/CodeIgniter4/pull/6615
77+
* feat: Controlled Cells by @lonnieezell in https://github.com/codeigniter4/CodeIgniter4/pull/6620
78+
* Allow HTTP/3 to work and not be blocked. by @lonnieezell in https://github.com/codeigniter4/CodeIgniter4/pull/6595
79+
* feat: add method to disable controller filters by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6652
80+
* feat: implementation option http2 in `CURLRequest` by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/6679
81+
* Add BaseBuilder::upsert() and BaseBuilder::upsertBatch() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6600
82+
* Deallocate prepared statements by @fpoy in https://github.com/codeigniter4/CodeIgniter4/pull/6665
83+
* feat: Check logs against parts of the message only by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/6704
84+
* feat: Opt-in logging of deprecations by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/6705
85+
* feat: void element tags in helpers are selectable between `>` and `/>` by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/6789
86+
* feat: add $allowedHostnames for multiple domain support by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6785
87+
* new make:cell command by @lonnieezell in https://github.com/codeigniter4/CodeIgniter4/pull/6864
88+
* Add BaseBuilder::deleteBatch() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6734
89+
* Update Kint to 5.0.1 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6893
90+
* Add `is_windows()` global function by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/6884
91+
* fix: HTML output by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6899
92+
* feat: add SQLite3 Config busyTimeout by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6939
93+
* insertBatch updateBatch upsertBatch deleteBatch from query by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6689
94+
* feat: add IncomingRequest::getRawInputVar() method by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/6943
95+
* feat: add closure validation rule by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6951
96+
* refactor: add Config\Session by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6989
97+
* feat: add IncomingRequest::is() method by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6995
98+
* feat: `spark routes` option to sort by handler by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7015
99+
100+
### Refactoring
101+
102+
* Extracting the call handler for Spark commands from kernel. by @iRedds in https://github.com/codeigniter4/CodeIgniter4/pull/6110
103+
* chore: move Kint to `require-dev` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6449
104+
* Improve `BaseBuilder::updateBatch()` SQL by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6373
105+
* refactor: to fix psalm errors by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6535
106+
* Add template types to `Connection` by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/6709
107+
* refactor: around URI by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6784
108+
* Add template types to Result by @paulbalandan in https://github.com/codeigniter4/CodeIgniter4/pull/6749
109+
* refactor: make now() testable by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6753
110+
* refactor: remove Workaround for Faker deprecation errors in PHP 8.2 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6987
111+
* refactor: to fix psalm error by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6999
112+
3113
## [v4.2.12](https://github.com/codeigniter4/CodeIgniter4/tree/v4.2.12) (2023-01-09)
4114
[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.2.11...v4.2.12)
5115

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# CodeIgniter 4 Development
22

3-
[![Build Status](https://github.com/codeigniter4/CodeIgniter4/workflows/PHPUnit/badge.svg)](https://github.com/codeigniter4/CodeIgniter4/actions?query=workflow%3A%22PHPUnit%22)
3+
[![PHPUnit](https://github.com/codeigniter4/CodeIgniter4/workflows/PHPUnit/badge.svg)](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/test-phpunit.yml)
4+
[![PHPStan](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/test-phpstan.yml/badge.svg)](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/test-phpstan.yml)
5+
[![Psalm](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/test-psalm.yml/badge.svg)](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/test-psalm.yml)
46
[![Coverage Status](https://coveralls.io/repos/github/codeigniter4/CodeIgniter4/badge.svg?branch=develop)](https://coveralls.io/github/codeigniter4/CodeIgniter4?branch=develop)
57
[![Downloads](https://poser.pugx.org/codeigniter4/framework/downloads)](https://packagist.org/packages/codeigniter4/framework)
68
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/codeigniter4/CodeIgniter4)](https://packagist.org/packages/codeigniter4/framework)

admin/framework/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
"ext-intl": "*",
1010
"ext-json": "*",
1111
"ext-mbstring": "*",
12-
"kint-php/kint": "^4.2",
1312
"laminas/laminas-escaper": "^2.9",
1413
"psr/log": "^1.1"
1514
},
1615
"require-dev": {
16+
"kint-php/kint": "^5.0.1",
1717
"codeigniter/coding-standard": "^1.5",
1818
"fakerphp/faker": "^1.9",
1919
"friendsofphp/php-cs-fixer": "3.13.0",

admin/starter/app/Config/Paths.php

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@ class Paths
2222
*
2323
* This must contain the name of your "system" folder. Include
2424
* the path if the folder is not in the same directory as this file.
25-
*
26-
* @var string
2725
*/
28-
public $systemDirectory = __DIR__ . '/../../vendor/codeigniter4/framework/system';
26+
public string $systemDirectory = __DIR__ . '/../../vendor/codeigniter4/framework/system';
2927

3028
/**
3129
* ---------------------------------------------------------------
@@ -38,10 +36,8 @@ class Paths
3836
* you do, use a full server path.
3937
*
4038
* @see http://codeigniter.com/user_guide/general/managing_apps.html
41-
*
42-
* @var string
4339
*/
44-
public $appDirectory = __DIR__ . '/..';
40+
public string $appDirectory = __DIR__ . '/..';
4541

4642
/**
4743
* ---------------------------------------------------------------
@@ -53,21 +49,17 @@ class Paths
5349
* need write permission to a single place that can be tucked away
5450
* for maximum security, keeping it out of the app and/or
5551
* system directories.
56-
*
57-
* @var string
5852
*/
59-
public $writableDirectory = __DIR__ . '/../../writable';
53+
public string $writableDirectory = __DIR__ . '/../../writable';
6054

6155
/**
6256
* ---------------------------------------------------------------
6357
* TESTS DIRECTORY NAME
6458
* ---------------------------------------------------------------
6559
*
6660
* This variable must contain the name of your "tests" directory.
67-
*
68-
* @var string
6961
*/
70-
public $testsDirectory = __DIR__ . '/../../tests';
62+
public string $testsDirectory = __DIR__ . '/../../tests';
7163

7264
/**
7365
* ---------------------------------------------------------------
@@ -78,8 +70,6 @@ class Paths
7870
* contains the view files used by your application. By
7971
* default this is in `app/Views`. This value
8072
* is used when no value is provided to `Services::renderer()`.
81-
*
82-
* @var string
8373
*/
84-
public $viewDirectory = __DIR__ . '/../Views';
74+
public string $viewDirectory = __DIR__ . '/../Views';
8575
}

0 commit comments

Comments
 (0)