Skip to content

Commit 27eb447

Browse files
committed
Release v4.1.5
1 parent b0868b9 commit 27eb447

File tree

98 files changed

+2931
-818
lines changed

Some content is hidden

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

98 files changed

+2931
-818
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ framework are exposed.
2828

2929
## Repository Management
3030

31-
We use Github issues, in our main repository, to track **BUGS** and to track approved **DEVELOPMENT** work packages.
31+
We use GitHub issues, in our main repository, to track **BUGS** and to track approved **DEVELOPMENT** work packages.
3232
We use our [forum](http://forum.codeigniter.com) to provide SUPPORT and to discuss
3333
FEATURE REQUESTS.
3434

app/Config/CURLRequest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Config;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
7+
class CURLRequest extends BaseConfig
8+
{
9+
/**
10+
* --------------------------------------------------------------------------
11+
* CURLRequest Share Options
12+
* --------------------------------------------------------------------------
13+
*
14+
* Whether share options between requests or not.
15+
*
16+
* If true, all the options won't be reset between requests.
17+
* It may cause an error request with unnecessary headers.
18+
*
19+
* @var bool
20+
*/
21+
public $shareOptions = true;
22+
}

app/Config/Cache.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,20 @@ class Cache extends BaseConfig
9797
*/
9898
public $ttl = 60;
9999

100+
/**
101+
* --------------------------------------------------------------------------
102+
* Reserved Characters
103+
* --------------------------------------------------------------------------
104+
*
105+
* A string of reserved characters that will not be allowed in keys or tags.
106+
* Strings that violate this restriction will cause handlers to throw.
107+
* Default: {}()/\@:
108+
* Note: The default set is required for PSR-6 compliance.
109+
*
110+
* @var string
111+
*/
112+
public $reservedCharacters = '{}()/\@:';
113+
100114
/**
101115
* --------------------------------------------------------------------------
102116
* File settings

app/Config/Feature.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Config;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
7+
/**
8+
* Enable/disable backward compatibility breaking features.
9+
*/
10+
class Feature extends BaseConfig
11+
{
12+
/**
13+
* Enable multiple filters for a route or not
14+
*
15+
* If you enable this:
16+
* - CodeIgniter\CodeIgniter::handleRequest() uses:
17+
* - CodeIgniter\Filters\Filters::enableFilters(), instead of enableFilter()
18+
* - CodeIgniter\CodeIgniter::tryToRouteIt() uses:
19+
* - CodeIgniter\Router\Router::getFilters(), instead of getFilter()
20+
* - CodeIgniter\Router\Router::handle() uses:
21+
* - property $filtersInfo, instead of $filterInfo
22+
* - CodeIgniter\Router\RouteCollection::getFiltersForRoute(), instead of getFilterForRoute()
23+
*
24+
* @var bool
25+
*/
26+
public $multipleFilters = false;
27+
}

app/Config/Generators.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Generators extends BaseConfig
2727
*/
2828
public $views = [
2929
'make:command' => 'CodeIgniter\Commands\Generators\Views\command.tpl.php',
30+
'make:config' => 'CodeIgniter\Commands\Generators\Views\config.tpl.php',
3031
'make:controller' => 'CodeIgniter\Commands\Generators\Views\controller.tpl.php',
3132
'make:entity' => 'CodeIgniter\Commands\Generators\Views\entity.tpl.php',
3233
'make:filter' => 'CodeIgniter\Commands\Generators\Views\filter.tpl.php',

app/Config/Kint.php

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,28 @@ class Kint extends BaseConfig
2424
*/
2525

2626
public $plugins;
27-
28-
public $maxDepth = 6;
29-
27+
public $maxDepth = 6;
3028
public $displayCalledFrom = true;
31-
32-
public $expanded = false;
29+
public $expanded = false;
3330

3431
/*
3532
|--------------------------------------------------------------------------
3633
| RichRenderer Settings
3734
|--------------------------------------------------------------------------
3835
*/
39-
public $richTheme = 'aante-light.css';
40-
36+
public $richTheme = 'aante-light.css';
4137
public $richFolder = false;
42-
43-
public $richSort = Renderer::SORT_FULL;
44-
38+
public $richSort = Renderer::SORT_FULL;
4539
public $richObjectPlugins;
46-
4740
public $richTabPlugins;
4841

4942
/*
5043
|--------------------------------------------------------------------------
5144
| CLI Settings
5245
|--------------------------------------------------------------------------
5346
*/
54-
public $cliColors = true;
55-
56-
public $cliForceUTF8 = false;
57-
47+
public $cliColors = true;
48+
public $cliForceUTF8 = false;
5849
public $cliDetectWidth = true;
59-
60-
public $cliMinWidth = 40;
50+
public $cliMinWidth = 40;
6151
}

app/Config/Publisher.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Config;
4+
5+
use CodeIgniter\Config\Publisher as BasePublisher;
6+
7+
/**
8+
* Publisher Configuration
9+
*
10+
* Defines basic security restrictions for the Publisher class
11+
* to prevent abuse by injecting malicious files into a project.
12+
*/
13+
class Publisher extends BasePublisher
14+
{
15+
/**
16+
* A list of allowed destinations with a (pseudo-)regex
17+
* of allowed files for each destination.
18+
* Attempts to publish to directories not in this list will
19+
* result in a PublisherException. Files that do no fit the
20+
* pattern will cause copy/merge to fail.
21+
*
22+
* @var array<string,string>
23+
*/
24+
public $restrictions = [
25+
ROOTPATH => '*',
26+
FCPATH => '#\.(?css|js|map|htm?|xml|json|webmanifest|tff|eot|woff?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
27+
];
28+
}

app/Config/Security.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@
66

77
class Security extends BaseConfig
88
{
9+
/**
10+
* --------------------------------------------------------------------------
11+
* CSRF Protection Method
12+
* --------------------------------------------------------------------------
13+
*
14+
* Protection Method for Cross Site Request Forgery protection.
15+
*
16+
* @var string 'cookie' or 'session'
17+
*/
18+
public $csrfProtection = 'cookie';
19+
920
/**
1021
* --------------------------------------------------------------------------
1122
* CSRF Token Name
1223
* --------------------------------------------------------------------------
1324
*
14-
* Token name for Cross Site Request Forgery protection cookie.
25+
* Token name for Cross Site Request Forgery protection.
1526
*
1627
* @var string
1728
*/
@@ -22,7 +33,7 @@ class Security extends BaseConfig
2233
* CSRF Header Name
2334
* --------------------------------------------------------------------------
2435
*
25-
* Token name for Cross Site Request Forgery protection cookie.
36+
* Header name for Cross Site Request Forgery protection.
2637
*
2738
* @var string
2839
*/
@@ -33,7 +44,7 @@ class Security extends BaseConfig
3344
* CSRF Cookie Name
3445
* --------------------------------------------------------------------------
3546
*
36-
* Cookie name for Cross Site Request Forgery protection cookie.
47+
* Cookie name for Cross Site Request Forgery protection.
3748
*
3849
* @var string
3950
*/
@@ -57,7 +68,7 @@ class Security extends BaseConfig
5768
* CSRF Regenerate
5869
* --------------------------------------------------------------------------
5970
*
60-
* Regenerate CSRF Token on every request.
71+
* Regenerate CSRF Token on every submission.
6172
*
6273
* @var bool
6374
*/

app/Views/welcome_message.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
color: rgba(200, 200, 200, 1);
164164
padding: .25rem 1.75rem;
165165
}
166-
@media (max-width: 559px) {
166+
@media (max-width: 629px) {
167167
header ul {
168168
padding: 0;
169169
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"ext-json": "*",
1212
"ext-mbstring": "*",
1313
"kint-php/kint": "^3.3",
14-
"laminas/laminas-escaper": "^2.8",
14+
"laminas/laminas-escaper": "^2.9",
1515
"psr/log": "^1.1"
1616
},
1717
"require-dev": {

env

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
# SECURITY
111111
#--------------------------------------------------------------------
112112

113+
# security.csrfProtection = 'cookie'
113114
# security.tokenName = 'csrf_token_name'
114115
# security.headerName = 'X-CSRF-TOKEN'
115116
# security.cookieName = 'csrf_cookie_name'
@@ -123,3 +124,9 @@
123124
#--------------------------------------------------------------------
124125

125126
# logger.threshold = 4
127+
128+
#--------------------------------------------------------------------
129+
# CURLRequest
130+
#--------------------------------------------------------------------
131+
132+
# curlrequest.shareOptions = true

system/BaseModel.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ abstract protected function doInsert(array $data);
366366
* This methods works only with dbCalls
367367
*
368368
* @param array|null $set An associative array of insert values
369-
* @param bool|null $escape Whether to escape values and identifiers
369+
* @param bool|null $escape Whether to escape values
370370
* @param int $batchSize The size of the batch to run
371371
* @param bool $testing True means only number of records is returned, false will execute the query
372372
*
@@ -763,7 +763,7 @@ public function insert($data = null, bool $returnID = true)
763763
* Compiles batch insert runs the queries, validating each row prior.
764764
*
765765
* @param array|null $set an associative array of insert values
766-
* @param bool|null $escape Whether to escape values and identifiers
766+
* @param bool|null $escape Whether to escape values
767767
* @param int $batchSize The size of the batch to run
768768
* @param bool $testing True means only number of records is returned, false will execute the query
769769
*
@@ -1031,6 +1031,10 @@ public function replace(?array $data = null, bool $returnSQL = false)
10311031
return false;
10321032
}
10331033

1034+
if ($this->useTimestamps && $this->updatedField && ! array_key_exists($this->updatedField, (array) $data)) {
1035+
$data[$this->updatedField] = $this->setDate();
1036+
}
1037+
10341038
return $this->doReplace($data, $returnSQL);
10351039
}
10361040

@@ -1079,7 +1083,7 @@ public function paginate(?int $perPage = null, string $group = 'default', ?int $
10791083
// Store it in the Pager library, so it can be paginated in the views.
10801084
$this->pager = $pager->store($group, $page, $perPage, $this->countAllResults(false), $segment);
10811085
$perPage = $this->pager->getPerPage($group);
1082-
$offset = ($page - 1) * $perPage;
1086+
$offset = ($pager->getCurrentPage($group) - 1) * $perPage;
10831087

10841088
return $this->findAll($perPage, $offset);
10851089
}

system/CLI/CLI.php

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,38 +228,77 @@ public static function prompt(string $field, $options = null, $validation = null
228228
}
229229

230230
if (is_string($options)) {
231-
$extraOutput = ' [' . static::color($options, 'white') . ']';
231+
$extraOutput = ' [' . static::color($options, 'green') . ']';
232232
$default = $options;
233233
}
234234

235235
if (is_array($options) && $options) {
236236
$opts = $options;
237-
$extraOutputDefault = static::color($opts[0], 'white');
237+
$extraOutputDefault = static::color($opts[0], 'green');
238238

239239
unset($opts[0]);
240240

241241
if (empty($opts)) {
242242
$extraOutput = $extraOutputDefault;
243243
} else {
244-
$extraOutput = ' [' . $extraOutputDefault . ', ' . implode(', ', $opts) . ']';
245-
$validation[] = 'in_list[' . implode(',', $options) . ']';
244+
$extraOutput = '[' . $extraOutputDefault . ', ' . implode(', ', $opts) . ']';
245+
$validation[] = 'in_list[' . implode(', ', $options) . ']';
246246
}
247247

248248
$default = $options[0];
249249
}
250250

251-
static::fwrite(STDOUT, $field . $extraOutput . ': ');
251+
static::fwrite(STDOUT, $field . (trim($field) ? ' ' : '') . $extraOutput . ': ');
252252

253253
// Read the input from keyboard.
254254
$input = trim(static::input()) ?: $default;
255255

256256
if ($validation) {
257-
while (! static::validate($field, $input, $validation)) {
257+
while (! static::validate(trim($field), $input, $validation)) {
258258
$input = static::prompt($field, $options, $validation);
259259
}
260260
}
261261

262-
return empty($input) ? '' : $input;
262+
return $input;
263+
}
264+
265+
/**
266+
* prompt(), but based on the option's key
267+
*
268+
* @param array|string $text Output "field" text or an one or two value array where the first value is the text before listing the options
269+
* and the second value the text before asking to select one option. Provide empty string to omit
270+
* @param array $options A list of options (array(key => description)), the first option will be the default value
271+
* @param array|string|null $validation Validation rules
272+
*
273+
* @return string The selected key of $options
274+
*
275+
* @codeCoverageIgnore
276+
*/
277+
public static function promptByKey($text, array $options, $validation = null): string
278+
{
279+
if (is_string($text)) {
280+
$text = [$text];
281+
} elseif (! is_array($text)) {
282+
throw new InvalidArgumentException('$text can only be of type string|array');
283+
}
284+
285+
if (! $options) {
286+
throw new InvalidArgumentException('No options to select from were provided');
287+
}
288+
289+
if ($line = array_shift($text)) {
290+
CLI::write($line);
291+
}
292+
293+
// +2 for the square brackets around the key
294+
$keyMaxLength = max(array_map('mb_strwidth', array_keys($options))) + 2;
295+
296+
foreach ($options as $key => $description) {
297+
$name = str_pad(' [' . $key . '] ', $keyMaxLength + 4, ' ');
298+
CLI::write(CLI::color($name, 'green') . CLI::wrap($description, 125, $keyMaxLength + 4));
299+
}
300+
301+
return static::prompt(PHP_EOL . array_shift($text), array_keys($options), $validation);
263302
}
264303

265304
/**

system/CLI/GeneratorTrait.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,14 @@ protected function qualifyClassName(): string
215215
// Trims input, normalize separators, and ensure that all paths are in Pascalcase.
216216
$class = ltrim(implode('\\', array_map('pascalize', explode('\\', str_replace('/', '\\', trim($class))))), '\\/');
217217

218-
// Gets the namespace from input.
219-
$namespace = trim(str_replace('/', '\\', $this->getOption('namespace') ?? APP_NAMESPACE), '\\');
218+
// Gets the namespace from input. Don't forget the ending backslash!
219+
$namespace = trim(str_replace('/', '\\', $this->getOption('namespace') ?? APP_NAMESPACE), '\\') . '\\';
220220

221221
if (strncmp($class, $namespace, strlen($namespace)) === 0) {
222222
return $class; // @codeCoverageIgnore
223223
}
224224

225-
return $namespace . '\\' . $this->directory . '\\' . str_replace('/', '\\', $class);
225+
return $namespace . $this->directory . '\\' . str_replace('/', '\\', $class);
226226
}
227227

228228
/**

0 commit comments

Comments
 (0)