mirror of
https://github.com/codeigniter4/CodeIgniter4.git
synced 2025-02-20 11:44:28 +08:00
Merge pull request #9420 from codeigniter4/develop
Some checks failed
AutoReview / Automatic Code Review (push) Has been cancelled
AutoReview / Check normalized composer.json (push) Has been cancelled
Coding Standards / PHP 8.1 Lint with PHP CS Fixer (push) Has been cancelled
Coding Standards / PHP 8.4 Lint with PHP CS Fixer (push) Has been cancelled
Check File Permissions / Check File Permission (push) Has been cancelled
Some checks failed
AutoReview / Automatic Code Review (push) Has been cancelled
AutoReview / Check normalized composer.json (push) Has been cancelled
Coding Standards / PHP 8.1 Lint with PHP CS Fixer (push) Has been cancelled
Coding Standards / PHP 8.4 Lint with PHP CS Fixer (push) Has been cancelled
Check File Permissions / Check File Permission (push) Has been cancelled
4.6.0 Ready code
This commit is contained in:
commit
5f37fda626
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -25,11 +25,10 @@ body:
|
||||
description: Which PHP versions did you run your code?
|
||||
multiple: true
|
||||
options:
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
- '8.3'
|
||||
- '8.4'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
2
.github/prlint.json
vendored
2
.github/prlint.json
vendored
@ -1,7 +1,7 @@
|
||||
{
|
||||
"title": [
|
||||
{
|
||||
"pattern": "^(\\[\\d+\\.\\d+\\]\\s{1})?(feat|fix|chore|docs|perf|refactor|style|test|config|revert)(\\([\\-.@:`a-zA-Z0-9]+\\))?!?:\\s{1}\\S.+\\S|Prep for \\d\\.\\d\\.\\d release|\\d\\.\\d\\.\\d Ready code$",
|
||||
"pattern": "^(\\[\\d+\\.\\d+\\]\\s{1})?(feat|fix|chore|docs|perf|refactor|style|test|config|revert)(\\([\\-.@:`a-zA-Z0-9]+\\))?!?:\\s{1}\\S.+\\S|Prep for \\d\\.\\d\\.\\d release|\\d\\.\\d\\.\\d (Ready|Merge) code$",
|
||||
"message": "PR title must include the type (feat, fix, chore, docs, perf, refactor, style, test, config, revert) of the commit per Conventional Commits specification. See https://www.conventionalcommits.org/en/v1.0.0/ for the discussion."
|
||||
}
|
||||
]
|
||||
|
4
.github/workflows/test-coding-standards.yml
vendored
4
.github/workflows/test-coding-standards.yml
vendored
@ -29,7 +29,7 @@ jobs:
|
||||
matrix:
|
||||
php-version:
|
||||
- '8.1'
|
||||
- '8.3'
|
||||
- '8.4'
|
||||
|
||||
steps:
|
||||
- name: Checkout base branch for PR
|
||||
@ -65,3 +65,5 @@ jobs:
|
||||
|
||||
- name: Run lint
|
||||
run: composer cs
|
||||
env:
|
||||
PHP_CS_FIXER_IGNORE_ENV: ${{ matrix.php-version == '8.4' }}
|
||||
|
15
.github/workflows/test-phpunit.yml
vendored
15
.github/workflows/test-phpunit.yml
vendored
@ -59,9 +59,7 @@ jobs:
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
- '8.3'
|
||||
include:
|
||||
- php-version: '8.3'
|
||||
composer-option: '--ignore-platform-req=php'
|
||||
- '8.4'
|
||||
|
||||
uses: ./.github/workflows/reusable-phpunit-test.yml # @TODO Extract to codeigniter4/.github repo
|
||||
with:
|
||||
@ -88,6 +86,7 @@ jobs:
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
- '8.3'
|
||||
- '8.4'
|
||||
db-platform:
|
||||
- MySQLi
|
||||
- OCI8
|
||||
@ -100,8 +99,6 @@ jobs:
|
||||
- php-version: '8.1'
|
||||
db-platform: MySQLi
|
||||
mysql-version: '5.7'
|
||||
- php-version: '8.3'
|
||||
composer-option: '--ignore-platform-req=php'
|
||||
|
||||
uses: ./.github/workflows/reusable-phpunit-test.yml # @TODO Extract to codeigniter4/.github repo
|
||||
with:
|
||||
@ -129,9 +126,7 @@ jobs:
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
- '8.3'
|
||||
include:
|
||||
- php-version: '8.3'
|
||||
composer-option: '--ignore-platform-req=php'
|
||||
- '8.4'
|
||||
|
||||
uses: ./.github/workflows/reusable-phpunit-test.yml # @TODO Extract to codeigniter4/.github repo
|
||||
with:
|
||||
@ -157,9 +152,7 @@ jobs:
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
- '8.3'
|
||||
include:
|
||||
- php-version: '8.3'
|
||||
composer-option: '--ignore-platform-req=php'
|
||||
- '8.4'
|
||||
|
||||
uses: ./.github/workflows/reusable-phpunit-test.yml # @TODO Extract to codeigniter4/.github repo
|
||||
with:
|
||||
|
2
.github/workflows/test-rector.yml
vendored
2
.github/workflows/test-rector.yml
vendored
@ -45,7 +45,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-versions: ['8.1', '8.3']
|
||||
php-versions: ['8.1', '8.4']
|
||||
steps:
|
||||
- name: Checkout base branch for PR
|
||||
if: github.event_name == 'pull_request'
|
||||
|
63
CHANGELOG.md
63
CHANGELOG.md
@ -1,5 +1,68 @@
|
||||
# Changelog
|
||||
|
||||
## [v4.6.0](https://github.com/codeigniter4/CodeIgniter4/tree/v4.6.0) (2025-01-19)
|
||||
[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.5.8...v4.6.0)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* refactor: remove deprecated failValidationError() in API\ResponseTrait by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8793
|
||||
* refactor: remove depreacted ResponseInterface::getReason() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8841
|
||||
* refactor: remove deprecated Logger::cleanFilenames() and TestLogger::cleanup() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8843
|
||||
* fix: Exception rework by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8728
|
||||
* fix: DefinedRouteCollector to use RouteCollectionInterface by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8911
|
||||
* fix: View::renderSection() return type by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8965
|
||||
* feat: [Filters] enables a filter to run more than once with different arguments by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8977
|
||||
* fix: add check for duplicate Registrar Auto-Discovery runs by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9073
|
||||
* fix: Time loses microseconds by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9081
|
||||
* feat: fix spark db:table causes errors with table name including special chars by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8748
|
||||
* [4.6] fix: Time::createFromTimestamp() change for PHP 8.4 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9105
|
||||
* fix: Time::setTimestamp()'s different behavior than DateTime by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9106
|
||||
* [4.6] fix: inconsistency in detailed error reporting by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9144
|
||||
* [4.6] feat: force PHP default 32 chars length at 4 bits to Session ID by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9139
|
||||
* fix: prioritize headers set by the `Response` class by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/9235
|
||||
|
||||
### Fixed Bugs
|
||||
|
||||
* [4.6] fix: add validation message for min_dims by @christianberkman in https://github.com/codeigniter4/CodeIgniter4/pull/8988
|
||||
* fix: [Filters] normalize `$filters` arguments by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8994
|
||||
### Enhancements
|
||||
* feat: [FileCollection] add function to reatain multiple patterns by @christianberkman in https://github.com/codeigniter4/CodeIgniter4/pull/8960
|
||||
* feat: [Validation] add `min_dims` rule in FileRules by @christianberkman in https://github.com/codeigniter4/CodeIgniter4/pull/8966
|
||||
* feat: add `foundRows` option for MySQLi config by @ducng99 in https://github.com/codeigniter4/CodeIgniter4/pull/8979
|
||||
* feat: `spark filter:check` shows filter classnames by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8985
|
||||
* feat: add BaseConnection::resetTransStatus() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8767
|
||||
* feat: add Services::resetServicesCache() to reset services cache by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9012
|
||||
* feat: add "400 Bad Request" page for end users by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9044
|
||||
* feat: add directives to `phpini:check` command by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9117
|
||||
* feat: multiple hostname routing by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/9150
|
||||
* [4.6] feat: workaround for implicit nullable deprecations in PHP 8.4 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9140
|
||||
* feat: support CURL HTTP3 by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/9145
|
||||
* feat: design info environment top in `error_exception` by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/9241
|
||||
* feat: [Validation] add support for `$dbGroup` as parameter in `is_unique` and `is_not_unique` by @maniaba in https://github.com/codeigniter4/CodeIgniter4/pull/9216
|
||||
* feat: added the `namespace` option to the `publish` command by @dimtrovich in https://github.com/codeigniter4/CodeIgniter4/pull/9278
|
||||
* chore: update `Kint` to v6.0 by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/9289
|
||||
* feat: CURL option `force_ip_resolve` by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/9194
|
||||
* feat: add SQLite3 config synchronous by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/9202
|
||||
* feat: Differentiate between kilobyte/kibibyte and megabyte/mebibyte by @ThomasMeschke in https://github.com/codeigniter4/CodeIgniter4/pull/9277
|
||||
* feat: Strict locale negotiation by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9360
|
||||
* fix: Add support for multibyte strings by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9372
|
||||
* feat: add page start end total to `PagerRenderer` by @murilohpucci in https://github.com/codeigniter4/CodeIgniter4/pull/9371
|
||||
* feat: New command `lang:sync` by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9023
|
||||
* feat: additional `opcache` setting in check php.ini by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/9032
|
||||
|
||||
### Refactoring
|
||||
|
||||
* [4.6] refactor: Validation rules and tests by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8975
|
||||
* [4.6] refactor: add `: void` by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9013
|
||||
* refactor: remove dependency on BaseConnection in TableName by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/9104
|
||||
* refactor: add return type to closuer in FilterCheck by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9190
|
||||
* refactor: Remove deprecated `RedirectException` by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9399
|
||||
* refactor: Remove deprecated `EVENT_PRIORITY_*` by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9401
|
||||
* refactor: Remove deprecated `View::$currentSection` by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9403
|
||||
* refactor: Remove deprecated `Cache::$storePath` by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9404
|
||||
* refactor: Remove deprecated `Config\Format::getFormatter()` by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9405
|
||||
* refactor: Remove deprecation related to cookies by @neznaika0 in https://github.com/codeigniter4/CodeIgniter4/pull/9406
|
||||
|
||||
## [v4.5.8](https://github.com/codeigniter4/CodeIgniter4/tree/v4.5.8) (2025-01-19)
|
||||
[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.5.7...v4.5.8)
|
||||
|
||||
|
@ -13,18 +13,18 @@
|
||||
"php": "^8.1",
|
||||
"ext-intl": "*",
|
||||
"ext-mbstring": "*",
|
||||
"laminas/laminas-escaper": "^2.13",
|
||||
"laminas/laminas-escaper": "^2.14",
|
||||
"psr/log": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeigniter/coding-standard": "^1.7",
|
||||
"fakerphp/faker": "^1.9",
|
||||
"fakerphp/faker": "^1.24",
|
||||
"friendsofphp/php-cs-fixer": "^3.47.1",
|
||||
"kint-php/kint": "^5.0.4",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"kint-php/kint": "^6.0",
|
||||
"mikey179/vfsstream": "^1.6.12",
|
||||
"nexusphp/cs-config": "^3.6",
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.2",
|
||||
"predis/predis": "^1.1 || ^2.0"
|
||||
"predis/predis": "^1.1 || ^2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": "If you use CURLRequest class",
|
||||
|
@ -34,18 +34,6 @@ class Cache extends BaseConfig
|
||||
*/
|
||||
public string $backupHandler = 'dummy';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cache Directory Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The path to where cache files should be stored, if using a file-based
|
||||
* system.
|
||||
*
|
||||
* @deprecated Use the driver-specific variant under $file
|
||||
*/
|
||||
public string $storePath = WRITEPATH . 'cache/';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Key Prefix
|
||||
@ -86,6 +74,7 @@ class Cache extends BaseConfig
|
||||
* --------------------------------------------------------------------------
|
||||
* File settings
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Your file storage preferences can be specified below, if you are using
|
||||
* the File driver.
|
||||
*
|
||||
@ -100,6 +89,7 @@ class Cache extends BaseConfig
|
||||
* -------------------------------------------------------------------------
|
||||
* Memcached settings
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Your Memcached servers can be specified below, if you are using
|
||||
* the Memcached drivers.
|
||||
*
|
||||
|
@ -77,18 +77,3 @@ defined('EXIT_USER_INPUT') || define('EXIT_USER_INPUT', 7); // invalid u
|
||||
defined('EXIT_DATABASE') || define('EXIT_DATABASE', 8); // database error
|
||||
defined('EXIT__AUTO_MIN') || define('EXIT__AUTO_MIN', 9); // lowest automatically-assigned error code
|
||||
defined('EXIT__AUTO_MAX') || define('EXIT__AUTO_MAX', 125); // highest automatically-assigned error code
|
||||
|
||||
/**
|
||||
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_LOW instead.
|
||||
*/
|
||||
define('EVENT_PRIORITY_LOW', 200);
|
||||
|
||||
/**
|
||||
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_NORMAL instead.
|
||||
*/
|
||||
define('EVENT_PRIORITY_NORMAL', 100);
|
||||
|
||||
/**
|
||||
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_HIGH instead.
|
||||
*/
|
||||
define('EVENT_PRIORITY_HIGH', 10);
|
||||
|
@ -43,6 +43,7 @@ class Database extends Config
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
'numberNative' => false,
|
||||
'foundRows' => false,
|
||||
'dateFormat' => [
|
||||
'date' => 'Y-m-d',
|
||||
'datetime' => 'Y-m-d H:i:s',
|
||||
@ -64,6 +65,7 @@ class Database extends Config
|
||||
// 'failover' => [],
|
||||
// 'foreignKeys' => true,
|
||||
// 'busyTimeout' => 1000,
|
||||
// 'synchronous' => null,
|
||||
// 'dateFormat' => [
|
||||
// 'date' => 'Y-m-d',
|
||||
// 'datetime' => 'Y-m-d H:i:s',
|
||||
|
@ -10,9 +10,9 @@ use CodeIgniter\Config\BaseConfig;
|
||||
class Feature extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* Use improved new auto routing instead of the default legacy version.
|
||||
* Use improved new auto routing instead of the legacy version.
|
||||
*/
|
||||
public bool $autoRoutesImproved = false;
|
||||
public bool $autoRoutesImproved = true;
|
||||
|
||||
/**
|
||||
* Use filter execution order in 4.4 or before.
|
||||
@ -26,4 +26,12 @@ class Feature extends BaseConfig
|
||||
* If false, `limit(0)` returns no records. (the behavior of 3.1.9 or later in version 3.x.)
|
||||
*/
|
||||
public bool $limitZeroAsAll = true;
|
||||
|
||||
/**
|
||||
* Use strict location negotiation.
|
||||
*
|
||||
* By default, the locale is selected based on a loose comparison of the language code (ISO 639-1)
|
||||
* Enabling strict comparison will also consider the region code (ISO 3166-1 alpha-2).
|
||||
*/
|
||||
public bool $strictLocaleNegotiation = false;
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Format\FormatterInterface;
|
||||
use CodeIgniter\Format\JSONFormatter;
|
||||
use CodeIgniter\Format\XMLFormatter;
|
||||
|
||||
@ -62,16 +61,4 @@ class Format extends BaseConfig
|
||||
'application/xml' => 0,
|
||||
'text/xml' => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* A Factory method to return the appropriate formatter for the given mime type.
|
||||
*
|
||||
* @return FormatterInterface
|
||||
*
|
||||
* @deprecated This is an alias of `\CodeIgniter\Format\Format::getFormatter`. Use that instead.
|
||||
*/
|
||||
public function getFormatter(string $mime)
|
||||
{
|
||||
return service('format')->getFormatter($mime);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace Config;
|
||||
|
||||
use Kint\Parser\ConstructablePluginInterface;
|
||||
use Kint\Renderer\AbstractRenderer;
|
||||
use Kint\Renderer\Rich\TabPluginInterface;
|
||||
use Kint\Renderer\Rich\ValuePluginInterface;
|
||||
|
||||
@ -41,7 +40,6 @@ class Kint
|
||||
*/
|
||||
public string $richTheme = 'aante-light.css';
|
||||
public bool $richFolder = false;
|
||||
public int $richSort = AbstractRenderer::SORT_FULL;
|
||||
|
||||
/**
|
||||
* @var array<string, class-string<ValuePluginInterface>>|null
|
||||
|
@ -136,5 +136,5 @@ class Routing extends BaseRouting
|
||||
*
|
||||
* Default: false
|
||||
*/
|
||||
public bool $translateUriToCamelCase = false;
|
||||
public bool $translateUriToCamelCase = true;
|
||||
}
|
||||
|
@ -83,21 +83,4 @@ class Security extends BaseConfig
|
||||
* @see https://codeigniter4.github.io/userguide/libraries/security.html#redirection-on-failure
|
||||
*/
|
||||
public bool $redirect = (ENVIRONMENT === 'production');
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF SameSite
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Setting for CSRF SameSite cookie token.
|
||||
*
|
||||
* Allowed values are: None - Lax - Strict - ''.
|
||||
*
|
||||
* Defaults to `Lax` as recommended in this link:
|
||||
*
|
||||
* @see https://portswigger.net/web-security/csrf/samesite-cookies
|
||||
*
|
||||
* @deprecated `Config\Cookie` $samesite property is used.
|
||||
*/
|
||||
public string $samesite = 'Lax';
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ p.lead {
|
||||
.header {
|
||||
background: var(--light-bg-color);
|
||||
color: var(--dark-text-color);
|
||||
margin-top: 2.17rem;
|
||||
}
|
||||
.header .container {
|
||||
padding: 1rem;
|
||||
@ -65,10 +66,13 @@ p.lead {
|
||||
}
|
||||
|
||||
.environment {
|
||||
background: var(--dark-bg-color);
|
||||
color: var(--light-text-color);
|
||||
background: var(--brand-primary-color);
|
||||
color: var(--main-bg-color);
|
||||
text-align: center;
|
||||
padding: 0.2rem;
|
||||
padding: calc(4px + 0.2083vw);
|
||||
width: 100%;
|
||||
margin-top: -2.14rem;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.source {
|
||||
|
84
app/Views/errors/html/error_400.php
Normal file
84
app/Views/errors/html/error_400.php
Normal file
@ -0,0 +1,84 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?= lang('Errors.badRequest') ?></title>
|
||||
|
||||
<style>
|
||||
div.logo {
|
||||
height: 200px;
|
||||
width: 155px;
|
||||
display: inline-block;
|
||||
opacity: 0.08;
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
left: 50%;
|
||||
margin-left: -73px;
|
||||
}
|
||||
body {
|
||||
height: 100%;
|
||||
background: #fafafa;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #777;
|
||||
font-weight: 300;
|
||||
}
|
||||
h1 {
|
||||
font-weight: lighter;
|
||||
letter-spacing: normal;
|
||||
font-size: 3rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: #222;
|
||||
}
|
||||
.wrap {
|
||||
max-width: 1024px;
|
||||
margin: 5rem auto;
|
||||
padding: 2rem;
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
border: 1px solid #efefef;
|
||||
border-radius: 0.5rem;
|
||||
position: relative;
|
||||
}
|
||||
pre {
|
||||
white-space: normal;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
code {
|
||||
background: #fafafa;
|
||||
border: 1px solid #efefef;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 5px;
|
||||
display: block;
|
||||
}
|
||||
p {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.footer {
|
||||
margin-top: 2rem;
|
||||
border-top: 1px solid #efefef;
|
||||
padding: 1em 2em 0 2em;
|
||||
font-size: 85%;
|
||||
color: #999;
|
||||
}
|
||||
a:active,
|
||||
a:link,
|
||||
a:visited {
|
||||
color: #dd4814;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<h1>400</h1>
|
||||
|
||||
<p>
|
||||
<?php if (ENVIRONMENT !== 'production') : ?>
|
||||
<?= nl2br(esc($message)) ?>
|
||||
<?php else : ?>
|
||||
<?= lang('Errors.sorryBadRequest') ?>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -13,21 +13,21 @@
|
||||
"php": "^8.1",
|
||||
"ext-intl": "*",
|
||||
"ext-mbstring": "*",
|
||||
"laminas/laminas-escaper": "^2.13",
|
||||
"laminas/laminas-escaper": "^2.14",
|
||||
"psr/log": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeigniter/phpstan-codeigniter": "^1.5.1",
|
||||
"fakerphp/faker": "^1.9",
|
||||
"kint-php/kint": "^5.0.4",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"fakerphp/faker": "^1.24",
|
||||
"kint-php/kint": "^6.0",
|
||||
"mikey179/vfsstream": "^1.6.12",
|
||||
"nexusphp/tachycardia": "^2.0",
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpstan/phpstan-strict-rules": "^2.0",
|
||||
"phpunit/phpcov": "^9.0.2 || ^10.0",
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.2",
|
||||
"predis/predis": "^1.1 || ^2.0",
|
||||
"predis/predis": "^1.1 || ^2.3",
|
||||
"rector/rector": "2.0.6",
|
||||
"shipmonk/phpstan-baseline-per-identifier": "^2.0"
|
||||
},
|
||||
@ -90,7 +90,7 @@
|
||||
"CodeIgniter\\ComposerScripts::postUpdate"
|
||||
],
|
||||
"post-autoload-dump": [
|
||||
"@composer update --working-dir=utils"
|
||||
"@composer update --working-dir=utils --ignore-platform-req=php"
|
||||
],
|
||||
"analyze": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
|
@ -5,12 +5,12 @@
|
||||
xmlns="https://www.phpdoc.org"
|
||||
xsi:noNamespaceSchemaLocation="https://docs.phpdoc.org/latest/phpdoc.xsd"
|
||||
>
|
||||
<title>CodeIgniter v4.5 API</title>
|
||||
<title>CodeIgniter v4.6 API</title>
|
||||
<paths>
|
||||
<output>api/build/</output>
|
||||
<cache>api/cache/</cache>
|
||||
</paths>
|
||||
<version number="4.5.8">
|
||||
<version number="4.6.0">
|
||||
<api format="php">
|
||||
<source dsn=".">
|
||||
<path>system</path>
|
||||
|
@ -38,5 +38,8 @@ parameters:
|
||||
disallowedImplicitArrayCreation: true
|
||||
disallowedShortTernary: true
|
||||
matchingInheritedMethodNames: true
|
||||
codeigniter:
|
||||
additionalServices:
|
||||
- AfterAutoloadModule\Config\Services
|
||||
shipmonkBaselinePerIdentifier:
|
||||
directory: %currentWorkingDirectory%
|
||||
|
@ -19,7 +19,6 @@ use Rector\CodeQuality\Rector\FuncCall\ChangeArrayPushToArrayAssignRector;
|
||||
use Rector\CodeQuality\Rector\FuncCall\CompactToVariablesRector;
|
||||
use Rector\CodeQuality\Rector\FunctionLike\SimplifyUselessVariableRector;
|
||||
use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector;
|
||||
use Rector\CodeQuality\Rector\If_\ShortenElseIfRector;
|
||||
use Rector\CodeQuality\Rector\Ternary\TernaryEmptyArrayArrayDimFetchToCoalesceRector;
|
||||
use Rector\CodingStyle\Rector\ClassMethod\FuncGetArgsToVariadicParamRector;
|
||||
use Rector\CodingStyle\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector;
|
||||
@ -183,7 +182,6 @@ return RectorConfig::configure()
|
||||
ChangeIfElseValueAssignToEarlyReturnRector::class,
|
||||
InlineIfToExplicitIfRector::class,
|
||||
PreparedValueToEarlyReturnRector::class,
|
||||
ShortenElseIfRector::class,
|
||||
UnusedForeachValueToArrayKeysRector::class,
|
||||
ChangeArrayPushToArrayAssignRector::class,
|
||||
RemoveErrorSuppressInTryCatchStmtsRector::class,
|
||||
@ -208,4 +206,4 @@ return RectorConfig::configure()
|
||||
// keep '\\' prefix string on string '\Foo\Bar'
|
||||
StringClassNameToClassConstantRector::SHOULD_KEEP_PRE_SLASH => true,
|
||||
])
|
||||
->withCodeQualityLevel(31);
|
||||
->withCodeQualityLevel(34);
|
||||
|
@ -224,18 +224,6 @@ trait ResponseTrait
|
||||
return $this->fail($description, $this->codes['resource_not_found'], $code, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when the data provided by the client cannot be validated.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @deprecated Use failValidationErrors instead
|
||||
*/
|
||||
protected function failValidationError(string $description = 'Bad Request', ?string $code = null, string $message = '')
|
||||
{
|
||||
return $this->fail($description, $this->codes['invalid_data'], $code, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when the data provided by the client cannot be validated on one or more fields.
|
||||
*
|
||||
|
@ -14,16 +14,16 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Autoloader;
|
||||
|
||||
use CodeIgniter\Exceptions\ConfigException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\InstalledVersions;
|
||||
use Config\Autoload;
|
||||
use Config\Kint as KintConfig;
|
||||
use Config\Modules;
|
||||
use InvalidArgumentException;
|
||||
use Kint;
|
||||
use Kint\Renderer\CliRenderer;
|
||||
use Kint\Renderer\RichRenderer;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* An autoloader that uses both PSR4 autoloading, and traditional classmaps.
|
||||
@ -547,7 +547,7 @@ class Autoloader
|
||||
|
||||
RichRenderer::$theme = $config->richTheme;
|
||||
RichRenderer::$folder = $config->richFolder;
|
||||
RichRenderer::$sort = $config->richSort;
|
||||
|
||||
if (isset($config->richObjectPlugins) && is_array($config->richObjectPlugins)) {
|
||||
RichRenderer::$value_plugins = $config->richObjectPlugins;
|
||||
}
|
||||
|
@ -21,12 +21,12 @@ use CodeIgniter\Database\Exceptions\DataException;
|
||||
use CodeIgniter\Database\Query;
|
||||
use CodeIgniter\DataConverter\DataConverter;
|
||||
use CodeIgniter\Entity\Entity;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\ModelException;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use CodeIgniter\Pager\Pager;
|
||||
use CodeIgniter\Validation\ValidationInterface;
|
||||
use Config\Feature;
|
||||
use InvalidArgumentException;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionProperty;
|
||||
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\CLI;
|
||||
|
||||
use CodeIgniter\CLI\Exceptions\CLIException;
|
||||
use InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
|
@ -52,12 +52,12 @@ class Commands
|
||||
/**
|
||||
* Runs a command given
|
||||
*
|
||||
* @return int|void Exit code
|
||||
* @return int Exit code
|
||||
*/
|
||||
public function run(string $command, array $params)
|
||||
{
|
||||
if (! $this->verifyCommand($command, $this->commands)) {
|
||||
return;
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
// The file would have already been loaded during the
|
||||
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\CLI\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\DebugTraceableTrait;
|
||||
use RuntimeException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
|
||||
/**
|
||||
* CLIException
|
||||
|
@ -14,13 +14,12 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Cache\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\DebugTraceableTrait;
|
||||
use CodeIgniter\Exceptions\ExceptionInterface;
|
||||
use RuntimeException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
|
||||
/**
|
||||
* CacheException
|
||||
*/
|
||||
class CacheException extends RuntimeException implements ExceptionInterface
|
||||
class CacheException extends RuntimeException
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
|
@ -15,9 +15,10 @@ namespace CodeIgniter\Cache\Handlers;
|
||||
|
||||
use Closure;
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use Config\Cache;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Base class for cache handling
|
||||
@ -108,6 +109,6 @@ abstract class BaseHandler implements CacheInterface
|
||||
*/
|
||||
public function deleteMatching(string $pattern)
|
||||
{
|
||||
throw new Exception('The deleteMatching method is not implemented.');
|
||||
throw new BadMethodCallException('The deleteMatching method is not implemented.');
|
||||
}
|
||||
}
|
||||
|
@ -54,13 +54,6 @@ class FileHandler extends BaseHandler
|
||||
*/
|
||||
public function __construct(Cache $config)
|
||||
{
|
||||
if (! property_exists($config, 'file')) {
|
||||
$config->file = [
|
||||
'storePath' => $config->storePath ?? WRITEPATH . 'cache',
|
||||
'mode' => 0640,
|
||||
];
|
||||
}
|
||||
|
||||
$this->path = ! empty($config->file['storePath']) ? $config->file['storePath'] : WRITEPATH . 'cache';
|
||||
$this->path = rtrim($this->path, '/') . '/';
|
||||
|
||||
|
@ -13,6 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Cache\Handlers;
|
||||
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use CodeIgniter\Exceptions\CriticalError;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use Config\Cache;
|
||||
@ -197,7 +198,7 @@ class MemcachedHandler extends BaseHandler
|
||||
*/
|
||||
public function deleteMatching(string $pattern)
|
||||
{
|
||||
throw new Exception('The deleteMatching method is not implemented for Memcached. You must select File, Redis or Predis handlers to use it.');
|
||||
throw new BadMethodCallException('The deleteMatching method is not implemented for Memcached. You must select File, Redis or Predis handlers to use it.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,9 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Cache\Handlers;
|
||||
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use Config\Cache;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Cache handler for WinCache from Microsoft & IIS.
|
||||
@ -80,7 +80,7 @@ class WincacheHandler extends BaseHandler
|
||||
*/
|
||||
public function deleteMatching(string $pattern)
|
||||
{
|
||||
throw new Exception('The deleteMatching method is not implemented for Wincache. You must select File, Redis or Predis handlers to use it.');
|
||||
throw new BadMethodCallException('The deleteMatching method is not implemented for Wincache. You must select File, Redis or Predis handlers to use it.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,12 +13,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Cache;
|
||||
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
use CodeIgniter\HTTP\Header;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Config\Cache as CacheConfig;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Web Page Caching
|
||||
@ -131,7 +131,7 @@ final class ResponseCache
|
||||
|| ! isset($cachedResponse['output'])
|
||||
|| ! isset($cachedResponse['headers'])
|
||||
) {
|
||||
throw new Exception('Error unserializing page cache');
|
||||
throw new RuntimeException('Error unserializing page cache');
|
||||
}
|
||||
|
||||
$headers = $cachedResponse['headers'];
|
||||
|
@ -16,6 +16,7 @@ use CodeIgniter\Cache\ResponseCache;
|
||||
use CodeIgniter\Debug\Timer;
|
||||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\Exceptions\FrameworkException;
|
||||
use CodeIgniter\Exceptions\LogicException;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\Filters\Filters;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
@ -28,7 +29,6 @@ use CodeIgniter\HTTP\Request;
|
||||
use CodeIgniter\HTTP\ResponsableInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\HTTP\URI;
|
||||
use CodeIgniter\Router\Exceptions\RedirectException as DeprecatedRedirectException;
|
||||
use CodeIgniter\Router\RouteCollectionInterface;
|
||||
use CodeIgniter\Router\Router;
|
||||
use Config\App;
|
||||
@ -41,7 +41,6 @@ use Kint;
|
||||
use Kint\Renderer\CliRenderer;
|
||||
use Kint\Renderer\RichRenderer;
|
||||
use Locale;
|
||||
use LogicException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
@ -56,7 +55,7 @@ class CodeIgniter
|
||||
/**
|
||||
* The current version of CodeIgniter Framework
|
||||
*/
|
||||
public const CI_VERSION = '4.5.8';
|
||||
public const CI_VERSION = '4.6.0';
|
||||
|
||||
/**
|
||||
* App startup time.
|
||||
@ -294,7 +293,7 @@ class CodeIgniter
|
||||
|
||||
RichRenderer::$theme = $config->richTheme;
|
||||
RichRenderer::$folder = $config->richFolder;
|
||||
RichRenderer::$sort = $config->richSort;
|
||||
|
||||
if (isset($config->richObjectPlugins) && is_array($config->richObjectPlugins)) {
|
||||
RichRenderer::$value_plugins = $config->richObjectPlugins;
|
||||
}
|
||||
@ -318,7 +317,7 @@ class CodeIgniter
|
||||
*
|
||||
* @param bool $returnResponse Used for testing purposes only.
|
||||
*
|
||||
* @return ResponseInterface|void
|
||||
* @return ResponseInterface|null
|
||||
*/
|
||||
public function run(?RouteCollectionInterface $routes = null, bool $returnResponse = false)
|
||||
{
|
||||
@ -353,11 +352,8 @@ class CodeIgniter
|
||||
} else {
|
||||
try {
|
||||
$this->response = $this->handleRequest($routes, config(Cache::class), $returnResponse);
|
||||
} catch (DeprecatedRedirectException|ResponsableInterface $e) {
|
||||
} catch (ResponsableInterface $e) {
|
||||
$this->outputBufferingEnd();
|
||||
if ($e instanceof DeprecatedRedirectException) {
|
||||
$e = new RedirectException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
$this->response = $e->getResponse();
|
||||
} catch (PageNotFoundException $e) {
|
||||
@ -379,6 +375,8 @@ class CodeIgniter
|
||||
}
|
||||
|
||||
$this->sendResponse();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -863,7 +861,7 @@ class CodeIgniter
|
||||
* controller method and make the script go. If it's not able to, will
|
||||
* show the appropriate Page Not Found error.
|
||||
*
|
||||
* @return ResponseInterface|string|void
|
||||
* @return ResponseInterface|string|null
|
||||
*/
|
||||
protected function startController()
|
||||
{
|
||||
@ -889,6 +887,8 @@ class CodeIgniter
|
||||
) {
|
||||
throw PageNotFoundException::forControllerNotFound($this->controller, $this->method);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,7 +74,7 @@ class MigrateRollback extends BaseCommand
|
||||
$force = array_key_exists('f', $params) || CLI::getOption('f');
|
||||
|
||||
if (! $force && CLI::prompt(lang('Migrations.rollBackConfirm'), ['y', 'n']) === 'n') {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
@ -115,5 +115,7 @@ class MigrateRollback extends BaseCommand
|
||||
$this->showError($e);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,9 @@ namespace CodeIgniter\Commands\Database;
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Database\TableName;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use Config\Database;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Get table data if it exists in the database.
|
||||
@ -199,7 +200,7 @@ class ShowTableInfo extends BaseCommand
|
||||
CLI::newLine();
|
||||
|
||||
$this->removeDBPrefix();
|
||||
$thead = $this->db->getFieldNames($tableName);
|
||||
$thead = $this->db->getFieldNames(TableName::fromActualName($this->db->DBPrefix, $tableName));
|
||||
$this->restoreDBPrefix();
|
||||
|
||||
// If there is a field named `id`, sort by it.
|
||||
@ -277,7 +278,7 @@ class ShowTableInfo extends BaseCommand
|
||||
$this->tbody = [];
|
||||
|
||||
$this->removeDBPrefix();
|
||||
$builder = $this->db->table($tableName);
|
||||
$builder = $this->db->table(TableName::fromActualName($this->db->DBPrefix, $tableName));
|
||||
$builder->limit($limitRows);
|
||||
if ($sortField !== null) {
|
||||
$builder->orderBy($sortField, $this->sortDesc ? 'DESC' : 'ASC');
|
||||
|
202
system/Commands/Translation/LocalizationSync.php
Normal file
202
system/Commands/Translation/LocalizationSync.php
Normal file
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Translation;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use CodeIgniter\Exceptions\LogicException;
|
||||
use Config\App;
|
||||
use ErrorException;
|
||||
use FilesystemIterator;
|
||||
use Locale;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use SplFileInfo;
|
||||
|
||||
/**
|
||||
* @see \CodeIgniter\Commands\Translation\LocalizationSyncTest
|
||||
*/
|
||||
class LocalizationSync extends BaseCommand
|
||||
{
|
||||
protected $group = 'Translation';
|
||||
protected $name = 'lang:sync';
|
||||
protected $description = 'Synchronize translation files from one language to another.';
|
||||
protected $usage = 'lang:sync [options]';
|
||||
protected $arguments = [];
|
||||
protected $options = [
|
||||
'--locale' => 'The original locale (en, ru, etc.).',
|
||||
'--target' => 'Target locale (en, ru, etc.).',
|
||||
];
|
||||
private string $languagePath;
|
||||
|
||||
public function run(array $params)
|
||||
{
|
||||
$optionTargetLocale = '';
|
||||
$optionLocale = $params['locale'] ?? Locale::getDefault();
|
||||
$this->languagePath = APPPATH . 'Language';
|
||||
|
||||
if (isset($params['target']) && $params['target'] !== '') {
|
||||
$optionTargetLocale = $params['target'];
|
||||
}
|
||||
|
||||
if (! in_array($optionLocale, config(App::class)->supportedLocales, true)) {
|
||||
CLI::error(
|
||||
'Error: "' . $optionLocale . '" is not supported. Supported locales: '
|
||||
. implode(', ', config(App::class)->supportedLocales),
|
||||
);
|
||||
|
||||
return EXIT_USER_INPUT;
|
||||
}
|
||||
|
||||
if ($optionTargetLocale === '') {
|
||||
CLI::error(
|
||||
'Error: "--target" is not configured. Supported locales: '
|
||||
. implode(', ', config(App::class)->supportedLocales),
|
||||
);
|
||||
|
||||
return EXIT_USER_INPUT;
|
||||
}
|
||||
|
||||
if (! in_array($optionTargetLocale, config(App::class)->supportedLocales, true)) {
|
||||
CLI::error(
|
||||
'Error: "' . $optionTargetLocale . '" is not supported. Supported locales: '
|
||||
. implode(', ', config(App::class)->supportedLocales),
|
||||
);
|
||||
|
||||
return EXIT_USER_INPUT;
|
||||
}
|
||||
|
||||
if ($optionTargetLocale === $optionLocale) {
|
||||
CLI::error(
|
||||
'Error: You cannot have the same values for "--target" and "--locale".',
|
||||
);
|
||||
|
||||
return EXIT_USER_INPUT;
|
||||
}
|
||||
|
||||
if (ENVIRONMENT === 'testing') {
|
||||
$this->languagePath = SUPPORTPATH . 'Language';
|
||||
}
|
||||
|
||||
if ($this->process($optionLocale, $optionTargetLocale) === EXIT_ERROR) {
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
CLI::write('All operations done!');
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
private function process(string $originalLocale, string $targetLocale): int
|
||||
{
|
||||
$originalLocaleDir = $this->languagePath . DIRECTORY_SEPARATOR . $originalLocale;
|
||||
$targetLocaleDir = $this->languagePath . DIRECTORY_SEPARATOR . $targetLocale;
|
||||
|
||||
if (! is_dir($originalLocaleDir)) {
|
||||
CLI::error(
|
||||
'Error: The "' . clean_path($originalLocaleDir) . '" directory was not found.',
|
||||
);
|
||||
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
// Unifying the error - mkdir() may cause an exception.
|
||||
try {
|
||||
if (! is_dir($targetLocaleDir) && ! mkdir($targetLocaleDir, 0775)) {
|
||||
throw new ErrorException();
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
CLI::error(
|
||||
'Error: The target directory "' . clean_path($targetLocaleDir) . '" cannot be accessed.',
|
||||
);
|
||||
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$originalLocaleDir,
|
||||
FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array<non-empty-string, SplFileInfo> $files
|
||||
*/
|
||||
$files = iterator_to_array($iterator, true);
|
||||
ksort($files);
|
||||
|
||||
foreach ($files as $originalLanguageFile) {
|
||||
if ($originalLanguageFile->getExtension() !== 'php') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$targetLanguageFile = $targetLocaleDir . DIRECTORY_SEPARATOR . $originalLanguageFile->getFilename();
|
||||
|
||||
$targetLanguageKeys = [];
|
||||
$originalLanguageKeys = include $originalLanguageFile;
|
||||
|
||||
if (is_file($targetLanguageFile)) {
|
||||
$targetLanguageKeys = include $targetLanguageFile;
|
||||
}
|
||||
|
||||
$targetLanguageKeys = $this->mergeLanguageKeys($originalLanguageKeys, $targetLanguageKeys, $originalLanguageFile->getBasename('.php'));
|
||||
|
||||
$content = "<?php\n\nreturn " . var_export($targetLanguageKeys, true) . ";\n";
|
||||
file_put_contents($targetLanguageFile, $content);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,mixed>|string|null> $originalLanguageKeys
|
||||
* @param array<string, array<string,mixed>|string|null> $targetLanguageKeys
|
||||
*
|
||||
* @return array<string, array<string,mixed>|string|null>
|
||||
*/
|
||||
private function mergeLanguageKeys(array $originalLanguageKeys, array $targetLanguageKeys, string $prefix = ''): array
|
||||
{
|
||||
$mergedLanguageKeys = [];
|
||||
|
||||
foreach ($originalLanguageKeys as $key => $value) {
|
||||
$placeholderValue = $prefix !== '' ? $prefix . '.' . $key : $key;
|
||||
|
||||
if (is_string($value)) {
|
||||
// Keep the old value
|
||||
// TODO: The value type may not match the original one
|
||||
if (array_key_exists($key, $targetLanguageKeys)) {
|
||||
$mergedLanguageKeys[$key] = $targetLanguageKeys[$key];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set new key with placeholder
|
||||
$mergedLanguageKeys[$key] = $placeholderValue;
|
||||
} elseif (is_array($value)) {
|
||||
if (! array_key_exists($key, $targetLanguageKeys)) {
|
||||
$mergedLanguageKeys[$key] = $this->mergeLanguageKeys($value, [], $placeholderValue);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$mergedLanguageKeys[$key] = $this->mergeLanguageKeys($value, $targetLanguageKeys[$key], $placeholderValue);
|
||||
} else {
|
||||
throw new LogicException('Value for the key "' . $placeholderValue . '" is of the wrong type. Only "array" or "string" is allowed.');
|
||||
}
|
||||
}
|
||||
|
||||
return $mergedLanguageKeys;
|
||||
}
|
||||
}
|
@ -73,13 +73,7 @@ class FilterCheck extends BaseCommand
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
$tbody = [];
|
||||
if (! isset($params[0], $params[1])) {
|
||||
CLI::error('You must specify a HTTP verb and a route.');
|
||||
CLI::write(' Usage: ' . $this->usage);
|
||||
CLI::write('Example: filter:check GET /');
|
||||
CLI::write(' filter:check PUT products/1');
|
||||
|
||||
if (! $this->checkParams($params)) {
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
@ -107,15 +101,38 @@ class FilterCheck extends BaseCommand
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
$filters = $this->addRequiredFilters($filterCollector, $filters);
|
||||
$this->showTable($filterCollector, $filters, $method, $route);
|
||||
$this->showFilterClasses($filterCollector, $method, $route);
|
||||
|
||||
$tbody[] = [
|
||||
strtoupper($method),
|
||||
$route,
|
||||
implode(' ', $filters['before']),
|
||||
implode(' ', $filters['after']),
|
||||
];
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, string|null> $params
|
||||
*/
|
||||
private function checkParams(array $params): bool
|
||||
{
|
||||
if (! isset($params[0], $params[1])) {
|
||||
CLI::error('You must specify a HTTP verb and a route.');
|
||||
CLI::write(' Usage: ' . $this->usage);
|
||||
CLI::write('Example: filter:check GET /');
|
||||
CLI::write(' filter:check PUT products/1');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{before: list<string>, after: list<string>} $filters
|
||||
*/
|
||||
private function showTable(
|
||||
FilterCollector $filterCollector,
|
||||
array $filters,
|
||||
string $method,
|
||||
string $route,
|
||||
): void {
|
||||
$thead = [
|
||||
'Method',
|
||||
'Route',
|
||||
@ -123,33 +140,60 @@ class FilterCheck extends BaseCommand
|
||||
'After Filters',
|
||||
];
|
||||
|
||||
CLI::table($tbody, $thead);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
private function addRequiredFilters(FilterCollector $filterCollector, array $filters): array
|
||||
{
|
||||
$output = [];
|
||||
|
||||
$required = $filterCollector->getRequiredFilters();
|
||||
|
||||
$colored = [];
|
||||
$coloredRequired = $this->colorItems($required);
|
||||
|
||||
foreach ($required['before'] as $filter) {
|
||||
$filter = CLI::color($filter, 'yellow');
|
||||
$colored[] = $filter;
|
||||
$before = array_merge($coloredRequired['before'], $filters['before']);
|
||||
$after = array_merge($filters['after'], $coloredRequired['after']);
|
||||
|
||||
$tbody = [];
|
||||
$tbody[] = [
|
||||
strtoupper($method),
|
||||
$route,
|
||||
implode(' ', $before),
|
||||
implode(' ', $after),
|
||||
];
|
||||
|
||||
CLI::table($tbody, $thead);
|
||||
}
|
||||
$output['before'] = array_merge($colored, $filters['before']);
|
||||
|
||||
$colored = [];
|
||||
|
||||
foreach ($required['after'] as $filter) {
|
||||
$filter = CLI::color($filter, 'yellow');
|
||||
$colored[] = $filter;
|
||||
/**
|
||||
* Color all elements of the array.
|
||||
*
|
||||
* @param array<array-key, mixed> $array
|
||||
*
|
||||
* @return array<array-key, mixed>
|
||||
*/
|
||||
private function colorItems(array $array): array
|
||||
{
|
||||
return array_map(function ($item): array|string {
|
||||
if (is_array($item)) {
|
||||
return $this->colorItems($item);
|
||||
}
|
||||
$output['after'] = array_merge($filters['after'], $colored);
|
||||
|
||||
return $output;
|
||||
return CLI::color($item, 'yellow');
|
||||
}, $array);
|
||||
}
|
||||
|
||||
private function showFilterClasses(
|
||||
FilterCollector $filterCollector,
|
||||
string $method,
|
||||
string $route,
|
||||
): void {
|
||||
$requiredFilterClasses = $filterCollector->getRequiredFilterClasses();
|
||||
$filterClasses = $filterCollector->getClasses($method, $route);
|
||||
|
||||
$coloredRequiredFilterClasses = $this->colorItems($requiredFilterClasses);
|
||||
|
||||
$classList = [
|
||||
'before' => array_merge($coloredRequiredFilterClasses['before'], $filterClasses['before']),
|
||||
'after' => array_merge($filterClasses['after'], $coloredRequiredFilterClasses['after']),
|
||||
];
|
||||
|
||||
foreach ($classList as $position => $classes) {
|
||||
CLI::write(ucfirst($position) . ' Filter Classes:', 'cyan');
|
||||
CLI::write(implode(' → ', $classes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,10 +120,10 @@ class Namespaces extends BaseCommand
|
||||
|
||||
private function truncate(string $string, int $max): string
|
||||
{
|
||||
$length = strlen($string);
|
||||
$length = mb_strlen($string);
|
||||
|
||||
if ($length > $max) {
|
||||
return substr($string, 0, $max - 3) . '...';
|
||||
return mb_substr($string, 0, $max - 3) . '...';
|
||||
}
|
||||
|
||||
return $string;
|
||||
|
@ -17,8 +17,8 @@ use CodeIgniter\Autoloader\FileLocator;
|
||||
use CodeIgniter\Autoloader\FileLocatorCached;
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use CodeIgniter\Publisher\Publisher;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Optimize for production.
|
||||
|
@ -14,6 +14,7 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Commands\Utilities;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use CodeIgniter\Security\CheckPhpIni;
|
||||
|
||||
/**
|
||||
@ -41,7 +42,7 @@ final class PhpIniCheck extends BaseCommand
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Check your php.ini values.';
|
||||
protected $description = 'Check your php.ini values in production environment.';
|
||||
|
||||
/**
|
||||
* The Command's usage
|
||||
@ -56,6 +57,7 @@ final class PhpIniCheck extends BaseCommand
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $arguments = [
|
||||
'opcache' => 'Check detail opcache values in production environment.',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -70,7 +72,24 @@ final class PhpIniCheck extends BaseCommand
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
CheckPhpIni::run();
|
||||
if (isset($params[0]) && ! in_array($params[0], array_keys($this->arguments), true)) {
|
||||
CLI::error('You must specify a correct argument.');
|
||||
CLI::write(' Usage: ' . $this->usage);
|
||||
CLI::write(' Example: phpini:check opcache');
|
||||
CLI::write('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);
|
||||
}
|
||||
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
$argument = $params[0] ?? null;
|
||||
|
||||
CheckPhpIni::run(argument: $argument);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -67,17 +67,24 @@ class Publish extends BaseCommand
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $options = [];
|
||||
protected $options = [
|
||||
'--namespace' => 'The namespace from which to search for files to publish. By default, all namespaces are analysed.',
|
||||
];
|
||||
|
||||
/**
|
||||
* Displays the help for the spark cli script itself.
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
$directory = array_shift($params) ?? 'Publishers';
|
||||
$directory = $params[0] ?? 'Publishers';
|
||||
$namespace = $params['namespace'] ?? '';
|
||||
|
||||
if ([] === $publishers = Publisher::discover($directory)) {
|
||||
if ([] === $publishers = Publisher::discover($directory, $namespace)) {
|
||||
if ($namespace === '') {
|
||||
CLI::write(lang('Publisher.publishMissing', [$directory]));
|
||||
} else {
|
||||
CLI::write(lang('Publisher.publishMissingNamespace', [$directory, $namespace]));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ final class FilterCollector
|
||||
* @param string $method HTTP verb like `GET`,`POST` or `CLI`.
|
||||
* @param string $uri URI path to find filters for
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of filter alias or classname
|
||||
* @return array{before: list<string>, after: list<string>} array of alias/classname:args
|
||||
*/
|
||||
public function get(string $method, string $uri): array
|
||||
{
|
||||
@ -78,10 +78,52 @@ final class FilterCollector
|
||||
return $finder->find($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns filter classes for the URI
|
||||
*
|
||||
* @param string $method HTTP verb like `GET`,`POST` or `CLI`.
|
||||
* @param string $uri URI path to find filters for
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of classname:args
|
||||
*/
|
||||
public function getClasses(string $method, string $uri): array
|
||||
{
|
||||
if ($method === strtolower($method)) {
|
||||
@trigger_error(
|
||||
'Passing lowercase HTTP method "' . $method . '" is deprecated.'
|
||||
. ' Use uppercase HTTP method like "' . strtoupper($method) . '".',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 4.5.0
|
||||
* @TODO Remove this in the future.
|
||||
*/
|
||||
$method = strtoupper($method);
|
||||
|
||||
if ($method === 'CLI') {
|
||||
return [
|
||||
'before' => [],
|
||||
'after' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$request = service('incomingrequest', null, false);
|
||||
$request->setMethod($method);
|
||||
|
||||
$router = $this->createRouter($request);
|
||||
$filters = $this->createFilters($request);
|
||||
|
||||
$finder = new FilterFinder($router, $filters);
|
||||
|
||||
return $finder->findClasses($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Required Filters
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of filter alias or classname
|
||||
* @return array{before: list<string>, after: list<string>} array of aliases
|
||||
*/
|
||||
public function getRequiredFilters(): array
|
||||
{
|
||||
@ -96,6 +138,24 @@ final class FilterCollector
|
||||
return $finder->getRequiredFilters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Required Filter class list
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of classnames
|
||||
*/
|
||||
public function getRequiredFilterClasses(): array
|
||||
{
|
||||
$request = service('incomingrequest', null, false);
|
||||
$request->setMethod(Method::GET);
|
||||
|
||||
$router = $this->createRouter($request);
|
||||
$filters = $this->createFilters($request);
|
||||
|
||||
$finder = new FilterFinder($router, $filters);
|
||||
|
||||
return $finder->getRequiredFilterClasses();
|
||||
}
|
||||
|
||||
private function createRouter(Request $request): Router
|
||||
{
|
||||
$routes = service('routes');
|
||||
|
@ -46,23 +46,20 @@ final class FilterFinder
|
||||
/**
|
||||
* @param string $uri URI path to find filters for
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of filter alias or classname
|
||||
* @return array{before: list<string>, after: list<string>} array of alias/classname:args
|
||||
*/
|
||||
public function find(string $uri): array
|
||||
{
|
||||
$this->filters->reset();
|
||||
|
||||
// Add route filters
|
||||
try {
|
||||
// Add route filters
|
||||
$routeFilters = $this->getRouteFilters($uri);
|
||||
|
||||
$this->filters->enableFilters($routeFilters, 'before');
|
||||
|
||||
$oldFilterOrder = config(Feature::class)->oldFilterOrder ?? false;
|
||||
if (! $oldFilterOrder) {
|
||||
$routeFilters = array_reverse($routeFilters);
|
||||
}
|
||||
|
||||
$this->filters->enableFilters($routeFilters, 'after');
|
||||
|
||||
$this->filters->initialize($uri);
|
||||
@ -81,10 +78,66 @@ final class FilterFinder
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri URI path to find filters for
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of classname:args
|
||||
*/
|
||||
public function findClasses(string $uri): array
|
||||
{
|
||||
$this->filters->reset();
|
||||
|
||||
try {
|
||||
// Add route filters
|
||||
$routeFilters = $this->getRouteFilters($uri);
|
||||
$this->filters->enableFilters($routeFilters, 'before');
|
||||
$oldFilterOrder = config(Feature::class)->oldFilterOrder ?? false;
|
||||
if (! $oldFilterOrder) {
|
||||
$routeFilters = array_reverse($routeFilters);
|
||||
}
|
||||
$this->filters->enableFilters($routeFilters, 'after');
|
||||
|
||||
$this->filters->initialize($uri);
|
||||
|
||||
$filterClassList = $this->filters->getFiltersClass();
|
||||
|
||||
$filterClasses = [
|
||||
'before' => [],
|
||||
'after' => [],
|
||||
];
|
||||
|
||||
foreach ($filterClassList['before'] as $classInfo) {
|
||||
$classWithArguments = ($classInfo[1] === []) ? $classInfo[0]
|
||||
: $classInfo[0] . ':' . implode(',', $classInfo[1]);
|
||||
|
||||
$filterClasses['before'][] = $classWithArguments;
|
||||
}
|
||||
|
||||
foreach ($filterClassList['after'] as $classInfo) {
|
||||
$classWithArguments = ($classInfo[1] === []) ? $classInfo[0]
|
||||
: $classInfo[0] . ':' . implode(',', $classInfo[1]);
|
||||
|
||||
$filterClasses['after'][] = $classWithArguments;
|
||||
}
|
||||
|
||||
return $filterClasses;
|
||||
} catch (RedirectException) {
|
||||
return [
|
||||
'before' => [],
|
||||
'after' => [],
|
||||
];
|
||||
} catch (BadRequestException|PageNotFoundException) {
|
||||
return [
|
||||
'before' => ['<unknown>'],
|
||||
'after' => ['<unknown>'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Required Filters
|
||||
*
|
||||
* @return array{before: list<string>, after:list<string>}
|
||||
* @return array{before: list<string>, after:list<string>} array of aliases
|
||||
*/
|
||||
public function getRequiredFilters(): array
|
||||
{
|
||||
@ -96,4 +149,31 @@ final class FilterFinder
|
||||
'after' => $requiredAfter,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Required Filter classes
|
||||
*
|
||||
* @return array{before: list<string>, after:list<string>}
|
||||
*/
|
||||
public function getRequiredFilterClasses(): array
|
||||
{
|
||||
$before = $this->filters->getRequiredClasses('before');
|
||||
$after = $this->filters->getRequiredClasses('after');
|
||||
|
||||
$requiredBefore = [];
|
||||
$requiredAfter = [];
|
||||
|
||||
foreach ($before as $classInfo) {
|
||||
$requiredBefore[] = $classInfo[0];
|
||||
}
|
||||
|
||||
foreach ($after as $classInfo) {
|
||||
$requiredAfter[] = $classInfo[0];
|
||||
}
|
||||
|
||||
return [
|
||||
'before' => $requiredBefore,
|
||||
'after' => $requiredAfter,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ use CodeIgniter\Cookie\Exceptions\CookieException;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Database\ConnectionInterface;
|
||||
use CodeIgniter\Debug\Timer;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use CodeIgniter\Files\Exceptions\FileNotFoundException;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
use CodeIgniter\HTTP\Exceptions\HTTPException;
|
||||
|
@ -11,11 +11,12 @@
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
use CodeIgniter\Exceptions\ConfigException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use Config\Encryption;
|
||||
use Config\Modules;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class BaseConfig
|
||||
@ -45,12 +46,22 @@ class BaseConfig
|
||||
public static bool $override = true;
|
||||
|
||||
/**
|
||||
* Has module discovery happened yet?
|
||||
* Has module discovery completed?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $didDiscovery = false;
|
||||
|
||||
/**
|
||||
* Is module discovery running or not?
|
||||
*/
|
||||
protected static bool $discovering = false;
|
||||
|
||||
/**
|
||||
* The processing Registrar file for error message.
|
||||
*/
|
||||
protected static string $registrarFile = '';
|
||||
|
||||
/**
|
||||
* The modules configuration.
|
||||
*
|
||||
@ -230,10 +241,24 @@ class BaseConfig
|
||||
}
|
||||
|
||||
if (! static::$didDiscovery) {
|
||||
// Discovery must be completed before the first instantiation of any Config class.
|
||||
if (static::$discovering) {
|
||||
throw new ConfigException(
|
||||
'During Auto-Discovery of Registrars,'
|
||||
. ' "' . static::class . '" executes Auto-Discovery again.'
|
||||
. ' "' . clean_path(static::$registrarFile) . '" seems to have bad code.',
|
||||
);
|
||||
}
|
||||
|
||||
static::$discovering = true;
|
||||
|
||||
$locator = service('locator');
|
||||
$registrarsFiles = $locator->search('Config/Registrar.php');
|
||||
|
||||
foreach ($registrarsFiles as $file) {
|
||||
// Saves the file for error message.
|
||||
static::$registrarFile = $file;
|
||||
|
||||
$className = $locator->findQualifiedNameFromPath($file);
|
||||
|
||||
if ($className === false) {
|
||||
@ -244,6 +269,7 @@ class BaseConfig
|
||||
}
|
||||
|
||||
static::$didDiscovery = true;
|
||||
static::$discovering = false;
|
||||
}
|
||||
|
||||
$shortName = (new ReflectionClass($this))->getShortName();
|
||||
|
@ -29,6 +29,7 @@ use CodeIgniter\Debug\Timer;
|
||||
use CodeIgniter\Debug\Toolbar;
|
||||
use CodeIgniter\Email\Email;
|
||||
use CodeIgniter\Encryption\EncrypterInterface;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Filters\Filters;
|
||||
use CodeIgniter\Format\Format;
|
||||
use CodeIgniter\Honeypot\Honeypot;
|
||||
@ -79,7 +80,6 @@ use Config\Session as ConfigSession;
|
||||
use Config\Toolbar as ConfigToolbar;
|
||||
use Config\Validation as ConfigValidation;
|
||||
use Config\View as ConfigView;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Services Configuration file.
|
||||
@ -389,6 +389,15 @@ class BaseService
|
||||
static::$mocks[strtolower($name)] = $mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the service cache.
|
||||
*/
|
||||
public static function resetServicesCache(): void
|
||||
{
|
||||
self::$serviceNames = [];
|
||||
static::$discovered = false;
|
||||
}
|
||||
|
||||
protected static function buildServicesCache(): void
|
||||
{
|
||||
if (! static::$discovered) {
|
||||
|
@ -13,7 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Environment-specific configuration
|
||||
|
@ -14,8 +14,8 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
use CodeIgniter\Database\ConnectionInterface;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Model;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Factories for creating instances.
|
||||
|
@ -58,15 +58,6 @@ interface CloneableCookieInterface extends CookieInterface
|
||||
*/
|
||||
public function withExpired();
|
||||
|
||||
/**
|
||||
* Creates a new Cookie that will virtually never expire from the browser.
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @deprecated See https://github.com/codeigniter4/CodeIgniter4/pull/6413
|
||||
*/
|
||||
public function withNeverExpiring();
|
||||
|
||||
/**
|
||||
* Creates a new Cookie with a new path on the server the cookie is available.
|
||||
*
|
||||
|
@ -15,11 +15,11 @@ namespace CodeIgniter\Cookie;
|
||||
|
||||
use ArrayAccess;
|
||||
use CodeIgniter\Cookie\Exceptions\CookieException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\LogicException;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use Config\Cookie as CookieConfig;
|
||||
use DateTimeInterface;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use ReturnTypeWillChange;
|
||||
|
||||
/**
|
||||
@ -465,18 +465,6 @@ class Cookie implements ArrayAccess, CloneableCookieInterface
|
||||
return $cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated See https://github.com/codeigniter4/CodeIgniter4/pull/6413
|
||||
*/
|
||||
public function withNeverExpiring()
|
||||
{
|
||||
$cookie = clone $this;
|
||||
|
||||
$cookie->expires = Time::now()->getTimestamp() + 5 * YEAR;
|
||||
|
||||
return $cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -159,28 +159,6 @@ class CookieStore implements Countable, IteratorAggregate
|
||||
return $store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches all cookies in store.
|
||||
*
|
||||
* @deprecated Response should dispatch cookies.
|
||||
*/
|
||||
public function dispatch(): void
|
||||
{
|
||||
foreach ($this->cookies as $cookie) {
|
||||
$name = $cookie->getPrefixedName();
|
||||
$value = $cookie->getValue();
|
||||
$options = $cookie->getOptions();
|
||||
|
||||
if ($cookie->isRaw()) {
|
||||
$this->setRawCookie($name, $value, $options);
|
||||
} else {
|
||||
$this->setCookie($name, $value, $options);
|
||||
}
|
||||
}
|
||||
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all cookie instances in store.
|
||||
*
|
||||
@ -232,28 +210,4 @@ class CookieStore implements Countable, IteratorAggregate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracted call to `setrawcookie()` in order to run unit tests on it.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected function setRawCookie(string $name, string $value, array $options): void
|
||||
{
|
||||
setrawcookie($name, $value, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracted call to `setcookie()` in order to run unit tests on it.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected function setCookie(string $name, string $value, array $options): void
|
||||
{
|
||||
setcookie($name, $value, $options);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\DataCaster\Cast;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
|
||||
abstract class BaseCast implements CastInterface
|
||||
{
|
||||
|
@ -14,8 +14,8 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\DataCaster\Cast;
|
||||
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class DatetimeCast
|
||||
@ -43,12 +43,7 @@ class DatetimeCast extends BaseCast
|
||||
/**
|
||||
* @see https://www.php.net/manual/en/datetimeimmutable.createfromformat.php#datetimeimmutable.createfromformat.parameters
|
||||
*/
|
||||
$format = match ($params[0] ?? '') {
|
||||
'' => $helper->dateFormat['datetime'],
|
||||
'ms' => $helper->dateFormat['datetime-ms'],
|
||||
'us' => $helper->dateFormat['datetime-us'],
|
||||
default => throw new InvalidArgumentException('Invalid parameter: ' . $params[0]),
|
||||
};
|
||||
$format = self::getDateTimeFormat($params, $helper);
|
||||
|
||||
return Time::createFromFormat($format, $value);
|
||||
}
|
||||
@ -62,6 +57,29 @@ class DatetimeCast extends BaseCast
|
||||
self::invalidTypeValueError($value);
|
||||
}
|
||||
|
||||
return (string) $value;
|
||||
if (! $helper instanceof BaseConnection) {
|
||||
$message = 'The parameter $helper must be BaseConnection.';
|
||||
|
||||
throw new InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
$format = self::getDateTimeFormat($params, $helper);
|
||||
|
||||
return $value->format($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets DateTime format from the DB connection.
|
||||
*
|
||||
* @param list<string> $params Additional param
|
||||
*/
|
||||
protected static function getDateTimeFormat(array $params, BaseConnection $db): string
|
||||
{
|
||||
return match ($params[0] ?? '') {
|
||||
'' => $db->dateFormat['datetime'],
|
||||
'ms' => $db->dateFormat['datetime-ms'],
|
||||
'us' => $db->dateFormat['datetime-us'],
|
||||
default => throw new InvalidArgumentException('Invalid parameter: ' . $params[0]),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class TimestampCast extends BaseCast
|
||||
self::invalidTypeValueError($value);
|
||||
}
|
||||
|
||||
return Time::createFromTimestamp((int) $value);
|
||||
return Time::createFromTimestamp((int) $value, date_default_timezone_get());
|
||||
}
|
||||
|
||||
public static function set(
|
||||
|
@ -26,7 +26,7 @@ use CodeIgniter\DataCaster\Cast\TimestampCast;
|
||||
use CodeIgniter\DataCaster\Cast\URICast;
|
||||
use CodeIgniter\Entity\Cast\CastInterface as EntityCastInterface;
|
||||
use CodeIgniter\Entity\Exceptions\CastException;
|
||||
use InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
|
||||
final class DataCaster
|
||||
{
|
||||
|
@ -16,9 +16,9 @@ namespace CodeIgniter\Database;
|
||||
use Closure;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Database\Exceptions\DataException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Traits\ConditionalTrait;
|
||||
use Config\Feature;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class BaseBuilder
|
||||
@ -298,7 +298,7 @@ class BaseBuilder
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array|string $tableName tablename or tablenames with or without aliases
|
||||
* @param array|string|TableName $tableName tablename or tablenames with or without aliases
|
||||
*
|
||||
* Examples of $tableName: `mytable`, `jobs j`, `jobs j, users u`, `['jobs j','users u']`
|
||||
*
|
||||
@ -315,14 +315,19 @@ class BaseBuilder
|
||||
*/
|
||||
$this->db = $db;
|
||||
|
||||
if ($tableName instanceof TableName) {
|
||||
$this->tableName = $tableName->getTableName();
|
||||
$this->QBFrom[] = $this->db->escapeIdentifier($tableName);
|
||||
$this->db->addTableAlias($tableName->getAlias());
|
||||
}
|
||||
// If it contains `,`, it has multiple tables
|
||||
if (is_string($tableName) && ! str_contains($tableName, ',')) {
|
||||
elseif (is_string($tableName) && ! str_contains($tableName, ',')) {
|
||||
$this->tableName = $tableName; // @TODO remove alias if exists
|
||||
$this->from($tableName);
|
||||
} else {
|
||||
$this->tableName = '';
|
||||
}
|
||||
|
||||
$this->from($tableName);
|
||||
}
|
||||
|
||||
if ($options !== null && $options !== []) {
|
||||
foreach ($options as $key => $value) {
|
||||
@ -3014,7 +3019,7 @@ class BaseBuilder
|
||||
*
|
||||
* @param array|string $table The table to inspect
|
||||
*
|
||||
* @return string|void
|
||||
* @return string|null
|
||||
*/
|
||||
protected function trackAliases($table)
|
||||
{
|
||||
@ -3023,7 +3028,7 @@ class BaseBuilder
|
||||
$this->trackAliases($t);
|
||||
}
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Does the string contain a comma? If so, we need to separate
|
||||
@ -3038,11 +3043,13 @@ class BaseBuilder
|
||||
$table = preg_replace('/\s+AS\s+/i', ' ', $table);
|
||||
|
||||
// Grab the alias
|
||||
$table = trim(strrchr($table, ' '));
|
||||
$alias = trim(strrchr($table, ' '));
|
||||
|
||||
// Store the alias, if it doesn't already exist
|
||||
$this->db->addTableAlias($table);
|
||||
$this->db->addTableAlias($alias);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -340,7 +340,7 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
/**
|
||||
* Array of table aliases.
|
||||
*
|
||||
* @var array
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $aliasedTables = [];
|
||||
|
||||
@ -576,10 +576,14 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addTableAlias(string $table)
|
||||
public function addTableAlias(string $alias)
|
||||
{
|
||||
if (! in_array($table, $this->aliasedTables, true)) {
|
||||
$this->aliasedTables[] = $table;
|
||||
if ($alias === '') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (! in_array($alias, $this->aliasedTables, true)) {
|
||||
$this->aliasedTables[] = $alias;
|
||||
}
|
||||
|
||||
return $this;
|
||||
@ -897,6 +901,16 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset transaction status - to restart transactions after strict mode failure
|
||||
*/
|
||||
public function resetTransStatus(): static
|
||||
{
|
||||
$this->transStatus = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin Transaction
|
||||
*/
|
||||
@ -915,7 +929,7 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
/**
|
||||
* Returns a non-shared new instance of the query builder for this connection.
|
||||
*
|
||||
* @param array|string $tableName
|
||||
* @param array|string|TableName $tableName
|
||||
*
|
||||
* @return BaseBuilder
|
||||
*
|
||||
@ -1046,7 +1060,7 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
* insert the table prefix (if it exists) in the proper position, and escape only
|
||||
* the correct identifiers.
|
||||
*
|
||||
* @param array|int|string $item
|
||||
* @param array|int|string|TableName $item
|
||||
* @param bool $prefixSingle Prefix a table name with no segments?
|
||||
* @param bool $protectIdentifiers Protect table or column names?
|
||||
* @param bool $fieldExists Supplied $item contains a column name?
|
||||
@ -1070,6 +1084,11 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
return $escapedArray;
|
||||
}
|
||||
|
||||
if ($item instanceof TableName) {
|
||||
/** @psalm-suppress NoValue I don't know why ERROR. */
|
||||
return $this->escapeTableName($item);
|
||||
}
|
||||
|
||||
// If you pass `['column1', 'column2']`, `$item` will be int because the array keys are int.
|
||||
$item = (string) $item;
|
||||
|
||||
@ -1212,10 +1231,18 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
*
|
||||
* This function escapes single identifier.
|
||||
*
|
||||
* @param non-empty-string $item
|
||||
* @param non-empty-string|TableName $item
|
||||
*/
|
||||
public function escapeIdentifier(string $item): string
|
||||
public function escapeIdentifier($item): string
|
||||
{
|
||||
if ($item === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($item instanceof TableName) {
|
||||
return $this->escapeTableName($item);
|
||||
}
|
||||
|
||||
return $this->escapeChar
|
||||
. str_replace(
|
||||
$this->escapeChar,
|
||||
@ -1225,6 +1252,17 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
. $this->escapeChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns escaped table name with alias.
|
||||
*/
|
||||
private function escapeTableName(TableName $tableName): string
|
||||
{
|
||||
$alias = $tableName->getAlias();
|
||||
|
||||
return $this->escapeIdentifier($tableName->getActualTableName())
|
||||
. (($alias !== '') ? ' ' . $this->escapeIdentifier($alias) : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape the SQL Identifiers
|
||||
*
|
||||
@ -1538,12 +1576,16 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
/**
|
||||
* Fetch Field Names
|
||||
*
|
||||
* @param string|TableName $tableName
|
||||
*
|
||||
* @return false|list<string>
|
||||
*
|
||||
* @throws DatabaseException
|
||||
*/
|
||||
public function getFieldNames(string $table)
|
||||
public function getFieldNames($tableName)
|
||||
{
|
||||
$table = ($tableName instanceof TableName) ? $tableName->getTableName() : $tableName;
|
||||
|
||||
// Is there a cached result?
|
||||
if (isset($this->dataCache['field_names'][$table])) {
|
||||
return $this->dataCache['field_names'][$table];
|
||||
@ -1553,7 +1595,7 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
if (false === ($sql = $this->_listColumns($table))) {
|
||||
if (false === ($sql = $this->_listColumns($tableName))) {
|
||||
if ($this->DBDebug) {
|
||||
throw new DatabaseException('This feature is not available for the database you are using.');
|
||||
}
|
||||
@ -1769,9 +1811,11 @@ abstract class BaseConnection implements ConnectionInterface
|
||||
/**
|
||||
* Generates a platform-specific query string so that the column names can be fetched.
|
||||
*
|
||||
* @param string|TableName $table
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
abstract protected function _listColumns(string $table = '');
|
||||
abstract protected function _listColumns($table = '');
|
||||
|
||||
/**
|
||||
* Platform-specific field data information.
|
||||
|
@ -14,9 +14,9 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Database;
|
||||
|
||||
use ArgumentCountError;
|
||||
use BadMethodCallException;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use ErrorException;
|
||||
|
||||
/**
|
||||
|
@ -14,8 +14,8 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Database;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use Config\Database as DbConfig;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class Config
|
||||
|
@ -15,7 +15,7 @@ namespace CodeIgniter\Database;
|
||||
|
||||
use CodeIgniter\Exceptions\ConfigException;
|
||||
use CodeIgniter\Exceptions\CriticalError;
|
||||
use InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Database Connection Factory
|
||||
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Database\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\DebugTraceableTrait;
|
||||
use RuntimeException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
|
||||
class DataException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
|
@ -14,9 +14,9 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Database\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\HasExitCodeInterface;
|
||||
use Error;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
|
||||
class DatabaseException extends Error implements ExceptionInterface, HasExitCodeInterface
|
||||
class DatabaseException extends RuntimeException implements ExceptionInterface, HasExitCodeInterface
|
||||
{
|
||||
public function getExitCode(): int
|
||||
{
|
||||
|
@ -14,8 +14,8 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Database;
|
||||
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
|
@ -16,10 +16,10 @@ namespace CodeIgniter\Database;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\Exceptions\ConfigException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use Config\Database;
|
||||
use Config\Migrations as MigrationsConfig;
|
||||
use RuntimeException;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,8 @@ namespace CodeIgniter\Database\MySQLi;
|
||||
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use LogicException;
|
||||
use CodeIgniter\Database\TableName;
|
||||
use CodeIgniter\Exceptions\LogicException;
|
||||
use mysqli;
|
||||
use mysqli_result;
|
||||
use mysqli_sql_exception;
|
||||
@ -81,6 +82,16 @@ class Connection extends BaseConnection
|
||||
*/
|
||||
public $numberNative = false;
|
||||
|
||||
/**
|
||||
* Use MYSQLI_CLIENT_FOUND_ROWS
|
||||
*
|
||||
* Whether affectedRows() should return number of rows found,
|
||||
* or number of rows changed, after an UPDATE query.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $foundRows = false;
|
||||
|
||||
/**
|
||||
* Connect to the database.
|
||||
*
|
||||
@ -182,6 +193,10 @@ class Connection extends BaseConnection
|
||||
$clientFlags += MYSQLI_CLIENT_SSL;
|
||||
}
|
||||
|
||||
if ($this->foundRows) {
|
||||
$clientFlags += MYSQLI_CLIENT_FOUND_ROWS;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->mysqli->real_connect(
|
||||
$hostname,
|
||||
@ -408,10 +423,19 @@ class Connection extends BaseConnection
|
||||
|
||||
/**
|
||||
* Generates a platform-specific query string so that the column names can be fetched.
|
||||
*
|
||||
* @param string|TableName $table
|
||||
*/
|
||||
protected function _listColumns(string $table = ''): string
|
||||
protected function _listColumns($table = ''): string
|
||||
{
|
||||
return 'SHOW COLUMNS FROM ' . $this->protectIdentifiers($table, true, null, false);
|
||||
$tableName = $this->protectIdentifiers(
|
||||
$table,
|
||||
true,
|
||||
null,
|
||||
false,
|
||||
);
|
||||
|
||||
return 'SHOW COLUMNS FROM ' . $tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,9 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Database\MySQLi;
|
||||
|
||||
use BadMethodCallException;
|
||||
use CodeIgniter\Database\BasePreparedQuery;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use mysqli;
|
||||
use mysqli_result;
|
||||
use mysqli_sql_exception;
|
||||
|
@ -16,6 +16,7 @@ namespace CodeIgniter\Database\OCI8;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Database\Query;
|
||||
use CodeIgniter\Database\TableName;
|
||||
use ErrorException;
|
||||
use stdClass;
|
||||
|
||||
@ -284,18 +285,25 @@ class Connection extends BaseConnection
|
||||
|
||||
/**
|
||||
* Generates a platform-specific query string so that the column names can be fetched.
|
||||
*
|
||||
* @param string|TableName $table
|
||||
*/
|
||||
protected function _listColumns(string $table = ''): string
|
||||
protected function _listColumns($table = ''): string
|
||||
{
|
||||
if (str_contains($table, '.')) {
|
||||
sscanf($table, '%[^.].%s', $owner, $table);
|
||||
if ($table instanceof TableName) {
|
||||
$tableName = $this->escape(strtoupper($table->getActualTableName()));
|
||||
$owner = $this->username;
|
||||
} elseif (str_contains($table, '.')) {
|
||||
sscanf($table, '%[^.].%s', $owner, $tableName);
|
||||
$tableName = $this->escape(strtoupper($this->DBPrefix . $tableName));
|
||||
} else {
|
||||
$owner = $this->username;
|
||||
$tableName = $this->escape(strtoupper($this->DBPrefix . $table));
|
||||
}
|
||||
|
||||
return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
|
||||
WHERE UPPER(OWNER) = ' . $this->escape(strtoupper($owner)) . '
|
||||
AND UPPER(TABLE_NAME) = ' . $this->escape(strtoupper($this->DBPrefix . $table));
|
||||
AND UPPER(TABLE_NAME) = ' . $tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,9 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Database\OCI8;
|
||||
|
||||
use BadMethodCallException;
|
||||
use CodeIgniter\Database\BasePreparedQuery;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use OCILob;
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ namespace CodeIgniter\Database\Postgre;
|
||||
use CodeIgniter\Database\BaseBuilder;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Database\RawSql;
|
||||
use InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Builder for Postgre
|
||||
|
@ -16,6 +16,7 @@ namespace CodeIgniter\Database\Postgre;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Database\RawSql;
|
||||
use CodeIgniter\Database\TableName;
|
||||
use ErrorException;
|
||||
use PgSql\Connection as PgSqlConnection;
|
||||
use PgSql\Result as PgSqlResult;
|
||||
@ -305,13 +306,20 @@ class Connection extends BaseConnection
|
||||
|
||||
/**
|
||||
* Generates a platform-specific query string so that the column names can be fetched.
|
||||
*
|
||||
* @param string|TableName $table
|
||||
*/
|
||||
protected function _listColumns(string $table = ''): string
|
||||
protected function _listColumns($table = ''): string
|
||||
{
|
||||
if ($table instanceof TableName) {
|
||||
$tableName = $this->escape($table->getActualTableName());
|
||||
} else {
|
||||
$tableName = $this->escape($this->DBPrefix . strtolower($table));
|
||||
}
|
||||
|
||||
return 'SELECT "column_name"
|
||||
FROM "information_schema"."columns"
|
||||
WHERE LOWER("table_name") = '
|
||||
. $this->escape($this->DBPrefix . strtolower($table))
|
||||
WHERE LOWER("table_name") = ' . $tableName
|
||||
. ' ORDER BY "ordinal_position"';
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Database\Postgre;
|
||||
|
||||
use BadMethodCallException;
|
||||
use CodeIgniter\Database\BasePreparedQuery;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use Exception;
|
||||
use PgSql\Connection as PgSqlConnection;
|
||||
use PgSql\Result as PgSqlResult;
|
||||
|
@ -13,7 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Database;
|
||||
|
||||
use BadMethodCallException;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
|
||||
/**
|
||||
* @template TConnection
|
||||
|
@ -15,6 +15,7 @@ namespace CodeIgniter\Database\SQLSRV;
|
||||
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Database\TableName;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
@ -225,12 +226,20 @@ class Connection extends BaseConnection
|
||||
|
||||
/**
|
||||
* Generates a platform-specific query string so that the column names can be fetched.
|
||||
*
|
||||
* @param string|TableName $table
|
||||
*/
|
||||
protected function _listColumns(string $table = ''): string
|
||||
protected function _listColumns($table = ''): string
|
||||
{
|
||||
if ($table instanceof TableName) {
|
||||
$tableName = $this->escape(strtolower($table->getActualTableName()));
|
||||
} else {
|
||||
$tableName = $this->escape($this->DBPrefix . strtolower($table));
|
||||
}
|
||||
|
||||
return 'SELECT [COLUMN_NAME] '
|
||||
. ' FROM [INFORMATION_SCHEMA].[COLUMNS]'
|
||||
. ' WHERE [TABLE_NAME] = ' . $this->escape($this->DBPrefix . $table)
|
||||
. ' WHERE [TABLE_NAME] = ' . $tableName
|
||||
. ' AND [TABLE_SCHEMA] = ' . $this->escape($this->schema);
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Database\SQLSRV;
|
||||
|
||||
use BadMethodCallException;
|
||||
use CodeIgniter\Database\BasePreparedQuery;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
|
||||
/**
|
||||
* Prepared query for Postgre
|
||||
|
@ -16,7 +16,7 @@ namespace CodeIgniter\Database\SQLite3;
|
||||
use CodeIgniter\Database\BaseBuilder;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Database\RawSql;
|
||||
use InvalidArgumentException;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Builder for SQLite3
|
||||
|
@ -15,6 +15,8 @@ namespace CodeIgniter\Database\SQLite3;
|
||||
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Database\TableName;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use Exception;
|
||||
use SQLite3;
|
||||
use SQLite3Result;
|
||||
@ -55,6 +57,15 @@ class Connection extends BaseConnection
|
||||
*/
|
||||
protected $busyTimeout;
|
||||
|
||||
/**
|
||||
* The setting of the "synchronous" flag
|
||||
*
|
||||
* @var int<0, 3>|null flag
|
||||
*
|
||||
* @see https://www.sqlite.org/pragma.html#pragma_synchronous
|
||||
*/
|
||||
protected ?int $synchronous = null;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
@ -69,6 +80,13 @@ class Connection extends BaseConnection
|
||||
if (is_int($this->busyTimeout)) {
|
||||
$this->connID->busyTimeout($this->busyTimeout);
|
||||
}
|
||||
|
||||
if (is_int($this->synchronous)) {
|
||||
if (! in_array($this->synchronous, [0, 1, 2, 3], true)) {
|
||||
throw new InvalidArgumentException('Invalid synchronous value.');
|
||||
}
|
||||
$this->connID->exec('PRAGMA synchronous = ' . $this->synchronous);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,19 +227,31 @@ class Connection extends BaseConnection
|
||||
|
||||
/**
|
||||
* Generates a platform-specific query string so that the column names can be fetched.
|
||||
*
|
||||
* @param string|TableName $table
|
||||
*/
|
||||
protected function _listColumns(string $table = ''): string
|
||||
protected function _listColumns($table = ''): string
|
||||
{
|
||||
return 'PRAGMA TABLE_INFO(' . $this->protectIdentifiers($table, true, null, false) . ')';
|
||||
if ($table instanceof TableName) {
|
||||
$tableName = $this->escapeIdentifier($table);
|
||||
} else {
|
||||
$tableName = $this->protectIdentifiers($table, true, null, false);
|
||||
}
|
||||
|
||||
return 'PRAGMA TABLE_INFO(' . $tableName . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|TableName $tableName
|
||||
*
|
||||
* @return false|list<string>
|
||||
*
|
||||
* @throws DatabaseException
|
||||
*/
|
||||
public function getFieldNames(string $table)
|
||||
public function getFieldNames($tableName)
|
||||
{
|
||||
$table = ($tableName instanceof TableName) ? $tableName->getTableName() : $tableName;
|
||||
|
||||
// Is there a cached result?
|
||||
if (isset($this->dataCache['field_names'][$table])) {
|
||||
return $this->dataCache['field_names'][$table];
|
||||
@ -231,7 +261,7 @@ class Connection extends BaseConnection
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
$sql = $this->_listColumns($table);
|
||||
$sql = $this->_listColumns($tableName);
|
||||
|
||||
$query = $this->query($sql);
|
||||
$this->dataCache['field_names'][$table] = [];
|
||||
|
@ -13,9 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Database\SQLite3;
|
||||
|
||||
use BadMethodCallException;
|
||||
use CodeIgniter\Database\BasePreparedQuery;
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Exceptions\BadMethodCallException;
|
||||
use Exception;
|
||||
use SQLite3;
|
||||
use SQLite3Result;
|
||||
|
@ -14,10 +14,10 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Database;
|
||||
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use Config\Database;
|
||||
use Faker\Factory;
|
||||
use Faker\Generator;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class Seeder
|
||||
|
135
system/Database/TableName.php
Normal file
135
system/Database/TableName.php
Normal file
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Database;
|
||||
|
||||
/**
|
||||
* Represents a table name in SQL.
|
||||
*
|
||||
* @interal
|
||||
*
|
||||
* @see \CodeIgniter\Database\TableNameTest
|
||||
*/
|
||||
class TableName
|
||||
{
|
||||
/**
|
||||
* @param string $actualTable Actual table name
|
||||
* @param string $logicalTable Logical table name (w/o DB prefix)
|
||||
* @param string $schema Schema name
|
||||
* @param string $database Database name
|
||||
* @param string $alias Alias name
|
||||
*/
|
||||
protected function __construct(
|
||||
private readonly string $actualTable,
|
||||
private readonly string $logicalTable = '',
|
||||
private readonly string $schema = '',
|
||||
private readonly string $database = '',
|
||||
private readonly string $alias = '',
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param string $table Table name (w/o DB prefix)
|
||||
* @param string $alias Alias name
|
||||
*/
|
||||
public static function create(string $dbPrefix, string $table, string $alias = ''): self
|
||||
{
|
||||
return new self(
|
||||
$dbPrefix . $table,
|
||||
$table,
|
||||
'',
|
||||
'',
|
||||
$alias,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance from an actual table name.
|
||||
*
|
||||
* @param string $actualTable Actual table name with DB prefix
|
||||
* @param string $alias Alias name
|
||||
*/
|
||||
public static function fromActualName(string $dbPrefix, string $actualTable, string $alias = ''): self
|
||||
{
|
||||
$prefix = $dbPrefix;
|
||||
$logicalTable = '';
|
||||
|
||||
if (str_starts_with($actualTable, $prefix)) {
|
||||
$logicalTable = substr($actualTable, strlen($prefix));
|
||||
}
|
||||
|
||||
return new self(
|
||||
$actualTable,
|
||||
$logicalTable,
|
||||
'',
|
||||
$alias,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance from full name.
|
||||
*
|
||||
* @param string $table Table name (w/o DB prefix)
|
||||
* @param string $schema Schema name
|
||||
* @param string $database Database name
|
||||
* @param string $alias Alias name
|
||||
*/
|
||||
public static function fromFullName(
|
||||
string $dbPrefix,
|
||||
string $table,
|
||||
string $schema = '',
|
||||
string $database = '',
|
||||
string $alias = '',
|
||||
): self {
|
||||
return new self(
|
||||
$dbPrefix . $table,
|
||||
$table,
|
||||
$schema,
|
||||
$database,
|
||||
$alias,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the single segment table name w/o DB prefix.
|
||||
*/
|
||||
public function getTableName(): string
|
||||
{
|
||||
return $this->logicalTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual single segment table name w/z DB prefix.
|
||||
*/
|
||||
public function getActualTableName(): string
|
||||
{
|
||||
return $this->actualTable;
|
||||
}
|
||||
|
||||
public function getAlias(): string
|
||||
{
|
||||
return $this->alias;
|
||||
}
|
||||
|
||||
public function getSchema(): string
|
||||
{
|
||||
return $this->schema;
|
||||
}
|
||||
|
||||
public function getDatabase(): string
|
||||
{
|
||||
return $this->database;
|
||||
}
|
||||
}
|
@ -75,8 +75,10 @@ final class ExceptionHandler extends BaseExceptionHandler implements ExceptionHa
|
||||
);
|
||||
}
|
||||
|
||||
// Handles non-HTML requests.
|
||||
if (! str_contains($request->getHeaderLine('accept'), 'text/html')) {
|
||||
$data = (ENVIRONMENT === 'development' || ENVIRONMENT === 'testing')
|
||||
// If display_errors is enabled, shows the error details.
|
||||
$data = $this->isDisplayErrorsEnabled()
|
||||
? $this->collectVars($exception, $statusCode)
|
||||
: '';
|
||||
|
||||
@ -134,13 +136,8 @@ final class ExceptionHandler extends BaseExceptionHandler implements ExceptionHa
|
||||
// Production environments should have a custom exception file.
|
||||
$view = 'production.php';
|
||||
|
||||
if (
|
||||
in_array(
|
||||
strtolower(ini_get('display_errors')),
|
||||
['1', 'true', 'on', 'yes'],
|
||||
true,
|
||||
)
|
||||
) {
|
||||
if ($this->isDisplayErrorsEnabled()) {
|
||||
// If display_errors is enabled, shows the error details.
|
||||
$view = 'error_exception.php';
|
||||
}
|
||||
|
||||
@ -158,4 +155,13 @@ final class ExceptionHandler extends BaseExceptionHandler implements ExceptionHa
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
private function isDisplayErrorsEnabled(): bool
|
||||
{
|
||||
return in_array(
|
||||
strtolower(ini_get('display_errors')),
|
||||
['1', 'true', 'on', 'yes'],
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +208,14 @@ class Exceptions
|
||||
public function errorHandler(int $severity, string $message, ?string $file = null, ?int $line = null)
|
||||
{
|
||||
if ($this->isDeprecationError($severity)) {
|
||||
if ($this->isSessionSidDeprecationError($message, $file, $line)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->isImplicitNullableDeprecationError($message, $file, $line)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! $this->config->logDeprecations || (bool) env('CODEIGNITER_SCREAM_DEPRECATIONS')) {
|
||||
throw new ErrorException($message, 0, $severity, $file, $line);
|
||||
}
|
||||
@ -222,6 +230,64 @@ class Exceptions
|
||||
return false; // return false to propagate the error to PHP standard error handler
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles session.sid_length and session.sid_bits_per_character deprecations
|
||||
* in PHP 8.4.
|
||||
*/
|
||||
private function isSessionSidDeprecationError(string $message, ?string $file = null, ?int $line = null): bool
|
||||
{
|
||||
if (
|
||||
PHP_VERSION_ID >= 80400
|
||||
&& str_contains($message, 'session.sid_')
|
||||
) {
|
||||
log_message(
|
||||
LogLevel::WARNING,
|
||||
'[DEPRECATED] {message} in {errFile} on line {errLine}.',
|
||||
[
|
||||
'message' => $message,
|
||||
'errFile' => clean_path($file ?? ''),
|
||||
'errLine' => $line ?? 0,
|
||||
],
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround to implicit nullable deprecation errors in PHP 8.4.
|
||||
*
|
||||
* "Implicitly marking parameter $xxx as nullable is deprecated,
|
||||
* the explicit nullable type must be used instead"
|
||||
*
|
||||
* @TODO remove this before v4.6.0 release
|
||||
*/
|
||||
private function isImplicitNullableDeprecationError(string $message, ?string $file = null, ?int $line = null): bool
|
||||
{
|
||||
if (
|
||||
PHP_VERSION_ID >= 80400
|
||||
&& str_contains($message, 'the explicit nullable type must be used instead')
|
||||
// Only Kint and Faker, which cause this error, are logged.
|
||||
&& (str_starts_with($message, 'Kint\\') || str_starts_with($message, 'Faker\\'))
|
||||
) {
|
||||
log_message(
|
||||
LogLevel::WARNING,
|
||||
'[DEPRECATED] {message} in {errFile} on line {errLine}.',
|
||||
[
|
||||
'message' => $message,
|
||||
'errFile' => clean_path($file ?? ''),
|
||||
'errLine' => $line ?? 0,
|
||||
],
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if any errors have happened during shutdown that
|
||||
* need to be caught and handle them.
|
||||
|
@ -13,7 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Debug;
|
||||
|
||||
use RuntimeException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class Timer
|
||||
|
@ -14,13 +14,12 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Encryption\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\DebugTraceableTrait;
|
||||
use CodeIgniter\Exceptions\ExceptionInterface;
|
||||
use RuntimeException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
|
||||
/**
|
||||
* Encryption exception
|
||||
*/
|
||||
class EncryptionException extends RuntimeException implements ExceptionInterface
|
||||
class EncryptionException extends RuntimeException
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
|
@ -40,7 +40,7 @@ class DatetimeCast extends BaseCast
|
||||
}
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return Time::createFromTimestamp((int) $value);
|
||||
return Time::createFromTimestamp((int) $value, date_default_timezone_get());
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
|
22
system/Exceptions/BadFunctionCallException.php
Normal file
22
system/Exceptions/BadFunctionCallException.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception thrown if a function is called in the wrong way, or the function
|
||||
* does not exist.
|
||||
*/
|
||||
class BadFunctionCallException extends \BadFunctionCallException implements ExceptionInterface
|
||||
{
|
||||
}
|
22
system/Exceptions/BadMethodCallException.php
Normal file
22
system/Exceptions/BadMethodCallException.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception thrown if a method is called in the wrong way, or the method
|
||||
* does not exist.
|
||||
*/
|
||||
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
|
||||
{
|
||||
}
|
@ -14,9 +14,10 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception for automatic logging.
|
||||
* Exception thrown if the value of the Config class is invalid or the type is
|
||||
* incorrect.
|
||||
*/
|
||||
class ConfigException extends CriticalError implements HasExitCodeInterface
|
||||
class ConfigException extends RuntimeException implements HasExitCodeInterface
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
|
@ -13,11 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
use Error;
|
||||
|
||||
/**
|
||||
* Error: Critical conditions, like component unavailable, etc.
|
||||
*/
|
||||
class CriticalError extends Error
|
||||
class CriticalError extends RuntimeException
|
||||
{
|
||||
}
|
||||
|
@ -13,12 +13,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class DownloadException
|
||||
*/
|
||||
class DownloadException extends RuntimeException implements ExceptionInterface
|
||||
class DownloadException extends RuntimeException
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
|
@ -13,15 +13,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class FrameworkException
|
||||
*
|
||||
* A collection of exceptions thrown by the framework
|
||||
* that can only be determined at run time.
|
||||
*/
|
||||
class FrameworkException extends RuntimeException implements ExceptionInterface
|
||||
class FrameworkException extends RuntimeException
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
|
@ -16,6 +16,6 @@ namespace CodeIgniter\Exceptions;
|
||||
/**
|
||||
* Interface for Exceptions that has exception code as HTTP status code.
|
||||
*/
|
||||
interface HTTPExceptionInterface
|
||||
interface HTTPExceptionInterface extends ExceptionInterface
|
||||
{
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace CodeIgniter\Exceptions;
|
||||
/**
|
||||
* Interface for Exceptions that has exception code as exit code.
|
||||
*/
|
||||
interface HasExitCodeInterface
|
||||
interface HasExitCodeInterface extends ExceptionInterface
|
||||
{
|
||||
/**
|
||||
* Returns exit status code.
|
||||
|
21
system/Exceptions/InvalidArgumentException.php
Normal file
21
system/Exceptions/InvalidArgumentException.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception thrown if an argument is not of the expected type.
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
21
system/Exceptions/LogicException.php
Normal file
21
system/Exceptions/LogicException.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception that represents error in the program logic.
|
||||
*/
|
||||
class LogicException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
@ -13,9 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
use OutOfBoundsException;
|
||||
|
||||
class PageNotFoundException extends OutOfBoundsException implements ExceptionInterface, HTTPExceptionInterface
|
||||
class PageNotFoundException extends RuntimeException implements HTTPExceptionInterface
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
|
21
system/Exceptions/RuntimeException.php
Normal file
21
system/Exceptions/RuntimeException.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception thrown if an error which can only be found on runtime occurs.
|
||||
*/
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
@ -14,9 +14,9 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception for automatic logging.
|
||||
* Exception thrown when there is an error with the test code.
|
||||
*/
|
||||
class TestException extends CriticalError
|
||||
class TestException extends LogicException
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
|
24
system/Files/Exceptions/ExceptionInterface.php
Normal file
24
system/Files/Exceptions/ExceptionInterface.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Files\Exceptions;
|
||||
|
||||
/**
|
||||
* Provides a domain-level interface for broad capture
|
||||
* of all Files-related exceptions.
|
||||
*
|
||||
* catch (\CodeIgniter\Files\Exceptions\ExceptionInterface) { ... }
|
||||
*/
|
||||
interface ExceptionInterface extends \CodeIgniter\Exceptions\ExceptionInterface
|
||||
{
|
||||
}
|
@ -14,8 +14,7 @@ declare(strict_types=1);
|
||||
namespace CodeIgniter\Files\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\DebugTraceableTrait;
|
||||
use CodeIgniter\Exceptions\ExceptionInterface;
|
||||
use RuntimeException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
|
||||
class FileException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user