Skip to content

Commit 544d392

Browse files
committed
Merge branch '4.5' of https://github.com/codeigniter4/CodeIgniter4 into fix-command-routes-with-locale
2 parents 91c778b + 7aad65d commit 544d392

Some content is hidden

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

46 files changed

+569
-281
lines changed

phpstan-baseline.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,6 @@
9696
'count' => 6,
9797
'path' => __DIR__ . '/system/CLI/CLI.php',
9898
];
99-
$ignoreErrors[] = [
100-
'message' => '#^Only booleans are allowed in &&, array given on the right side\\.$#',
101-
'count' => 1,
102-
'path' => __DIR__ . '/system/CLI/CLI.php',
103-
];
10499
$ignoreErrors[] = [
105100
'message' => '#^Only booleans are allowed in &&, array\\<int, string\\> given on the right side\\.$#',
106101
'count' => 1,
@@ -1158,7 +1153,7 @@
11581153
];
11591154
$ignoreErrors[] = [
11601155
'message' => '#^Only booleans are allowed in a ternary operator condition, int\\<0, max\\> given\\.$#',
1161-
'count' => 4,
1156+
'count' => 3,
11621157
'path' => __DIR__ . '/system/Database/MigrationRunner.php',
11631158
];
11641159
$ignoreErrors[] = [
@@ -2098,7 +2093,7 @@
20982093
];
20992094
$ignoreErrors[] = [
21002095
'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#',
2101-
'count' => 6,
2096+
'count' => 5,
21022097
'path' => __DIR__ . '/system/HTTP/IncomingRequest.php',
21032098
];
21042099
$ignoreErrors[] = [

rector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
__DIR__ . '/system/Router/AutoRouterImproved.php',
9595
// @TODO remove if deprecated $config is removed
9696
__DIR__ . '/system/HTTP/Request.php',
97+
__DIR__ . '/system/HTTP/Response.php',
9798
],
9899

99100
// check on constant compare

system/CLI/CLI.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,9 @@ public static function input(?string $prefix = null): string
213213
* // Do not provide options but requires a valid email
214214
* $email = CLI::prompt('What is your email?', null, 'required|valid_email');
215215
*
216-
* @param string $field Output "field" question
217-
* @param array|string $options String to a default value, array to a list of options (the first option will be the default value)
218-
* @param array|string|null $validation Validation rules
216+
* @param string $field Output "field" question
217+
* @param list<int|string>|string $options String to a default value, array to a list of options (the first option will be the default value)
218+
* @param array|string|null $validation Validation rules
219219
*
220220
* @return string The user input
221221
*/
@@ -237,9 +237,9 @@ public static function prompt(string $field, $options = null, $validation = null
237237
$default = $options;
238238
}
239239

240-
if (is_array($options) && $options) {
240+
if (is_array($options) && $options !== []) {
241241
$opts = $options;
242-
$extraOutputDefault = static::color($opts[0], 'green');
242+
$extraOutputDefault = static::color((string) $opts[0], 'green');
243243

244244
unset($opts[0]);
245245

system/Commands/Database/MigrateStatus.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public function run(array $params)
115115
ksort($migrations);
116116

117117
foreach ($migrations as $uid => $migration) {
118-
$migrations[$uid]->name = mb_substr($migration->name, mb_strpos($migration->name, $uid . '_'));
118+
$migrations[$uid]->name = mb_substr($migration->name, (int) mb_strpos($migration->name, $uid . '_'));
119119

120120
$date = '---';
121121
$group = '---';

system/Commands/Generators/Views/filter.tpl.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class {class} implements FilterInterface
2121
* @param RequestInterface $request
2222
* @param array|null $arguments
2323
*
24-
* @return mixed
24+
* @return RequestInterface|ResponseInterface|string|void
2525
*/
2626
public function before(RequestInterface $request, $arguments = null)
2727
{
@@ -38,7 +38,7 @@ public function before(RequestInterface $request, $arguments = null)
3838
* @param ResponseInterface $response
3939
* @param array|null $arguments
4040
*
41-
* @return mixed
41+
* @return ResponseInterface|void
4242
*/
4343
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
4444
{

system/Common.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ function is_windows(?bool $mock = null): bool
755755
* A convenience method to translate a string or array of them and format
756756
* the result with the intl extension's MessageFormatter.
757757
*
758-
* @return string
758+
* @return list<string>|string
759759
*/
760760
function lang(string $line, array $args = [], ?string $locale = null)
761761
{

system/Database/MigrationRunner.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ public function getBatchEnd(int $batch): string
752752
->get()
753753
->getResultObject();
754754

755-
return count($migration) ? $migration[0]->version : 0;
755+
return $migration === [] ? '0' : $migration[0]->version;
756756
}
757757

758758
/**

system/HTTP/IncomingRequest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,14 @@ public function __construct($config, ?URI $uri = null, $body = 'php://input', ?U
165165
$body = file_get_contents('php://input');
166166
}
167167

168+
// If file_get_contents() returns false or empty string, set null.
169+
if ($body === false || $body === '') {
170+
$body = null;
171+
}
172+
168173
$this->config = $config;
169174
$this->uri = $uri;
170-
$this->body = ! empty($body) ? $body : null;
175+
$this->body = $body;
171176
$this->userAgent = $userAgent;
172177
$this->validLocales = $config->supportedLocales;
173178

system/HTTP/Response.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,10 @@ class Response extends Message implements ResponseInterface
146146
* @param App $config
147147
*
148148
* @todo Recommend removing reliance on config injection
149+
*
150+
* @deprecated 4.5.0 The param $config is no longer used.
149151
*/
150-
public function __construct($config)
152+
public function __construct($config) // @phpstan-ignore-line
151153
{
152154
// Default to a non-caching page.
153155
// Also ensures that a Cache-control header exists.
@@ -156,8 +158,6 @@ public function __construct($config)
156158
// We need CSP object even if not enabled to avoid calls to non existing methods
157159
$this->CSP = Services::csp();
158160

159-
$this->CSPEnabled = $config->CSPEnabled;
160-
161161
$this->cookieStore = new CookieStore([]);
162162

163163
$cookie = config(CookieConfig::class);

system/HTTP/ResponseTrait.php

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,12 @@
3434
*/
3535
trait ResponseTrait
3636
{
37-
/**
38-
* Whether Content Security Policy is being enforced.
39-
*
40-
* @var bool
41-
*
42-
* @deprecated Use $this->CSP->enabled() instead.
43-
*/
44-
protected $CSPEnabled = false;
45-
4637
/**
4738
* Content security policy handler
4839
*
4940
* @var ContentSecurityPolicy
50-
*
51-
* @deprecated Will be protected. Use `getCSP()` instead.
5241
*/
53-
public $CSP;
42+
protected $CSP;
5443

5544
/**
5645
* CookieStore instance.
@@ -59,69 +48,6 @@ trait ResponseTrait
5948
*/
6049
protected $cookieStore;
6150

62-
/**
63-
* Set a cookie name prefix if you need to avoid collisions
64-
*
65-
* @var string
66-
*
67-
* @deprecated Use the dedicated Cookie class instead.
68-
*/
69-
protected $cookiePrefix = '';
70-
71-
/**
72-
* Set to .your-domain.com for site-wide cookies
73-
*
74-
* @var string
75-
*
76-
* @deprecated Use the dedicated Cookie class instead.
77-
*/
78-
protected $cookieDomain = '';
79-
80-
/**
81-
* Typically will be a forward slash
82-
*
83-
* @var string
84-
*
85-
* @deprecated Use the dedicated Cookie class instead.
86-
*/
87-
protected $cookiePath = '/';
88-
89-
/**
90-
* Cookie will only be set if a secure HTTPS connection exists.
91-
*
92-
* @var bool
93-
*
94-
* @deprecated Use the dedicated Cookie class instead.
95-
*/
96-
protected $cookieSecure = false;
97-
98-
/**
99-
* Cookie will only be accessible via HTTP(S) (no javascript)
100-
*
101-
* @var bool
102-
*
103-
* @deprecated Use the dedicated Cookie class instead.
104-
*/
105-
protected $cookieHTTPOnly = false;
106-
107-
/**
108-
* Cookie SameSite setting
109-
*
110-
* @var string
111-
*
112-
* @deprecated Use the dedicated Cookie class instead.
113-
*/
114-
protected $cookieSameSite = Cookie::SAMESITE_LAX;
115-
116-
/**
117-
* Stores all cookies that were set in the response.
118-
*
119-
* @var array
120-
*
121-
* @deprecated Use the dedicated Cookie class instead.
122-
*/
123-
protected $cookies = [];
124-
12551
/**
12652
* Type of format the body is in.
12753
* Valid: html, json, xml

system/HTTP/SiteURI.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ private function normalizeBaseURL(App $configApp): string
197197
// Validate baseURL
198198
if (filter_var($baseURL, FILTER_VALIDATE_URL) === false) {
199199
throw new ConfigException(
200-
'Config\App::$baseURL is invalid.'
200+
'Config\App::$baseURL "' . $baseURL . '" is not a valid URL.'
201201
);
202202
}
203203

system/Helpers/Array/ArrayHelper.php

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace CodeIgniter\Helpers\Array;
1313

14+
use InvalidArgumentException;
15+
1416
/**
1517
* @interal This is internal implementation for the framework.
1618
*
@@ -27,9 +29,21 @@ final class ArrayHelper
2729
*
2830
* @used-by dot_array_search()
2931
*
32+
* @param string $index The index as dot array syntax.
33+
*
3034
* @return array|bool|int|object|string|null
3135
*/
3236
public static function dotSearch(string $index, array $array)
37+
{
38+
return self::arraySearchDot(self::convertToArray($index), $array);
39+
}
40+
41+
/**
42+
* @param string $index The index as dot array syntax.
43+
*
44+
* @return list<string> The index as an array.
45+
*/
46+
private static function convertToArray(string $index): array
3347
{
3448
// See https://regex101.com/r/44Ipql/1
3549
$segments = preg_split(
@@ -39,9 +53,10 @@ public static function dotSearch(string $index, array $array)
3953
PREG_SPLIT_NO_EMPTY
4054
);
4155

42-
$segments = array_map(static fn ($key) => str_replace('\.', '.', $key), $segments);
43-
44-
return self::arraySearchDot($segments, $array);
56+
return array_map(
57+
static fn ($key) => str_replace('\.', '.', $key),
58+
$segments
59+
);
4560
}
4661

4762
/**
@@ -106,6 +121,59 @@ private static function arraySearchDot(array $indexes, array $array)
106121
return null;
107122
}
108123

124+
/**
125+
* array_key_exists() with dot array syntax.
126+
*
127+
* If wildcard `*` is used, all items for the key after it must have the key.
128+
*/
129+
public static function dotKeyExists(string $index, array $array): bool
130+
{
131+
if (str_ends_with($index, '*') || str_contains($index, '*.*')) {
132+
throw new InvalidArgumentException(
133+
'You must set key right after "*". Invalid index: "' . $index . '"'
134+
);
135+
}
136+
137+
$indexes = self::convertToArray($index);
138+
139+
// If indexes is empty, returns false.
140+
if ($indexes === []) {
141+
return false;
142+
}
143+
144+
$currentArray = $array;
145+
146+
// Grab the current index
147+
while ($currentIndex = array_shift($indexes)) {
148+
if ($currentIndex === '*') {
149+
$currentIndex = array_shift($indexes);
150+
151+
foreach ($currentArray as $item) {
152+
if (! array_key_exists($currentIndex, $item)) {
153+
return false;
154+
}
155+
}
156+
157+
// If indexes is empty, all elements are checked.
158+
if ($indexes === []) {
159+
return true;
160+
}
161+
162+
$currentArray = self::dotSearch('*.' . $currentIndex, $currentArray);
163+
164+
continue;
165+
}
166+
167+
if (! array_key_exists($currentIndex, $currentArray)) {
168+
return false;
169+
}
170+
171+
$currentArray = $currentArray[$currentIndex];
172+
}
173+
174+
return true;
175+
}
176+
109177
/**
110178
* Groups all rows by their index values. Result's depth equals number of indexes
111179
*

system/Language/Language.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public function getLocale(): string
8888
* Parses the language string for a file, loads the file, if necessary,
8989
* getting the line.
9090
*
91-
* @return string|string[]
91+
* @return list<string>|string
9292
*/
9393
public function getLine(string $line, array $args = [])
9494
{

system/Session/Handlers/RedisHandler.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,13 @@ public function open($path, $name): bool
124124

125125
$redis = new Redis();
126126

127-
if (! $redis->connect($this->savePath['protocol'] . '://' . $this->savePath['host'], ($this->savePath['host'][0] === '/' ? 0 : $this->savePath['port']), $this->savePath['timeout'])) {
127+
if (
128+
! $redis->connect(
129+
$this->savePath['protocol'] . '://' . $this->savePath['host'],
130+
($this->savePath['host'][0] === '/') ? 0 : (int) $this->savePath['port'],
131+
$this->savePath['timeout']
132+
)
133+
) {
128134
$this->logger->error('Session: Unable to connect to Redis with the configured settings.');
129135
} elseif (isset($this->savePath['password']) && ! $redis->auth($this->savePath['password'])) {
130136
$this->logger->error('Session: Unable to authenticate to Redis instance.');

system/Test/CIUnitTestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ public function assertHeaderNotEmitted(string $header, bool $ignoreCase = false)
439439
* where the result is close but not exactly equal to the
440440
* expected time, for reasons beyond our control.
441441
*
442-
* @param mixed $actual
442+
* @param float|int $actual
443443
*
444444
* @throws Exception
445445
*/

0 commit comments

Comments
 (0)