Skip to content

Commit 9b2cd73

Browse files
committed
Release v4.5.1
1 parent 365a46c commit 9b2cd73

File tree

25 files changed

+234
-99
lines changed

25 files changed

+234
-99
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,3 @@ nb-configuration.xml
124124

125125
/results/
126126
/phpunit*.xml
127-
/.phpunit.*.cache
128-

phpunit.xml.dist

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,63 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="system/Test/bootstrap.php" backupGlobals="false" colors="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache">
3-
<coverage includeUncoveredFiles="true">
4-
<report>
5-
<clover outputFile="build/logs/clover.xml"/>
6-
<html outputDirectory="build/logs/html"/>
7-
<php outputFile="build/logs/coverage.serialized"/>
8-
<text outputFile="php://stdout" showUncoveredFiles="false"/>
9-
</report>
10-
</coverage>
11-
<testsuites>
12-
<testsuite name="App">
13-
<directory>./tests</directory>
14-
</testsuite>
15-
</testsuites>
16-
<logging>
17-
<testdoxHtml outputFile="build/logs/testdox.html"/>
18-
<testdoxText outputFile="build/logs/testdox.txt"/>
19-
<junit outputFile="build/logs/logfile.xml"/>
20-
</logging>
21-
<php>
22-
<server name="app.baseURL" value="http://example.com/"/>
23-
<!-- Directory containing phpunit.xml -->
24-
<const name="HOMEPATH" value="./"/>
25-
<!-- Directory containing the Paths config file -->
26-
<const name="CONFIGPATH" value="./app/Config/"/>
27-
<!-- Directory containing the front controller (index.php) -->
28-
<const name="PUBLICPATH" value="./public/"/>
29-
<!-- Database configuration -->
30-
<!-- Uncomment to provide your own database for testing
31-
<env name="database.tests.hostname" value="localhost"/>
32-
<env name="database.tests.database" value="tests"/>
33-
<env name="database.tests.username" value="tests_user"/>
34-
<env name="database.tests.password" value=""/>
35-
<env name="database.tests.DBDriver" value="MySQLi"/>
36-
<env name="database.tests.DBPrefix" value="tests_"/>
37-
-->
38-
</php>
39-
<source>
40-
<include>
41-
<directory suffix=".php">./app</directory>
42-
</include>
43-
<exclude>
44-
<directory suffix=".php">./app/Views</directory>
45-
<file>./app/Config/Routes.php</file>
46-
</exclude>
47-
</source>
2+
<phpunit
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
5+
bootstrap="system/Test/bootstrap.php"
6+
backupGlobals="false"
7+
beStrictAboutOutputDuringTests="true"
8+
colors="true"
9+
columns="max"
10+
failOnRisky="true"
11+
failOnWarning="true"
12+
cacheDirectory="build/.phpunit.cache">
13+
<coverage
14+
includeUncoveredFiles="true"
15+
pathCoverage="false"
16+
ignoreDeprecatedCodeUnits="true"
17+
disableCodeCoverageIgnore="true">
18+
<report>
19+
<clover outputFile="build/logs/clover.xml"/>
20+
<html outputDirectory="build/logs/html"/>
21+
<php outputFile="build/logs/coverage.serialized"/>
22+
<text outputFile="php://stdout" showUncoveredFiles="false"/>
23+
</report>
24+
</coverage>
25+
<testsuites>
26+
<testsuite name="App">
27+
<directory>./tests</directory>
28+
</testsuite>
29+
</testsuites>
30+
<logging>
31+
<testdoxHtml outputFile="build/logs/testdox.html"/>
32+
<testdoxText outputFile="build/logs/testdox.txt"/>
33+
<junit outputFile="build/logs/logfile.xml"/>
34+
</logging>
35+
<source>
36+
<include>
37+
<directory suffix=".php">./app</directory>
38+
</include>
39+
<exclude>
40+
<directory suffix=".php">./app/Views</directory>
41+
<file>./app/Config/Routes.php</file>
42+
</exclude>
43+
</source>
44+
<php>
45+
<server name="app.baseURL" value="http://example.com/"/>
46+
<server name="CODEIGNITER_SCREAM_DEPRECATIONS" value="0"/>
47+
<!-- Directory containing phpunit.xml -->
48+
<const name="HOMEPATH" value="./"/>
49+
<!-- Directory containing the Paths config file -->
50+
<const name="CONFIGPATH" value="./app/Config/"/>
51+
<!-- Directory containing the front controller (index.php) -->
52+
<const name="PUBLICPATH" value="./public/"/>
53+
<!-- Database configuration -->
54+
<!-- Uncomment to provide your own database for testing
55+
<env name="database.tests.hostname" value="localhost"/>
56+
<env name="database.tests.database" value="tests"/>
57+
<env name="database.tests.username" value="tests_user"/>
58+
<env name="database.tests.password" value=""/>
59+
<env name="database.tests.DBDriver" value="MySQLi"/>
60+
<env name="database.tests.DBPrefix" value="tests_"/>
61+
-->
62+
</php>
4863
</phpunit>

system/Autoloader/FileLocator.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ class FileLocator implements FileLocatorInterface
2828
*/
2929
protected $autoloader;
3030

31+
/**
32+
* List of classnames that did not exist.
33+
*
34+
* @var list<class-string>
35+
*/
36+
private array $invalidClassnames = [];
37+
3138
public function __construct(Autoloader $autoloader)
3239
{
3340
$this->autoloader = $autoloader;
@@ -288,14 +295,20 @@ public function findQualifiedNameFromPath(string $path)
288295
),
289296
'\\'
290297
);
291-
292298
// Remove the file extension (.php)
293299
$className = mb_substr($className, 0, -4);
294300

301+
if (in_array($className, $this->invalidClassnames, true)) {
302+
continue;
303+
}
304+
295305
// Check if this exists
296306
if (class_exists($className)) {
297307
return $className;
298308
}
309+
310+
// If the class does not exist, it is an invalid classname.
311+
$this->invalidClassnames[] = $className;
299312
}
300313
}
301314

system/BaseModel.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,9 @@ public function insertBatch(?array $set = null, ?bool $escape = null, int $batch
926926
$row = (array) $row;
927927
}
928928

929+
// Convert any Time instances to appropriate $dateFormat
930+
$row = $this->timeToString($row);
931+
929932
// Validate every row.
930933
if (! $this->skipValidation && ! $this->validate($row)) {
931934
// Restore $cleanValidationRules
@@ -1845,8 +1848,6 @@ protected function transformDataToArray($row, string $type): array
18451848
$row = $this->converter->toDataSource($row);
18461849
} elseif ($row instanceof Entity) {
18471850
$row = $this->converter->extract($row, $onlyChanged);
1848-
// Convert any Time instances to appropriate $dateFormat
1849-
$row = $this->timeToString($row);
18501851
} elseif (is_object($row)) {
18511852
$row = $this->converter->extract($row, $onlyChanged);
18521853
}
@@ -1870,7 +1871,8 @@ protected function transformDataToArray($row, string $type): array
18701871
throw DataException::forEmptyDataset($type);
18711872
}
18721873

1873-
return $row;
1874+
// Convert any Time instances to appropriate $dateFormat
1875+
return $this->timeToString($row);
18741876
}
18751877

18761878
/**

system/CLI/BaseCommand.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ abstract public function run(array $params);
108108
/**
109109
* Can be used by a command to run other commands.
110110
*
111+
* @param array<int|string, string|null> $params
112+
*
111113
* @return int|void
112114
*
113115
* @throws ReflectionException
@@ -140,7 +142,7 @@ public function showHelp()
140142
{
141143
CLI::write(lang('CLI.helpUsage'), 'yellow');
142144

143-
if (! empty($this->usage)) {
145+
if (isset($this->usage)) {
144146
$usage = $this->usage;
145147
} else {
146148
$usage = $this->name;
@@ -152,7 +154,7 @@ public function showHelp()
152154

153155
CLI::write($this->setPad($usage, 0, 0, 2));
154156

155-
if (! empty($this->description)) {
157+
if (isset($this->description)) {
156158
CLI::newLine();
157159
CLI::write(lang('CLI.helpDescription'), 'yellow');
158160
CLI::write($this->setPad($this->description, 0, 0, 2));
@@ -194,6 +196,8 @@ public function setPad(string $item, int $max, int $extra = 2, int $indent = 0):
194196
/**
195197
* Get pad for $key => $value array output
196198
*
199+
* @param array<string, string> $array
200+
*
197201
* @deprecated Use setPad() instead.
198202
*
199203
* @codeCoverageIgnore
@@ -212,7 +216,7 @@ public function getPad(array $array, int $pad): int
212216
/**
213217
* Makes it simple to access our protected properties.
214218
*
215-
* @return array|Commands|LoggerInterface|string|null
219+
* @return array<string, string>|Commands|LoggerInterface|string|null
216220
*/
217221
public function __get(string $key)
218222
{

system/CodeIgniter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class CodeIgniter
5656
/**
5757
* The current version of CodeIgniter Framework
5858
*/
59-
public const CI_VERSION = '4.5.0';
59+
public const CI_VERSION = '4.5.1';
6060

6161
/**
6262
* App startup time.

system/Commands/Housekeeping/ClearDebugbar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function run(array $params)
5757
{
5858
helper('filesystem');
5959

60-
if (! delete_files(WRITEPATH . 'debugbar')) {
60+
if (! delete_files(WRITEPATH . 'debugbar', false, true)) {
6161
// @codeCoverageIgnoreStart
6262
CLI::error('Error deleting the debugbar JSON files.');
6363
CLI::newLine();

system/Config/BaseService.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,15 @@ protected static function buildServicesCache(): void
389389
$locator = static::locator();
390390
$files = $locator->search('Config/Services');
391391

392+
$systemPath = static::autoloader()->getNamespace('CodeIgniter')[0];
393+
392394
// Get instances of all service classes and cache them locally.
393395
foreach ($files as $file) {
396+
// Does not search `CodeIgniter` namespace to prevent from loading twice.
397+
if (str_starts_with($file, $systemPath)) {
398+
continue;
399+
}
400+
394401
$classname = $locator->findQualifiedNameFromPath($file);
395402

396403
if ($classname === false) {

system/Config/Factories.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ public static function get(string $component, string $alias): ?object
180180
if (isset(self::$aliases[$component][$alias])) {
181181
$class = self::$aliases[$component][$alias];
182182

183-
return self::$instances[$component][$class];
183+
if (isset(self::$instances[$component][$class])) {
184+
return self::$instances[$component][$class];
185+
}
184186
}
185187

186188
return self::__callStatic($component, [$alias]);

system/Database/BaseConnection.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use CodeIgniter\Database\Exceptions\DatabaseException;
1818
use CodeIgniter\Events\Events;
1919
use stdClass;
20+
use Stringable;
2021
use Throwable;
2122

2223
/**
@@ -1309,12 +1310,15 @@ public function escape($str)
13091310
return array_map($this->escape(...), $str);
13101311
}
13111312

1312-
/** @psalm-suppress NoValue I don't know why ERROR. */
1313-
if (is_string($str) || (is_object($str) && method_exists($str, '__toString'))) {
1313+
if ($str instanceof Stringable) {
13141314
if ($str instanceof RawSql) {
13151315
return $str->__toString();
13161316
}
13171317

1318+
$str = (string) $str;
1319+
}
1320+
1321+
if (is_string($str)) {
13181322
return "'" . $this->escapeString($str) . "'";
13191323
}
13201324

@@ -1328,8 +1332,8 @@ public function escape($str)
13281332
/**
13291333
* Escape String
13301334
*
1331-
* @param list<string>|string $str Input string
1332-
* @param bool $like Whether or not the string will be used in a LIKE condition
1335+
* @param list<string|Stringable>|string|Stringable $str Input string
1336+
* @param bool $like Whether the string will be used in a LIKE condition
13331337
*
13341338
* @return list<string>|string
13351339
*/
@@ -1343,6 +1347,14 @@ public function escapeString($str, bool $like = false)
13431347
return $str;
13441348
}
13451349

1350+
if ($str instanceof Stringable) {
1351+
if ($str instanceof RawSql) {
1352+
return $str->__toString();
1353+
}
1354+
1355+
$str = (string) $str;
1356+
}
1357+
13461358
$str = $this->_escapeString($str);
13471359

13481360
// escape LIKE condition wildcards
@@ -1371,7 +1383,7 @@ public function escapeString($str, bool $like = false)
13711383
* Calls the individual driver for platform
13721384
* specific escaping for LIKE conditions
13731385
*
1374-
* @param list<string>|string $str
1386+
* @param list<string|Stringable>|string|Stringable $str
13751387
*
13761388
* @return list<string>|string
13771389
*/

system/Database/Postgre/Connection.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use PgSql\Connection as PgSqlConnection;
2121
use PgSql\Result as PgSqlResult;
2222
use stdClass;
23+
use Stringable;
2324

2425
/**
2526
* Connection for Postgre
@@ -233,20 +234,22 @@ public function escape($str)
233234
$this->initialize();
234235
}
235236

236-
/** @psalm-suppress NoValue I don't know why ERROR. */
237-
if (is_string($str) || (is_object($str) && method_exists($str, '__toString'))) {
237+
if ($str instanceof Stringable) {
238238
if ($str instanceof RawSql) {
239239
return $str->__toString();
240240
}
241241

242+
$str = (string) $str;
243+
}
244+
245+
if (is_string($str)) {
242246
return pg_escape_literal($this->connID, $str);
243247
}
244248

245249
if (is_bool($str)) {
246250
return $str ? 'TRUE' : 'FALSE';
247251
}
248252

249-
/** @psalm-suppress NoValue I don't know why ERROR. */
250253
return parent::escape($str);
251254
}
252255

system/Debug/BaseExceptionHandler.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,14 @@ protected static function highlightFile(string $file, int $lineNumber, int $line
245245
*/
246246
protected function render(Throwable $exception, int $statusCode, $viewFile = null): void
247247
{
248-
if (empty($viewFile) || ! is_file($viewFile)) {
249-
echo 'The error view files were not found. Cannot render exception trace.';
248+
if ($viewFile === null) {
249+
echo 'The error view file was not specified. Cannot display error view.';
250+
251+
exit(1);
252+
}
253+
254+
if (! is_file($viewFile)) {
255+
echo 'The error view file "' . $viewFile . '" was not found. Cannot display error view.';
250256

251257
exit(1);
252258
}

0 commit comments

Comments
 (0)