Merge pull request #8354 from kenjis/rector-upgrade-php81-CI45

refactor: upgrade to PHP 8.1 with rector
This commit is contained in:
kenjis 2024-04-07 12:36:19 +09:00 committed by GitHub
commit 77cbf2cd31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
149 changed files with 600 additions and 898 deletions

View File

@ -3,7 +3,7 @@
use CodeIgniter\CLI\CLI;
// The main Exception
CLI::write('[' . get_class($exception) . ']', 'light_gray', 'red');
CLI::write('[' . $exception::class . ']', 'light_gray', 'red');
CLI::write($message);
CLI::write('at ' . CLI::color(clean_path($exception->getFile()) . ':' . $exception->getLine(), 'green'));
CLI::newLine();
@ -14,7 +14,7 @@ while ($prevException = $last->getPrevious()) {
$last = $prevException;
CLI::write(' Caused by:');
CLI::write(' [' . get_class($prevException) . ']', 'red');
CLI::write(' [' . $prevException::class . ']', 'red');
CLI::write(' ' . $prevException->getMessage());
CLI::write(' at ' . CLI::color(clean_path($prevException->getFile()) . ':' . $prevException->getLine(), 'green'));
CLI::newLine();
@ -50,20 +50,11 @@ if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) {
$function .= $padClass . $error['function'];
}
$args = implode(', ', array_map(static function ($value) {
switch (true) {
case is_object($value):
return 'Object(' . get_class($value) . ')';
case is_array($value):
return count($value) ? '[...]' : '[]';
case $value === null:
return 'null'; // return the lowercased version
default:
return var_export($value, true);
}
$args = implode(', ', array_map(static fn ($value) => match (true) {
is_object($value) => 'Object(' . $value::class . ')',
is_array($value) => count($value) ? '[...]' : '[]',
$value === null => 'null', // return the lowercased version
default => var_export($value, true),
}, array_values($error['args'] ?? [])));
$function .= '(' . $args . ')';

View File

@ -61,10 +61,10 @@ $errorId = uniqid('error', true);
<pre>
Caused by:
<?= esc(get_class($prevException)), esc($prevException->getCode() ? ' #' . $prevException->getCode() : '') ?>
<?= esc($prevException::class), esc($prevException->getCode() ? ' #' . $prevException->getCode() : '') ?>
<?= nl2br(esc($prevException->getMessage())) ?>
<a href="https://www.duckduckgo.com/?q=<?= urlencode(get_class($prevException) . ' ' . preg_replace('#\'.*\'|".*"#Us', '', $prevException->getMessage())) ?>"
<a href="https://www.duckduckgo.com/?q=<?= urlencode($prevException::class . ' ' . preg_replace('#\'.*\'|".*"#Us', '', $prevException->getMessage())) ?>"
rel="noreferrer" target="_blank">search &rarr;</a>
<?= esc(clean_path($prevException->getFile()) . ':' . $prevException->getLine()) ?>
</pre>
@ -121,7 +121,7 @@ $errorId = uniqid('error', true);
<?php
$params = null;
// Reflection by name is not available for closure function
if (substr($row['function'], -1) !== '}') {
if (! str_ends_with($row['function'], '}')) {
$mirror = isset($row['class']) ? new ReflectionMethod($row['class'], $row['function']) : new ReflectionFunction($row['function']);
$params = $mirror->getParameters();
}

View File

@ -1341,11 +1341,6 @@ $ignoreErrors[] = [
'count' => 1,
'path' => __DIR__ . '/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php',
];
$ignoreErrors[] = [
'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\AutoRouterImproved\\\\AutoRouteCollector\\:\\:__construct\\(\\) has parameter \\$protectedControllers with no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php',
];
$ignoreErrors[] = [
'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\AutoRouterImproved\\\\AutoRouteCollector\\:\\:addFilters\\(\\) has no return type specified\\.$#',
'count' => 1,
@ -1361,16 +1356,6 @@ $ignoreErrors[] = [
'count' => 1,
'path' => __DIR__ . '/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php',
];
$ignoreErrors[] = [
'message' => '#^Property CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\AutoRouterImproved\\\\AutoRouteCollector\\:\\:\\$httpMethods type has no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php',
];
$ignoreErrors[] = [
'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\AutoRouterImproved\\\\ControllerMethodReader\\:\\:__construct\\(\\) has parameter \\$httpMethods with no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/system/Commands/Utilities/Routes/AutoRouterImproved/ControllerMethodReader.php',
];
$ignoreErrors[] = [
'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\AutoRouterImproved\\\\ControllerMethodReader\\:\\:getParameters\\(\\) return type has no value type specified in iterable type array\\.$#',
'count' => 1,
@ -7561,11 +7546,6 @@ $ignoreErrors[] = [
'count' => 1,
'path' => __DIR__ . '/system/RESTful/ResourceController.php',
];
$ignoreErrors[] = [
'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouter\\:\\:__construct\\(\\) has parameter \\$cliRoutes with no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/system/Router/AutoRouter.php',
];
$ignoreErrors[] = [
'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouter\\:\\:getRoute\\(\\) return type has no value type specified in iterable type array\\.$#',
'count' => 1,
@ -11841,11 +11821,6 @@ $ignoreErrors[] = [
'count' => 1,
'path' => __DIR__ . '/tests/system/CommonSingleServiceTest.php',
];
$ignoreErrors[] = [
'message' => '#^Parameter \\#1 \\$expected of method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) expects class\\-string\\<object\\>, false given\\.$#',
'count' => 2,
'path' => __DIR__ . '/tests/system/CommonSingleServiceTest.php',
];
$ignoreErrors[] = [
'message' => '#^Accessing offset \'BAR\' directly on \\$_SERVER is discouraged\\.$#',
'count' => 1,

View File

@ -46,6 +46,10 @@ use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
use Rector\Php70\Rector\FuncCall\RandomFunctionRector;
use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector;
use Rector\Php80\Rector\Class_\AnnotationToAttributeRector;
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
use Rector\Php80\Rector\FunctionLike\MixedTypeRector;
use Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector;
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
use Rector\PHPUnit\AnnotationsToAttributes\Rector\Class_\AnnotationWithValueToAttributeRector;
use Rector\PHPUnit\AnnotationsToAttributes\Rector\Class_\CoversAnnotationWithValueToAttributeRector;
use Rector\PHPUnit\AnnotationsToAttributes\Rector\ClassMethod\DataProviderAnnotationToAttributeRector;
@ -57,6 +61,7 @@ use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector;
use Rector\Strict\Rector\If_\BooleanInIfConditionRuleFixerRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector;
use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector;
use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector;
use Utils\Rector\PassStrictParameterToFunctionParameterRector;
@ -66,7 +71,7 @@ use Utils\Rector\UnderscoreToCamelCaseVariableNameRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([
SetList::DEAD_CODE,
LevelSetList::UP_TO_PHP_74,
LevelSetList::UP_TO_PHP_81,
PHPUnitSetList::PHPUNIT_CODE_QUALITY,
PHPUnitSetList::PHPUNIT_100,
]);
@ -155,6 +160,49 @@ return static function (RectorConfig $rectorConfig): void {
SimplifyRegexPatternRector::class,
// PHP 8.0 features but cause breaking changes
ClassPropertyAssignToConstructorPromotionRector::class => [
__DIR__ . '/system/Database/BaseResult.php',
__DIR__ . '/system/Database/RawSql.php',
__DIR__ . '/system/Debug/BaseExceptionHandler.php',
__DIR__ . '/system/Filters/Filters.php',
__DIR__ . '/system/HTTP/CURLRequest.php',
__DIR__ . '/system/HTTP/DownloadResponse.php',
__DIR__ . '/system/HTTP/IncomingRequest.php',
__DIR__ . '/system/Security/Security.php',
__DIR__ . '/system/Session/Session.php',
],
MixedTypeRector::class,
// PHP 8.1 features but cause breaking changes
FinalizePublicClassConstantRector::class => [
__DIR__ . '/system/Cache/Handlers/BaseHandler.php',
__DIR__ . '/system/Cache/Handlers/FileHandler.php',
__DIR__ . '/system/CodeIgniter.php',
__DIR__ . '/system/Events/Events.php',
__DIR__ . '/system/Log/Handlers/ChromeLoggerHandler.php',
__DIR__ . '/system/Log/Handlers/ErrorlogHandler.php',
__DIR__ . '/system/Security/Security.php',
],
ReturnNeverTypeRector::class => [
__DIR__ . '/system/Cache/Handlers/BaseHandler.php',
__DIR__ . '/system/Cache/Handlers/MemcachedHandler.php',
__DIR__ . '/system/Cache/Handlers/WincacheHandler.php',
__DIR__ . '/system/CodeIgniter.php',
__DIR__ . '/system/Database/MySQLi/Utils.php',
__DIR__ . '/system/Database/OCI8/Utils.php',
__DIR__ . '/system/Database/Postgre/Utils.php',
__DIR__ . '/system/Database/SQLSRV/Utils.php',
__DIR__ . '/system/Database/SQLite3/Utils.php',
__DIR__ . '/system/HTTP/DownloadResponse.php',
__DIR__ . '/system/HTTP/SiteURI.php',
__DIR__ . '/system/Helpers/kint_helper.php',
__DIR__ . '/tests/_support/Autoloader/FatalLocator.php',
],
// Unnecessary (string) is inserted
NullToStrictStringFuncCallArgRector::class,
// PHPUnit 10 (requires PHP 8.1) features
DataProviderAnnotationToAttributeRector::class,
DependsAnnotationWithValueToAttributeRector::class,

View File

@ -163,10 +163,10 @@ class Autoloader
public function register()
{
// Register classmap loader for the files in our class map.
spl_autoload_register([$this, 'loadClassmap'], true);
spl_autoload_register($this->loadClassmap(...), true);
// Register the PSR-4 autoloader.
spl_autoload_register([$this, 'loadClass'], true);
spl_autoload_register($this->loadClass(...), true);
// Load our non-class files
foreach ($this->files as $file) {
@ -181,8 +181,8 @@ class Autoloader
*/
public function unregister(): void
{
spl_autoload_unregister([$this, 'loadClass']);
spl_autoload_unregister([$this, 'loadClassmap']);
spl_autoload_unregister($this->loadClass(...));
spl_autoload_unregister($this->loadClassmap(...));
}
/**
@ -281,12 +281,12 @@ class Autoloader
*/
protected function loadInNamespace(string $class)
{
if (strpos($class, '\\') === false) {
if (! str_contains($class, '\\')) {
return false;
}
foreach ($this->prefixes as $namespace => $directories) {
if (strpos($class, $namespace) === 0) {
if (str_starts_with($class, $namespace)) {
$relativeClassPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, strlen($namespace)));
foreach ($directories as $directory) {
@ -425,7 +425,7 @@ class Autoloader
foreach ($srcPaths as $path) {
foreach ($installPaths as $installPath) {
if ($installPath === substr($path, 0, strlen($installPath))) {
if (str_starts_with($path, $installPath)) {
$add = true;
break 2;
}

View File

@ -53,12 +53,12 @@ class FileLocator implements FileLocatorInterface
$file = $this->ensureExt($file, $ext);
// Clears the folder name if it is at the beginning of the filename
if ($folder !== null && strpos($file, $folder) === 0) {
if ($folder !== null && str_starts_with($file, $folder)) {
$file = substr($file, strlen($folder . '/'));
}
// Is not namespaced? Try the application folder.
if (strpos($file, '\\') === false) {
if (! str_contains($file, '\\')) {
return $this->legacyLocate($file, $folder);
}
@ -103,7 +103,7 @@ class FileLocator implements FileLocatorInterface
// If we have a folder name, then the calling function
// expects this file to be within that folder, like 'Views',
// or 'libraries'.
if ($folder !== null && strpos($path . $filename, '/' . $folder . '/') === false) {
if ($folder !== null && ! str_contains($path . $filename, '/' . $folder . '/')) {
$path .= trim($folder, '/') . '/';
}
@ -192,7 +192,7 @@ class FileLocator implements FileLocatorInterface
if ($prioritizeApp) {
$foundPaths[] = $fullPath;
} elseif (strpos($fullPath, APPPATH) === 0) {
} elseif (str_starts_with($fullPath, APPPATH)) {
$appPaths[] = $fullPath;
} else {
$foundPaths[] = $fullPath;
@ -216,7 +216,7 @@ class FileLocator implements FileLocatorInterface
if ($ext !== '') {
$ext = '.' . $ext;
if (substr($path, -strlen($ext)) !== $ext) {
if (! str_ends_with($path, $ext)) {
$path .= $ext;
}
}

View File

@ -23,8 +23,6 @@ use CodeIgniter\Cache\FactoriesCache\FileVarExportHandler;
*/
final class FileLocatorCached implements FileLocatorInterface
{
private FileLocator $locator;
/**
* @var CacheInterface|FileVarExportHandler
*/
@ -51,10 +49,9 @@ final class FileLocatorCached implements FileLocatorInterface
/**
* @param CacheInterface|FileVarExportHandler|null $cache
*/
public function __construct(FileLocator $locator, $cache = null)
public function __construct(private readonly FileLocator $locator, $cache = null)
{
$this->cacheHandler = $cache ?? new FileVarExportHandler();
$this->locator = $locator;
$this->loadCache();
}

View File

@ -634,7 +634,7 @@ abstract class BaseModel
*/
public function findColumn(string $columnName)
{
if (strpos($columnName, ',') !== false) {
if (str_contains($columnName, ',')) {
throw DataException::forFindColumnHaveMultipleColumns();
}
@ -1397,19 +1397,12 @@ abstract class BaseModel
*/
protected function intToDate(int $value)
{
switch ($this->dateFormat) {
case 'int':
return $value;
case 'datetime':
return date($this->db->dateFormat['datetime'], $value);
case 'date':
return date($this->db->dateFormat['date'], $value);
default:
throw ModelException::forNoDateFormat(static::class);
}
return match ($this->dateFormat) {
'int' => $value,
'datetime' => date($this->db->dateFormat['datetime'], $value),
'date' => date($this->db->dateFormat['date'], $value),
default => throw ModelException::forNoDateFormat(static::class),
};
}
/**
@ -1426,19 +1419,12 @@ abstract class BaseModel
*/
protected function timeToDate(Time $value)
{
switch ($this->dateFormat) {
case 'datetime':
return $value->format($this->db->dateFormat['datetime']);
case 'date':
return $value->format($this->db->dateFormat['date']);
case 'int':
return $value->getTimestamp();
default:
return (string) $value;
}
return match ($this->dateFormat) {
'datetime' => $value->format($this->db->dateFormat['datetime']),
'date' => $value->format($this->db->dateFormat['date']),
'int' => $value->getTimestamp(),
default => (string) $value,
};
}
/**

View File

@ -592,7 +592,7 @@ class CLI
$newText = '';
// Detect if color method was already in use with this text
if (strpos($text, "\033[0m") !== false) {
if (str_contains($text, "\033[0m")) {
$pattern = '/\\033\\[0;.+?\\033\\[0m/u';
preg_match_all($pattern, $text, $matches);

View File

@ -183,7 +183,7 @@ class Commands
foreach (array_keys($collection) as $commandName) {
$lev = levenshtein($name, $commandName);
if ($lev <= strlen($commandName) / 3 || strpos($commandName, $name) !== false) {
if ($lev <= strlen($commandName) / 3 || str_contains($commandName, $name)) {
$alternatives[$commandName] = $lev;
}
}

View File

@ -268,7 +268,7 @@ trait GeneratorTrait
// Gets the namespace from input. Don't forget the ending backslash!
$namespace = $this->getNamespace() . '\\';
if (strncmp($class, $namespace, strlen($namespace)) === 0) {
if (str_starts_with($class, $namespace)) {
return $class; // @codeCoverageIgnore
}

View File

@ -21,7 +21,7 @@ class InputOutput
/**
* Is the readline library on the system?
*/
private bool $readlineSupport;
private readonly bool $readlineSupport;
public function __construct()
{

View File

@ -88,22 +88,12 @@ class PredisHandler extends BaseHandler
return null;
}
switch ($data['__ci_type']) {
case 'array':
case 'object':
return unserialize($data['__ci_value']);
case 'boolean':
case 'integer':
case 'double': // Yes, 'double' is returned and NOT 'float'
case 'string':
case 'NULL':
return settype($data['__ci_value'], $data['__ci_type']) ? $data['__ci_value'] : null;
case 'resource':
default:
return null;
}
return match ($data['__ci_type']) {
'array', 'object' => unserialize($data['__ci_value']),
// Yes, 'double' is returned and NOT 'float'
'boolean', 'integer', 'double', 'string', 'NULL' => settype($data['__ci_value'], $data['__ci_type']) ? $data['__ci_value'] : null,
default => null,
};
}
/**

View File

@ -114,22 +114,12 @@ class RedisHandler extends BaseHandler
return null;
}
switch ($data['__ci_type']) {
case 'array':
case 'object':
return unserialize($data['__ci_value']);
case 'boolean':
case 'integer':
case 'double': // Yes, 'double' is returned and NOT 'float'
case 'string':
case 'NULL':
return settype($data['__ci_value'], $data['__ci_type']) ? $data['__ci_value'] : null;
case 'resource':
default:
return null;
}
return match ($data['__ci_type']) {
'array', 'object' => unserialize($data['__ci_value']),
// Yes, 'double' is returned and NOT 'float'
'boolean', 'integer', 'double', 'string', 'NULL' => settype($data['__ci_value'], $data['__ci_type']) ? $data['__ci_value'] : null,
default => null,
};
}
/**

View File

@ -49,12 +49,9 @@ final class ResponseCache
*/
private int $ttl = 0;
private CacheInterface $cache;
public function __construct(CacheConfig $config, CacheInterface $cache)
public function __construct(CacheConfig $config, private readonly CacheInterface $cache)
{
$this->cacheQueryString = $config->cacheQueryString;
$this->cache = $cache;
}
/**

View File

@ -871,7 +871,7 @@ class CodeIgniter
$this->benchmark->start('controller_constructor');
// Is it routed to a Closure?
if (is_object($this->controller) && (get_class($this->controller) === 'Closure')) {
if (is_object($this->controller) && ($this->controller::class === 'Closure')) {
$controller = $this->controller;
return $controller(...$this->router->params());
@ -1049,7 +1049,7 @@ class CodeIgniter
}
// Ignore non-HTML responses
if (strpos($this->response->getHeaderLine('Content-Type'), 'text/html') === false) {
if (! str_contains($this->response->getHeaderLine('Content-Type'), 'text/html')) {
return;
}

View File

@ -109,7 +109,7 @@ class CreateDatabase extends BaseCommand
$config->{$group}['database'] = $name;
if ($name !== ':memory:') {
$dbName = strpos($name, DIRECTORY_SEPARATOR) === false ? WRITEPATH . $name : $name;
$dbName = ! str_contains($name, DIRECTORY_SEPARATOR) ? WRITEPATH . $name : $name;
if (is_file($dbName)) {
CLI::error("Database \"{$dbName}\" already exists.", 'light_gray', 'red');

View File

@ -168,7 +168,7 @@ class GenerateKey extends BaseCommand
$oldFileContents = (string) file_get_contents($envFile);
$replacementKey = "\nencryption.key = {$newKey}";
if (strpos($oldFileContents, 'encryption.key') === false) {
if (! str_contains($oldFileContents, 'encryption.key')) {
return file_put_contents($envFile, $replacementKey, FILE_APPEND) !== false;
}

View File

@ -85,13 +85,13 @@ class Publish extends BaseCommand
foreach ($publishers as $publisher) {
if ($publisher->publish()) {
CLI::write(lang('Publisher.publishSuccess', [
get_class($publisher),
$publisher::class,
count($publisher->getPublished()),
$publisher->getDestination(),
]), 'green');
} else {
CLI::error(lang('Publisher.publishFailure', [
get_class($publisher),
$publisher::class,
$publisher->getDestination(),
]), 'light_gray', 'red');

View File

@ -20,22 +20,11 @@ namespace CodeIgniter\Commands\Utilities\Routes;
*/
final class AutoRouteCollector
{
/**
* @var string namespace to search
*/
private string $namespace;
private string $defaultController;
private string $defaultMethod;
/**
* @param string $namespace namespace to search
*/
public function __construct(string $namespace, string $defaultController, string $defaultMethod)
public function __construct(private readonly string $namespace, private readonly string $defaultController, private readonly string $defaultMethod)
{
$this->namespace = $namespace;
$this->defaultController = $defaultController;
$this->defaultMethod = $defaultMethod;
}
/**

View File

@ -24,43 +24,19 @@ use CodeIgniter\Commands\Utilities\Routes\FilterCollector;
final class AutoRouteCollector
{
/**
* @var string namespace to search
*/
private string $namespace;
private string $defaultController;
private string $defaultMethod;
private array $httpMethods;
/**
* List of controllers in Defined Routes that should not be accessed via Auto-Routing.
*
* @var list<class-string>
*/
private array $protectedControllers;
/**
* @var string URI prefix for Module Routing
*/
private string $prefix;
/**
* @param string $namespace namespace to search
* @param string $namespace namespace to search
* @param list<class-string> $protectedControllers List of controllers in Defined
* Routes that should not be accessed via Auto-Routing.
* @param string $prefix URI prefix for Module Routing
*/
public function __construct(
string $namespace,
string $defaultController,
string $defaultMethod,
array $httpMethods,
array $protectedControllers,
string $prefix = ''
private readonly string $namespace,
private readonly string $defaultController,
private readonly string $defaultMethod,
private readonly array $httpMethods,
private readonly array $protectedControllers,
private string $prefix = ''
) {
$this->namespace = $namespace;
$this->defaultController = $defaultController;
$this->defaultMethod = $defaultMethod;
$this->httpMethods = $httpMethods;
$this->protectedControllers = $protectedControllers;
$this->prefix = $prefix;
}
/**

View File

@ -24,27 +24,17 @@ use ReflectionMethod;
*/
final class ControllerMethodReader
{
/**
* @var string the default namespace
*/
private string $namespace;
private readonly bool $translateURIDashes;
private readonly bool $translateUriToCamelCase;
/**
* @var list<string>
* @param string $namespace the default namespace
* @param list<string> $httpMethods
*/
private array $httpMethods;
private bool $translateURIDashes;
private bool $translateUriToCamelCase;
/**
* @param string $namespace the default namespace
*/
public function __construct(string $namespace, array $httpMethods)
{
$this->namespace = $namespace;
$this->httpMethods = $httpMethods;
public function __construct(
private readonly string $namespace,
private readonly array $httpMethods
) {
$config = config(Routing::class);
$this->translateURIDashes = $config->translateURIDashes;
$this->translateUriToCamelCase = $config->translateUriToCamelCase;
@ -75,7 +65,7 @@ final class ControllerMethodReader
$methodName = $method->getName();
foreach ($this->httpMethods as $httpVerb) {
if (strpos($methodName, strtolower($httpVerb)) === 0) {
if (str_starts_with($methodName, strtolower($httpVerb))) {
// Remove HTTP verb prefix.
$methodInUri = $this->convertMethodNameToUri($httpVerb, $methodName);

View File

@ -22,20 +22,15 @@ use CodeIgniter\Autoloader\FileLocatorInterface;
*/
final class ControllerFinder
{
/**
* @var string namespace to search
*/
private string $namespace;
private FileLocatorInterface $locator;
private readonly FileLocatorInterface $locator;
/**
* @param string $namespace namespace to search
*/
public function __construct(string $namespace)
{
$this->namespace = $namespace;
$this->locator = service('locator');
public function __construct(
private readonly string $namespace
) {
$this->locator = service('locator');
}
/**

View File

@ -23,17 +23,11 @@ use ReflectionMethod;
*/
final class ControllerMethodReader
{
/**
* @var string the default namespace
*/
private string $namespace;
/**
* @param string $namespace the default namespace
*/
public function __construct(string $namespace)
public function __construct(private readonly string $namespace)
{
$this->namespace = $namespace;
}
/**

View File

@ -27,16 +27,14 @@ use Config\Filters as FiltersConfig;
*/
final class FilterCollector
{
/**
* Whether to reset Defined Routes.
*
* If set to true, route filters are not found.
*/
private bool $resetRoutes;
public function __construct(bool $resetRoutes = false)
{
$this->resetRoutes = $resetRoutes;
public function __construct(
/**
* Whether to reset Defined Routes.
*
* If set to true, route filters are not found.
*/
private readonly bool $resetRoutes = false
) {
}
/**

View File

@ -26,8 +26,8 @@ use Config\Feature;
*/
final class FilterFinder
{
private Router $router;
private Filters $filters;
private readonly Router $router;
private readonly Filters $filters;
public function __construct(?Router $router = null, ?Filters $filters = null)
{
@ -67,12 +67,12 @@ final class FilterFinder
$this->filters->initialize($uri);
return $this->filters->getFilters();
} catch (RedirectException $e) {
} catch (RedirectException) {
return [
'before' => [],
'after' => [],
];
} catch (PageNotFoundException $e) {
} catch (PageNotFoundException) {
return [
'before' => ['<unknown>'],
'after' => ['<unknown>'],

View File

@ -23,7 +23,7 @@ use Config\App;
*/
final class SampleURIGenerator
{
private RouteCollection $routes;
private readonly RouteCollection $routes;
/**
* Sample URI path for placeholder.
@ -53,7 +53,7 @@ final class SampleURIGenerator
{
$sampleUri = $routeKey;
if (strpos($routeKey, '{locale}') !== false) {
if (str_contains($routeKey, '{locale}')) {
$sampleUri = str_replace(
'{locale}',
config(App::class)->defaultLocale,

View File

@ -94,29 +94,18 @@ if (! function_exists('clean_path')) {
// Resolve relative paths
try {
$path = realpath($path) ?: $path;
} catch (ErrorException|ValueError $e) {
} catch (ErrorException|ValueError) {
$path = 'error file path: ' . urlencode($path);
}
switch (true) {
case strpos($path, APPPATH) === 0:
return 'APPPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(APPPATH));
case strpos($path, SYSTEMPATH) === 0:
return 'SYSTEMPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(SYSTEMPATH));
case strpos($path, FCPATH) === 0:
return 'FCPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(FCPATH));
case defined('VENDORPATH') && strpos($path, VENDORPATH) === 0:
return 'VENDORPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(VENDORPATH));
case strpos($path, ROOTPATH) === 0:
return 'ROOTPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(ROOTPATH));
default:
return $path;
}
return match (true) {
str_starts_with($path, APPPATH) => 'APPPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(APPPATH)),
str_starts_with($path, SYSTEMPATH) => 'SYSTEMPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(SYSTEMPATH)),
str_starts_with($path, FCPATH) => 'FCPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(FCPATH)),
defined('VENDORPATH') && str_starts_with($path, VENDORPATH) => 'VENDORPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(VENDORPATH)),
str_starts_with($path, ROOTPATH) => 'ROOTPATH' . DIRECTORY_SEPARATOR . substr($path, strlen(ROOTPATH)),
default => $path,
};
}
}
@ -393,21 +382,13 @@ if (! function_exists('env')) {
}
// Handle any boolean values
switch (strtolower($value)) {
case 'true':
return true;
case 'false':
return false;
case 'empty':
return '';
case 'null':
return null;
}
return $value;
return match (strtolower($value)) {
'true' => true,
'false' => false,
'empty' => '',
'null' => null,
default => $value,
};
}
}
@ -602,7 +583,7 @@ if (! function_exists('helper')) {
$appHelper = null;
$localIncludes = [];
if (strpos($filename, '_helper') === false) {
if (! str_contains($filename, '_helper')) {
$filename .= '_helper';
}
@ -613,7 +594,7 @@ if (! function_exists('helper')) {
// If the file is namespaced, we'll just grab that
// file and not search for any others
if (strpos($filename, '\\') !== false) {
if (str_contains($filename, '\\')) {
$path = $loader->locateFile($filename, 'Helpers');
if (empty($path)) {
@ -627,9 +608,9 @@ if (! function_exists('helper')) {
$paths = $loader->search('Helpers/' . $filename);
foreach ($paths as $path) {
if (strpos($path, APPPATH . 'Helpers' . DIRECTORY_SEPARATOR) === 0) {
if (str_starts_with($path, APPPATH . 'Helpers' . DIRECTORY_SEPARATOR)) {
$appHelper = $path;
} elseif (strpos($path, SYSTEMPATH . 'Helpers' . DIRECTORY_SEPARATOR) === 0) {
} elseif (str_starts_with($path, SYSTEMPATH . 'Helpers' . DIRECTORY_SEPARATOR)) {
$systemHelper = $path;
} else {
$localIncludes[] = $path;
@ -1225,7 +1206,7 @@ if (! function_exists('class_basename')) {
*/
function class_basename($class)
{
$class = is_object($class) ? get_class($class) : $class;
$class = is_object($class) ? $class::class : $class;
return basename(str_replace('\\', '/', $class));
}
@ -1244,7 +1225,7 @@ if (! function_exists('class_uses_recursive')) {
function class_uses_recursive($class)
{
if (is_object($class)) {
$class = get_class($class);
$class = $class::class;
}
$results = [];

View File

@ -73,7 +73,7 @@ final class ComposerScripts
foreach (self::$dependencies as $key => $dependency) {
// Kint may be removed.
if (! is_dir($dependency['from']) && strpos($key, 'kint') === 0) {
if (! is_dir($dependency['from']) && str_starts_with($key, 'kint')) {
continue;
}

View File

@ -119,10 +119,10 @@ class BaseConfig
$this->initEnvValue($this->{$property}, $property, $prefix, $shortPrefix);
if ($this instanceof Encryption && $property === 'key') {
if (strpos($this->{$property}, 'hex2bin:') === 0) {
if (str_starts_with($this->{$property}, 'hex2bin:')) {
// Handle hex2bin prefix
$this->{$property} = hex2bin(substr($this->{$property}, 8));
} elseif (strpos($this->{$property}, 'base64:') === 0) {
} elseif (str_starts_with($this->{$property}, 'base64:')) {
// Handle base64 prefix
$this->{$property} = base64_decode(substr($this->{$property}, 7), true);
}

View File

@ -70,12 +70,12 @@ class DotEnv
foreach ($lines as $line) {
// Is it a comment?
if (strpos(trim($line), '#') === 0) {
if (str_starts_with(trim($line), '#')) {
continue;
}
// If there is an equal sign, then we know we are assigning a variable.
if (strpos($line, '=') !== false) {
if (str_contains($line, '=')) {
[$name, $value] = $this->normaliseVariable($line);
$vars[$name] = $value;
$this->setVariable($name, $value);
@ -114,7 +114,7 @@ class DotEnv
public function normaliseVariable(string $name, string $value = ''): array
{
// Split our compound string into its parts.
if (strpos($name, '=') !== false) {
if (str_contains($name, '=')) {
[$name, $value] = explode('=', $name, 2);
}
@ -194,7 +194,7 @@ class DotEnv
*/
protected function resolveNestedVariables(string $value): string
{
if (strpos($value, '$') !== false) {
if (str_contains($value, '$')) {
$value = preg_replace_callback(
'/\${([a-zA-Z0-9_\.]+)}/',
function ($matchedPatterns) {

View File

@ -331,7 +331,7 @@ final class Factories
*/
private static function isNamespaced(string $alias): bool
{
return strpos($alias, '\\') !== false;
return str_contains($alias, '\\');
}
/**
@ -349,10 +349,10 @@ final class Factories
// Special case for Config since its App namespace is actually \Config
if (self::isConfig($options['component'])) {
return strpos($alias, 'Config') === 0;
return str_starts_with($alias, 'Config');
}
return strpos($alias, APP_NAMESPACE) === 0;
return str_starts_with($alias, APP_NAMESPACE);
}
/**
@ -476,7 +476,7 @@ final class Factories
// Force a configuration to exist for this component
self::getOptions($component);
$class = get_class($instance);
$class = $instance::class;
self::$instances[$component][$class] = $instance;
self::$aliases[$component][$alias] = $class;

View File

@ -182,7 +182,7 @@ class Cookie implements ArrayAccess, CloneableCookieInterface
unset($part);
foreach ($parts as $part) {
if (strpos($part, '=') !== false) {
if (str_contains($part, '=')) {
[$attr, $val] = explode('=', $part);
} else {
$attr = $part;
@ -752,11 +752,11 @@ class Cookie implements ArrayAccess, CloneableCookieInterface
*/
protected function validatePrefix(string $prefix, bool $secure, string $path, string $domain): void
{
if (strpos($prefix, '__Secure-') === 0 && ! $secure) {
if (str_starts_with($prefix, '__Secure-') && ! $secure) {
throw CookieException::forInvalidSecurePrefix();
}
if (strpos($prefix, '__Host-') === 0 && (! $secure || $domain !== '' || $path !== '/')) {
if (str_starts_with($prefix, '__Host-') && (! $secure || $domain !== '' || $path !== '/')) {
throw CookieException::forInvalidHostPrefix();
}
}

View File

@ -225,7 +225,7 @@ class CookieStore implements Countable, IteratorAggregate
protected function validateCookies(array $cookies): void
{
foreach ($cookies as $index => $cookie) {
$type = is_object($cookie) ? get_class($cookie) : gettype($cookie);
$type = get_debug_type($cookie);
if (! $cookie instanceof Cookie) {
throw CookieException::forInvalidCookieInstance([static::class, Cookie::class, $type, $index]);

View File

@ -30,7 +30,7 @@ class ArrayCast extends BaseCast implements CastInterface
self::invalidTypeValueError($value);
}
if ((strpos($value, 'a:') === 0 || strpos($value, 's:') === 0)) {
if ((str_starts_with($value, 'a:') || str_starts_with($value, 's:'))) {
$value = unserialize($value, ['allowed_classes' => false]);
}

View File

@ -58,35 +58,24 @@ final class DataCaster
'uri' => URICast::class,
];
/**
* Strict mode? Set to false for casts for Entity.
*/
private readonly bool $strict;
/**
* Helper object.
*/
private readonly ?object $helper;
/**
* @param array<string, class-string>|null $castHandlers Custom convert handlers
* @param array<string, string>|null $types [field => type]
* @param object|null $helper Helper object.
* @param bool $strict Strict mode? Set to false for casts for Entity.
*/
public function __construct(
?array $castHandlers = null,
?array $types = null,
?object $helper = null,
bool $strict = true
private readonly ?object $helper = null,
private readonly bool $strict = true
) {
$this->castHandlers = array_merge($this->castHandlers, $castHandlers);
$this->helper = $helper;
if ($types !== null) {
$this->setTypes($types);
}
$this->strict = $strict;
if ($this->strict) {
foreach ($this->castHandlers as $handler) {
if (

View File

@ -316,7 +316,7 @@ class BaseBuilder
$this->db = $db;
// If it contains `,`, it has multiple tables
if (is_string($tableName) && strpos($tableName, ',') === false) {
if (is_string($tableName) && ! str_contains($tableName, ',')) {
$this->tableName = $tableName; // @TODO remove alias if exists
} else {
$this->tableName = '';
@ -514,7 +514,7 @@ class BaseBuilder
throw DataException::forEmptyInputGiven('Select');
}
if (strpos($select, ',') !== false) {
if (str_contains($select, ',')) {
throw DataException::forInvalidArgument('column name not separated by comma');
}
@ -541,7 +541,7 @@ class BaseBuilder
*/
protected function createAliasFromTable(string $item): string
{
if (strpos($item, '.') !== false) {
if (str_contains($item, '.')) {
$item = explode('.', $item);
return end($item);
@ -577,7 +577,7 @@ class BaseBuilder
}
foreach ((array) $from as $table) {
if (strpos($table, ',') !== false) {
if (str_contains($table, ',')) {
$this->from(explode(',', $table));
} else {
$table = trim($table);
@ -766,7 +766,7 @@ class BaseBuilder
$op = trim(current($op));
// Does the key end with operator?
if (substr($k, -strlen($op)) === $op) {
if (str_ends_with($k, $op)) {
$k = rtrim(substr($k, 0, -strlen($op)));
$op = " {$op}";
} else {
@ -2342,7 +2342,7 @@ class BaseBuilder
*/
protected function removeAlias(string $from): string
{
if (strpos($from, ' ') !== false) {
if (str_contains($from, ' ')) {
// if the alias is written with the AS keyword, remove it
$from = preg_replace('/\s+AS\s+/i', ' ', $from);
@ -3008,12 +3008,12 @@ class BaseBuilder
// Does the string contain a comma? If so, we need to separate
// the string into discreet statements
if (strpos($table, ',') !== false) {
if (str_contains($table, ',')) {
return $this->trackAliases(explode(',', $table));
}
// if a table alias is used we can recognize it by a space
if (strpos($table, ' ') !== false) {
if (str_contains($table, ' ')) {
// if the alias is written with the AS keyword, remove it
$table = preg_replace('/\s+AS\s+/i', ' ', $table);
@ -3158,11 +3158,11 @@ class BaseBuilder
if (! empty($matches[4])) {
$protectIdentifiers = false;
if (strpos($matches[4], '.') !== false) {
if (str_contains($matches[4], '.')) {
$protectIdentifiers = true;
}
if (strpos($matches[4], ':') === false) {
if (! str_contains($matches[4], ':')) {
$matches[4] = $this->db->protectIdentifiers(trim($matches[4]), false, $protectIdentifiers);
}

View File

@ -1093,7 +1093,7 @@ abstract class BaseConnection implements ConnectionInterface
// Break the string apart if it contains periods, then insert the table prefix
// in the correct location, assuming the period doesn't indicate that we're dealing
// with an alias. While we're at it, we will escape the components
if (strpos($item, '.') !== false) {
if (str_contains($item, '.')) {
return $this->protectDotItem($item, $alias, $protectIdentifiers, $fieldExists);
}
@ -1105,11 +1105,11 @@ abstract class BaseConnection implements ConnectionInterface
// Is there a table prefix? If not, no need to insert it
if ($this->DBPrefix !== '') {
// Verify table prefix and replace if necessary
if ($this->swapPre !== '' && strpos($item, $this->swapPre) === 0) {
if ($this->swapPre !== '' && str_starts_with($item, $this->swapPre)) {
$item = preg_replace('/^' . $this->swapPre . '(\S+?)/', $this->DBPrefix . '\\1', $item);
}
// Do we prefix an item with no segments?
elseif ($prefixSingle === true && strpos($item, $this->DBPrefix) !== 0) {
elseif ($prefixSingle === true && ! str_starts_with($item, $this->DBPrefix)) {
$item = $this->DBPrefix . $item;
}
}
@ -1171,11 +1171,11 @@ abstract class BaseConnection implements ConnectionInterface
}
// Verify table prefix and replace if necessary
if ($this->swapPre !== '' && strpos($parts[$i], $this->swapPre) === 0) {
if ($this->swapPre !== '' && str_starts_with($parts[$i], $this->swapPre)) {
$parts[$i] = preg_replace('/^' . $this->swapPre . '(\S+?)/', $this->DBPrefix . '\\1', $parts[$i]);
}
// We only add the table prefix if it does not already exist
elseif (strpos($parts[$i], $this->DBPrefix) !== 0) {
elseif (! str_starts_with($parts[$i], $this->DBPrefix)) {
$parts[$i] = $this->DBPrefix . $parts[$i];
}
@ -1236,7 +1236,7 @@ abstract class BaseConnection implements ConnectionInterface
if (ctype_digit($item)
|| $item[0] === "'"
|| ($this->escapeChar !== '"' && $item[0] === '"')
|| strpos($item, '(') !== false) {
|| str_contains($item, '(')) {
return $item;
}
@ -1256,7 +1256,7 @@ abstract class BaseConnection implements ConnectionInterface
foreach ($this->reservedIdentifiers as $id) {
/** @psalm-suppress NoValue I don't know why ERROR. */
if (strpos($item, '.' . $id) !== false) {
if (str_contains($item, '.' . $id)) {
return preg_replace(
'/' . $this->pregEscapeChar[0] . '?([^' . $this->pregEscapeChar[1] . '\.]+)' . $this->pregEscapeChar[1] . '?\./i',
$this->pregEscapeChar[2] . '$1' . $this->pregEscapeChar[3] . '.',
@ -1306,7 +1306,7 @@ abstract class BaseConnection implements ConnectionInterface
public function escape($str)
{
if (is_array($str)) {
return array_map([&$this, 'escape'], $str);
return array_map($this->escape(...), $str);
}
/** @psalm-suppress NoValue I don't know why ERROR. */
@ -1402,7 +1402,7 @@ abstract class BaseConnection implements ConnectionInterface
{
$driver = $this->getDriverFunctionPrefix();
if (strpos($driver, $functionName) === false) {
if (! str_contains($driver, $functionName)) {
$functionName = $driver . $functionName;
}

View File

@ -46,7 +46,7 @@ class Database
throw new InvalidArgumentException('You must supply the parameter: alias.');
}
if (! empty($params['DSN']) && strpos($params['DSN'], '://') !== false) {
if (! empty($params['DSN']) && str_contains($params['DSN'], '://')) {
$params = $this->parseDSN($params);
}
@ -132,7 +132,7 @@ class Database
*/
protected function initDriver(string $driver, string $class, $argument): object
{
$classname = (strpos($driver, '\\') === false)
$classname = (! str_contains($driver, '\\'))
? "CodeIgniter\\Database\\{$driver}\\{$class}"
: $driver . '\\' . $class;

View File

@ -383,7 +383,7 @@ class Forge
]);
$this->addKey('id', true);
} else {
if (strpos($fields, ' ') === false) {
if (! str_contains($fields, ' ')) {
throw new InvalidArgumentException('Field information is required for that operation.');
}
@ -650,7 +650,7 @@ class Forge
return false;
}
if ($this->db->DBPrefix && strpos($tableName, $this->db->DBPrefix) === 0) {
if ($this->db->DBPrefix && str_starts_with($tableName, $this->db->DBPrefix)) {
$tableName = substr($tableName, strlen($this->db->DBPrefix));
}

View File

@ -445,7 +445,7 @@ class MigrationRunner
*/
protected function migrationFromFile(string $path, string $namespace)
{
if (substr($path, -4) !== '.php') {
if (! str_ends_with($path, '.php')) {
return false;
}

View File

@ -223,7 +223,7 @@ class Connection extends BaseConnection
public function parseInsertTableName(string $sql): string
{
$commentStrippedSql = preg_replace(['/\/\*(.|\n)*?\*\//m', '/--.+/'], '', $sql);
$isInsertQuery = strpos(strtoupper(ltrim($commentStrippedSql)), 'INSERT') === 0;
$isInsertQuery = str_starts_with(strtoupper(ltrim($commentStrippedSql)), 'INSERT');
if (! $isInsertQuery) {
return '';
@ -232,7 +232,7 @@ class Connection extends BaseConnection
preg_match('/(?is)\b(?:into)\s+("?\w+"?)/', $commentStrippedSql, $match);
$tableName = $match[1] ?? '';
return strpos($tableName, '"') === 0 ? trim($tableName, '"') : strtoupper($tableName);
return str_starts_with($tableName, '"') ? trim($tableName, '"') : strtoupper($tableName);
}
/**
@ -269,7 +269,7 @@ class Connection extends BaseConnection
*/
protected function _listColumns(string $table = ''): string
{
if (strpos($table, '.') !== false) {
if (str_contains($table, '.')) {
sscanf($table, '%[^.].%s', $owner, $table);
} else {
$owner = $this->username;
@ -289,7 +289,7 @@ class Connection extends BaseConnection
*/
protected function _fieldData(string $table): array
{
if (strpos($table, '.') !== false) {
if (str_contains($table, '.')) {
sscanf($table, '%[^.].%s', $owner, $table);
} else {
$owner = $this->username;
@ -333,7 +333,7 @@ class Connection extends BaseConnection
*/
protected function _indexData(string $table): array
{
if (strpos($table, '.') !== false) {
if (str_contains($table, '.')) {
sscanf($table, '%[^.].%s', $owner, $table);
} else {
$owner = $this->username;
@ -631,7 +631,7 @@ class Connection extends BaseConnection
return;
}
$isEasyConnectableHostName = $this->hostname !== '' && strpos($this->hostname, '/') === false && strpos($this->hostname, ':') === false;
$isEasyConnectableHostName = $this->hostname !== '' && ! str_contains($this->hostname, '/') && ! str_contains($this->hostname, ':');
$easyConnectablePort = ! empty($this->port) && ctype_digit($this->port) ? ':' . $this->port : '';
$easyConnectableDatabase = $this->database !== '' ? '/' . ltrim($this->database, '/') : '';

View File

@ -132,7 +132,7 @@ class Forge extends BaseForge
// so add null constraint is used only when it is different from the current null constraint.
// If a not null constraint is added to a column with a not null constraint,
// ORA-01442 will occur.
$wantToAddNull = strpos($processedFields[$i]['null'], ' NOT') === false;
$wantToAddNull = ! str_contains($processedFields[$i]['null'], ' NOT');
$currentNullable = $nullableMap[$processedFields[$i]['name']];
if ($wantToAddNull === true && $currentNullable === true) {
@ -198,7 +198,7 @@ class Forge extends BaseForge
{
$constraint = '';
// @todo: can't cover multi pattern when set type.
if ($processedField['type'] === 'VARCHAR2' && strpos($processedField['length'], "('") === 0) {
if ($processedField['type'] === 'VARCHAR2' && str_starts_with($processedField['length'], "('")) {
$constraint = ' CHECK(' . $this->db->escapeIdentifiers($processedField['name'])
. ' IN ' . $processedField['length'] . ')';

View File

@ -358,10 +358,10 @@ class Connection extends BaseConnection
$_fields = explode(',', preg_replace('/^.*\((.+?)\)$/', '$1', trim($row->indexdef)));
$obj->fields = array_map(static fn ($v) => trim($v), $_fields);
if (strpos($row->indexdef, 'CREATE UNIQUE INDEX pk') === 0) {
if (str_starts_with($row->indexdef, 'CREATE UNIQUE INDEX pk')) {
$obj->type = 'PRIMARY';
} else {
$obj->type = (strpos($row->indexdef, 'CREATE UNIQUE') === 0) ? 'UNIQUE' : 'INDEX';
$obj->type = (str_starts_with($row->indexdef, 'CREATE UNIQUE')) ? 'UNIQUE' : 'INDEX';
}
$retVal[$obj->name] = $obj;
@ -498,7 +498,7 @@ class Connection extends BaseConnection
}
// If UNIX sockets are used, we shouldn't set a port
if (strpos($this->hostname, '/') !== false) {
if (str_contains($this->hostname, '/')) {
$this->port = '';
}

View File

@ -13,10 +13,12 @@ declare(strict_types=1);
namespace CodeIgniter\Database;
use Stringable;
/**
* Query builder
*/
class Query implements QueryInterface
class Query implements QueryInterface, Stringable
{
/**
* The query string, as provided by the user.

View File

@ -13,10 +13,12 @@ declare(strict_types=1);
namespace CodeIgniter\Database;
use Stringable;
/**
* @see \CodeIgniter\Database\RawSqlTest
*/
class RawSql
class RawSql implements Stringable
{
/**
* @var string Raw SQL string

View File

@ -72,7 +72,7 @@ class Builder extends BaseBuilder
$from = [];
foreach ($this->QBFrom as $value) {
$from[] = strpos($value, '(SELECT') === 0 ? $value : $this->getFullName($value);
$from[] = str_starts_with($value, '(SELECT') ? $value : $this->getFullName($value);
}
return implode(', ', $from);
@ -283,7 +283,7 @@ class Builder extends BaseBuilder
{
$alias = '';
if (strpos($table, ' ') !== false) {
if (str_contains($table, ' ')) {
$alias = explode(' ', $table);
$table = array_shift($alias);
$alias = ' ' . implode(' ', $alias);
@ -451,7 +451,7 @@ class Builder extends BaseBuilder
throw DataException::forEmptyInputGiven('Select');
}
if (strpos($select, ',') !== false) {
if (str_contains($select, ',')) {
throw DataException::forInvalidArgument('Column name not separated by comma');
}

View File

@ -123,7 +123,7 @@ class Connection extends BaseConnection
unset($connection['UID'], $connection['PWD']);
}
if (strpos($this->hostname, ',') === false && $this->port !== '') {
if (! str_contains($this->hostname, ',') && $this->port !== '') {
$this->hostname .= ', ' . $this->port;
}
@ -255,10 +255,10 @@ class Connection extends BaseConnection
$_fields = explode(',', trim($row->index_keys));
$obj->fields = array_map(static fn ($v) => trim($v), $_fields);
if (strpos($row->index_description, 'primary key located on') !== false) {
if (str_contains($row->index_description, 'primary key located on')) {
$obj->type = 'PRIMARY';
} else {
$obj->type = (strpos($row->index_description, 'nonclustered, unique') !== false) ? 'UNIQUE' : 'INDEX';
$obj->type = (str_contains($row->index_description, 'nonclustered, unique')) ? 'UNIQUE' : 'INDEX';
}
$retVal[$obj->name] = $obj;

View File

@ -82,7 +82,7 @@ class Connection extends BaseConnection
}
try {
if ($this->database !== ':memory:' && strpos($this->database, DIRECTORY_SEPARATOR) === false) {
if ($this->database !== ':memory:' && ! str_contains($this->database, DIRECTORY_SEPARATOR)) {
$this->database = WRITEPATH . $this->database;
}

View File

@ -169,7 +169,7 @@ class Forge extends BaseForge
*/
protected function _processColumn(array $processedField): string
{
if ($processedField['type'] === 'TEXT' && strpos($processedField['length'], "('") === 0) {
if ($processedField['type'] === 'TEXT' && str_starts_with($processedField['length'], "('")) {
$processedField['type'] .= ' CHECK(' . $this->db->escapeIdentifiers($processedField['name'])
. ' IN ' . $processedField['length'] . ')';
}

View File

@ -98,7 +98,7 @@ class Table
$prefix = $this->db->DBPrefix;
if (! empty($prefix) && strpos($table, $prefix) === 0) {
if (! empty($prefix) && str_starts_with($table, $prefix)) {
$table = substr($table, strlen($prefix));
}
@ -432,7 +432,7 @@ class Table
*/
private function isIntegerType(string $type): bool
{
return strpos(strtoupper($type), 'INT') !== false;
return str_contains(strtoupper($type), 'INT');
}
/**

View File

@ -125,7 +125,7 @@ class Seeder
throw new InvalidArgumentException('No seeder was specified.');
}
if (strpos($class, '\\') === false) {
if (! str_contains($class, '\\')) {
$path = $this->seedPath . str_replace('.php', '', $class) . '.php';
if (! is_file($path)) {

View File

@ -83,8 +83,8 @@ abstract class BaseExceptionHandler
}
return [
'title' => get_class($exception),
'type' => get_class($exception),
'title' => $exception::class,
'type' => $exception::class,
'code' => $statusCode,
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
@ -116,7 +116,7 @@ abstract class BaseExceptionHandler
$explode = explode('/', $keyToMask);
$index = end($explode);
if (strpos(strrev($path . '/' . $index), strrev($keyToMask)) === 0) {
if (str_starts_with(strrev($path . '/' . $index), strrev($keyToMask))) {
if (is_array($args) && array_key_exists($index, $args)) {
$args[$index] = '******************';
} elseif (
@ -178,7 +178,7 @@ abstract class BaseExceptionHandler
try {
$source = file_get_contents($file);
} catch (Throwable $e) {
} catch (Throwable) {
return false;
}

View File

@ -56,7 +56,7 @@ final class ExceptionHandler extends BaseExceptionHandler implements ExceptionHa
if ($request instanceof IncomingRequest) {
try {
$response->setStatusCode($statusCode);
} catch (HTTPException $e) {
} catch (HTTPException) {
// Workaround for invalid HTTP status code.
$statusCode = 500;
$response->setStatusCode($statusCode);
@ -75,7 +75,7 @@ final class ExceptionHandler extends BaseExceptionHandler implements ExceptionHa
);
}
if (strpos($request->getHeaderLine('accept'), 'text/html') === false) {
if (! str_contains($request->getHeaderLine('accept'), 'text/html')) {
$data = (ENVIRONMENT === 'development' || ENVIRONMENT === 'testing')
? $this->collectVars($exception, $statusCode)
: '';

View File

@ -108,8 +108,8 @@ class Exceptions
*/
public function initialize()
{
set_exception_handler([$this, 'exceptionHandler']);
set_error_handler([$this, 'errorHandler']);
set_exception_handler($this->exceptionHandler(...));
set_error_handler($this->errorHandler(...));
register_shutdown_function([$this, 'shutdownHandler']);
}
@ -132,7 +132,7 @@ class Exceptions
$uri = $this->request->getPath() === '' ? '/' : $this->request->getPath();
$routeInfo = '[Method: ' . $this->request->getMethod() . ', Route: ' . $uri . ']';
log_message('critical', get_class($exception) . ": {message}\n{routeInfo}\nin {exFile} on line {exLine}.\n{trace}", [
log_message('critical', $exception::class . ": {message}\n{routeInfo}\nin {exFile} on line {exLine}.\n{trace}", [
'message' => $exception->getMessage(),
'routeInfo' => $routeInfo,
'exFile' => clean_path($exception->getFile()), // {file} refers to THIS file
@ -146,7 +146,7 @@ class Exceptions
while ($prevException = $last->getPrevious()) {
$last = $prevException;
log_message('critical', '[Caused by] ' . get_class($prevException) . ": {message}\nin {exFile} on line {exLine}.\n{trace}", [
log_message('critical', '[Caused by] ' . $prevException::class . ": {message}\nin {exFile} on line {exLine}.\n{trace}", [
'message' => $prevException->getMessage(),
'exFile' => clean_path($prevException->getFile()), // {file} refers to THIS file
'exLine' => $prevException->getLine(), // {line} refers to THIS line
@ -175,7 +175,7 @@ class Exceptions
if (! is_cli()) {
try {
$this->response->setStatusCode($statusCode);
} catch (HTTPException $e) {
} catch (HTTPException) {
// Workaround for invalid HTTP status code.
$statusCode = 500;
$this->response->setStatusCode($statusCode);
@ -185,7 +185,7 @@ class Exceptions
header(sprintf('HTTP/%s %s %s', $this->request->getProtocolVersion(), $this->response->getStatusCode(), $this->response->getReasonPhrase()), true, $statusCode);
}
if (strpos($this->request->getHeaderLine('accept'), 'text/html') === false) {
if (! str_contains($this->request->getHeaderLine('accept'), 'text/html')) {
$this->respond(ENVIRONMENT === 'development' ? $this->collectVars($exception, $statusCode) : '', $statusCode)->send();
exit($exitCode);
@ -243,7 +243,7 @@ class Exceptions
if ($this->exceptionCaughtByExceptionHandler instanceof Throwable) {
$message .= "\n【Previous Exception】\n"
. get_class($this->exceptionCaughtByExceptionHandler) . "\n"
. $this->exceptionCaughtByExceptionHandler::class . "\n"
. $this->exceptionCaughtByExceptionHandler->getMessage() . "\n"
. $this->exceptionCaughtByExceptionHandler->getTraceAsString();
}
@ -355,8 +355,8 @@ class Exceptions
}
return [
'title' => get_class($exception),
'type' => get_class($exception),
'title' => $exception::class,
'type' => $exception::class,
'code' => $statusCode,
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
@ -396,7 +396,7 @@ class Exceptions
$explode = explode('/', $keyToMask);
$index = end($explode);
if (strpos(strrev($path . '/' . $index), strrev($keyToMask)) === 0) {
if (str_starts_with(strrev($path . '/' . $index), strrev($keyToMask))) {
if (is_array($args) && array_key_exists($index, $args)) {
$args[$index] = '******************';
} elseif (
@ -480,25 +480,13 @@ class Exceptions
*/
public static function cleanPath(string $file): string
{
switch (true) {
case strpos($file, APPPATH) === 0:
$file = 'APPPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(APPPATH));
break;
case strpos($file, SYSTEMPATH) === 0:
$file = 'SYSTEMPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(SYSTEMPATH));
break;
case strpos($file, FCPATH) === 0:
$file = 'FCPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(FCPATH));
break;
case defined('VENDORPATH') && strpos($file, VENDORPATH) === 0:
$file = 'VENDORPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(VENDORPATH));
break;
}
return $file;
return match (true) {
str_starts_with($file, APPPATH) => 'APPPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(APPPATH)),
str_starts_with($file, SYSTEMPATH) => 'SYSTEMPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(SYSTEMPATH)),
str_starts_with($file, FCPATH) => 'FCPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(FCPATH)),
defined('VENDORPATH') && str_starts_with($file, VENDORPATH) => 'VENDORPATH' . DIRECTORY_SEPARATOR . substr($file, strlen(VENDORPATH)),
default => $file,
};
}
/**
@ -544,7 +532,7 @@ class Exceptions
try {
$source = file_get_contents($file);
} catch (Throwable $e) {
} catch (Throwable) {
return false;
}
@ -609,23 +597,12 @@ class Exceptions
$idx = $index;
$idx = str_pad((string) ++$idx, 2, ' ', STR_PAD_LEFT);
$args = implode(', ', array_map(static function ($value): string {
switch (true) {
case is_object($value):
return sprintf('Object(%s)', get_class($value));
case is_array($value):
return $value !== [] ? '[...]' : '[]';
case $value === null:
return 'null';
case is_resource($value):
return sprintf('resource (%s)', get_resource_type($value));
default:
return var_export($value, true);
}
$args = implode(', ', array_map(static fn ($value): string => match (true) {
is_object($value) => sprintf('Object(%s)', $value::class),
is_array($value) => $value !== [] ? '[...]' : '[]',
$value === null => 'null',
is_resource($value) => sprintf('resource (%s)', get_resource_type($value)),
default => var_export($value, true),
}, $frame['args']));
$backtraces[] = sprintf(

View File

@ -410,7 +410,7 @@ class Toolbar
// Non-HTML formats should not include the debugbar
// then we send headers saying where to find the debug data
// for this response
if ($request->isAJAX() || strpos($format, 'html') === false) {
if ($request->isAJAX() || ! str_contains($format, 'html')) {
$response->setHeader('Debugbar-Time', "{$time}")
->setHeader('Debugbar-Link', site_url("?debugbar_time={$time}"));
@ -433,7 +433,7 @@ class Toolbar
. $kintScript
. PHP_EOL;
if (strpos($response->getBody(), '<head>') !== false) {
if (str_contains($response->getBody(), '<head>')) {
$response->setBody(
preg_replace(
'/<head>/',

View File

@ -163,7 +163,7 @@ class Database extends BaseCollector
}
// find the first trace line that does not originate from `system/`
if ($firstNonSystemLine === '' && strpos($line['file'], 'SYSTEMPATH') === false) {
if ($firstNonSystemLine === '' && ! str_contains($line['file'], 'SYSTEMPATH')) {
$firstNonSystemLine = $line['file'];
}

View File

@ -62,7 +62,7 @@ class Files extends BaseCollector
foreach ($rawFiles as $file) {
$path = clean_path($file);
if (strpos($path, 'SYSTEMPATH') !== false) {
if (str_contains($path, 'SYSTEMPATH')) {
$coreFiles[] = [
'path' => $path,
'name' => basename($file),

View File

@ -65,7 +65,7 @@ class Routes extends BaseCollector
} else {
try {
$method = new ReflectionMethod($router->controllerName(), $router->methodName());
} catch (ReflectionException $e) {
} catch (ReflectionException) {
try {
// If we're here, the method doesn't exist
// and is likely calculated in _remap.

View File

@ -660,7 +660,7 @@ class Email
public function attach($file, $disposition = '', $newname = null, $mime = '')
{
if ($mime === '') {
if (strpos($file, '://') === false && ! is_file($file)) {
if (! str_contains($file, '://') && ! is_file($file)) {
$this->setErrorMessage(lang('Email.attachmentMissing', [$file]));
return false;
@ -750,7 +750,7 @@ class Email
protected function stringToArray($email)
{
if (! is_array($email)) {
return (strpos($email, ',') !== false) ? preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY) : (array) trim($email);
return (str_contains($email, ',')) ? preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY) : (array) trim($email);
}
return $email;
@ -874,7 +874,7 @@ class Email
}
foreach ($this->baseCharsets as $charset) {
if (strpos($this->charset, $charset) === 0) {
if (str_starts_with($this->charset, $charset)) {
$this->encoding = '7bit';
break;
@ -1023,7 +1023,7 @@ class Email
$charlim = empty($this->wrapChars) ? 76 : $this->wrapChars;
}
if (strpos($str, "\r") !== false) {
if (str_contains($str, "\r")) {
$str = str_replace(["\r\n", "\r"], "\n", $str);
}
@ -1421,7 +1421,7 @@ class Email
$str = preg_replace(['| +|', '/\x00+/'], [' ', ''], $str);
// Standardize newlines
if (strpos($str, "\r") !== false) {
if (str_contains($str, "\r")) {
$str = str_replace(["\r\n", "\r"], "\n", $str);
}
@ -1656,10 +1656,7 @@ class Email
{
$this->finalBody = preg_replace_callback(
'/\{unwrap\}(.*?)\{\/unwrap\}/si',
[
$this,
'removeNLCallback',
],
$this->removeNLCallback(...),
$this->finalBody
);
}
@ -1675,7 +1672,7 @@ class Email
*/
protected function removeNLCallback($matches)
{
if (strpos($matches[1], "\r") !== false || strpos($matches[1], "\n") !== false) {
if (str_contains($matches[1], "\r") || str_contains($matches[1], "\n")) {
$matches[1] = str_replace(["\r\n", "\r", "\n"], '', $matches[1]);
}
@ -1856,7 +1853,7 @@ class Email
$this->setErrorMessage($reply);
$this->SMTPEnd();
if (strpos($reply, '250') !== 0) {
if (! str_starts_with($reply, '250')) {
$this->setErrorMessage(lang('Email.SMTPError', [$reply]));
return false;
@ -2028,11 +2025,11 @@ class Email
$this->sendData('AUTH LOGIN');
$reply = $this->getSMTPData();
if (strpos($reply, '503') === 0) { // Already authenticated
if (str_starts_with($reply, '503')) { // Already authenticated
return true;
}
if (strpos($reply, '334') !== 0) {
if (! str_starts_with($reply, '334')) {
$this->setErrorMessage(lang('Email.failedSMTPLogin', [$reply]));
return false;
@ -2041,7 +2038,7 @@ class Email
$this->sendData(base64_encode($this->SMTPUser));
$reply = $this->getSMTPData();
if (strpos($reply, '334') !== 0) {
if (! str_starts_with($reply, '334')) {
$this->setErrorMessage(lang('Email.SMTPAuthUsername', [$reply]));
return false;
@ -2050,7 +2047,7 @@ class Email
$this->sendData(base64_encode($this->SMTPPass));
$reply = $this->getSMTPData();
if (strpos($reply, '235') !== 0) {
if (! str_starts_with($reply, '235')) {
$this->setErrorMessage(lang('Email.SMTPAuthPassword', [$reply]));
return false;

View File

@ -23,7 +23,7 @@ class ArrayCast extends BaseCast
*/
public static function get($value, array $params = []): array
{
if (is_string($value) && (strpos($value, 'a:') === 0 || strpos($value, 's:') === 0)) {
if (is_string($value) && (str_starts_with($value, 'a:') || str_starts_with($value, 's:'))) {
$value = unserialize($value);
}

View File

@ -181,7 +181,7 @@ class Entity implements JsonSerializable
{
$this->_cast = $cast;
$keys = array_filter(array_keys($this->attributes), static fn ($key) => strpos($key, '_') !== 0);
$keys = array_filter(array_keys($this->attributes), static fn ($key) => ! str_starts_with($key, '_'));
if (is_array($this->datamap)) {
$keys = array_unique(

View File

@ -43,25 +43,14 @@ class CastException extends FrameworkException implements HasExitCodeInterface
*/
public static function forInvalidJsonFormat(int $error)
{
switch ($error) {
case JSON_ERROR_DEPTH:
return new static(lang('Cast.jsonErrorDepth'));
case JSON_ERROR_STATE_MISMATCH:
return new static(lang('Cast.jsonErrorStateMismatch'));
case JSON_ERROR_CTRL_CHAR:
return new static(lang('Cast.jsonErrorCtrlChar'));
case JSON_ERROR_SYNTAX:
return new static(lang('Cast.jsonErrorSyntax'));
case JSON_ERROR_UTF8:
return new static(lang('Cast.jsonErrorUtf8'));
default:
return new static(lang('Cast.jsonErrorUnknown'));
}
return match ($error) {
JSON_ERROR_DEPTH => new static(lang('Cast.jsonErrorDepth')),
JSON_ERROR_STATE_MISMATCH => new static(lang('Cast.jsonErrorStateMismatch')),
JSON_ERROR_CTRL_CHAR => new static(lang('Cast.jsonErrorCtrlChar')),
JSON_ERROR_SYNTAX => new static(lang('Cast.jsonErrorSyntax')),
JSON_ERROR_UTF8 => new static(lang('Cast.jsonErrorUtf8')),
default => new static(lang('Cast.jsonErrorUnknown')),
};
}
/**

View File

@ -64,7 +64,7 @@ class FrameworkException extends RuntimeException implements ExceptionInterface
*/
public static function forMissingExtension(string $extension)
{
if (strpos($extension, 'intl') !== false) {
if (str_contains($extension, 'intl')) {
// @codeCoverageIgnoreStart
$message = sprintf(
'The framework needs the following extension(s) installed and loaded: %s.',

View File

@ -76,16 +76,11 @@ class File extends SplFileInfo
*/
public function getSizeByUnit(string $unit = 'b')
{
switch (strtolower($unit)) {
case 'kb':
return number_format($this->getSize() / 1024, 3);
case 'mb':
return number_format(($this->getSize() / 1024) / 1024, 3);
default:
return $this->getSize();
}
return match (strtolower($unit)) {
'kb' => number_format($this->getSize() / 1024, 3),
'mb' => number_format(($this->getSize() / 1024) / 1024, 3),
default => $this->getSize(),
};
}
/**
@ -175,7 +170,7 @@ class File extends SplFileInfo
$info = pathinfo($destination);
$extension = isset($info['extension']) ? '.' . $info['extension'] : '';
if (strpos($info['filename'], $delimiter) !== false) {
if (str_contains($info['filename'], $delimiter)) {
$parts = explode($delimiter, $info['filename']);
if (is_numeric(end($parts))) {

View File

@ -85,7 +85,7 @@ class FileCollection implements Countable, IteratorAggregate
{
$directory = self::resolveDirectory($directory);
return array_filter($files, static fn (string $value): bool => strpos($value, $directory) === 0);
return array_filter($files, static fn (string $value): bool => str_starts_with($value, $directory));
}
/**
@ -182,7 +182,7 @@ class FileCollection implements Countable, IteratorAggregate
try {
// Test for a directory
self::resolveDirectory($path);
} catch (FileException $e) {
} catch (FileException) {
$this->addFile($path);
continue;

View File

@ -197,7 +197,7 @@ class Filters
$class = new $className();
if (! $class instanceof FilterInterface) {
throw FilterException::forIncorrectInterface(get_class($class));
throw FilterException::forIncorrectInterface($class::class);
}
$result = $class->before(
@ -235,7 +235,7 @@ class Filters
$class = new $className();
if (! $class instanceof FilterInterface) {
throw FilterException::forIncorrectInterface(get_class($class));
throw FilterException::forIncorrectInterface($class::class);
}
$result = $class->after(
@ -518,7 +518,7 @@ class Filters
{
$arguments = [];
if (strpos($name, ':') !== false) {
if (str_contains($name, ':')) {
[$name, $arguments] = explode(':', $name);
$arguments = explode(',', $arguments);

View File

@ -92,7 +92,7 @@ class InvalidChars implements FilterInterface
protected function checkEncoding($value)
{
if (is_array($value)) {
array_map([$this, 'checkEncoding'], $value);
array_map($this->checkEncoding(...), $value);
return $value;
}
@ -114,7 +114,7 @@ class InvalidChars implements FilterInterface
protected function checkControl($value)
{
if (is_array($value)) {
array_map([$this, 'checkControl'], $value);
array_map($this->checkControl(...), $value);
return $value;
}

View File

@ -26,7 +26,7 @@ use CodeIgniter\HTTP\ResponseInterface;
*/
class PageCache implements FilterInterface
{
private ResponseCache $pageCache;
private readonly ResponseCache $pageCache;
public function __construct()
{

View File

@ -91,7 +91,7 @@ class CURLRequest extends OutgoingRequest
/**
* The default options from the constructor. Applied to all requests.
*/
private array $defaultOptions;
private readonly array $defaultOptions;
/**
* Whether share options between requests or not.
@ -99,7 +99,7 @@ class CURLRequest extends OutgoingRequest
* If true, all the options won't be reset between requests.
* It may cause an error request with unnecessary headers.
*/
private bool $shareOptions;
private readonly bool $shareOptions;
/**
* Takes an array of options to set the following possible class properties:
@ -325,7 +325,7 @@ class CURLRequest extends OutgoingRequest
protected function prepareURL(string $url): string
{
// If it's a full URI, then we have nothing to do here...
if (strpos($url, '://') !== false) {
if (str_contains($url, '://')) {
return $url;
}
@ -380,16 +380,16 @@ class CURLRequest extends OutgoingRequest
// Set the string we want to break our response from
$breakString = "\r\n\r\n";
while (strpos($output, 'HTTP/1.1 100 Continue') === 0) {
while (str_starts_with($output, 'HTTP/1.1 100 Continue')) {
$output = substr($output, strpos($output, $breakString) + 4);
}
if (strpos($output, 'HTTP/1.1 200 Connection established') === 0) {
if (str_starts_with($output, 'HTTP/1.1 200 Connection established')) {
$output = substr($output, strpos($output, $breakString) + 4);
}
// If request and response have Digest
if (isset($this->config['auth'][2]) && $this->config['auth'][2] === 'digest' && strpos($output, 'WWW-Authenticate: Digest') !== false) {
if (isset($this->config['auth'][2]) && $this->config['auth'][2] === 'digest' && str_contains($output, 'WWW-Authenticate: Digest')) {
$output = substr($output, strpos($output, $breakString) + 4);
}
@ -489,7 +489,7 @@ class CURLRequest extends OutgoingRequest
} else {
$this->response->setHeader($title, $value);
}
} elseif (strpos($header, 'HTTP') === 0) {
} elseif (str_starts_with($header, 'HTTP')) {
preg_match('#^HTTP\/([12](?:\.[01])?) (\d+) (.+)#', $header, $matches);
if (isset($matches[1])) {

View File

@ -802,7 +802,7 @@ class ContentSecurityPolicy
$reportOnly = $this->reportOnly;
}
if (strpos($value, 'nonce-') === 0) {
if (str_starts_with($value, 'nonce-')) {
$value = "'{$value}'";
}

View File

@ -38,7 +38,7 @@ class DownloadResponse extends Response
/**
* mime set flag
*/
private bool $setMime;
private readonly bool $setMime;
/**
* Download for binary

View File

@ -59,7 +59,7 @@ class FileCollection
$this->populateFiles();
if ($this->hasFile($name)) {
if (strpos($name, '.') !== false) {
if (str_contains($name, '.')) {
$name = explode('.', $name);
$uploadedFile = $this->getValueDotNotationSyntax($name, $this->files);
@ -86,7 +86,7 @@ class FileCollection
$this->populateFiles();
if ($this->hasFile($name)) {
if (strpos($name, '.') !== false) {
if (str_contains($name, '.')) {
$name = explode('.', $name);
$uploadedFile = $this->getValueDotNotationSyntax($name, $this->files);
@ -115,7 +115,7 @@ class FileCollection
{
$this->populateFiles();
if (strpos($fileID, '.') !== false) {
if (str_contains($fileID, '.')) {
$segments = explode('.', $fileID);
$el = $this->files;

View File

@ -147,7 +147,7 @@ class UploadedFile extends File implements UploadedFileInterface
try {
$this->hasMoved = move_uploaded_file($this->path, $destination);
} catch (Exception $e) {
} catch (Exception) {
$error = error_get_last();
$message = strip_tags($error['message'] ?? '');

View File

@ -13,6 +13,8 @@ declare(strict_types=1);
namespace CodeIgniter\HTTP;
use Stringable;
/**
* Class Header
*
@ -20,7 +22,7 @@ namespace CodeIgniter\HTTP;
*
* @see \CodeIgniter\HTTP\HeaderTest
*/
class Header
class Header implements Stringable
{
/**
* The name of the header.

View File

@ -141,7 +141,7 @@ class IncomingRequest extends Request
$body === 'php://input'
// php://input is not available with enctype="multipart/form-data".
// See https://www.php.net/manual/en/wrappers.php.php#wrappers.php.input
&& strpos($this->getHeaderLine('Content-Type'), 'multipart/form-data') === false
&& ! str_contains($this->getHeaderLine('Content-Type'), 'multipart/form-data')
&& (int) $this->getHeaderLine('Content-Length') <= $this->getPostMaxSize()
) {
// Get our body from php://input
@ -173,24 +173,12 @@ class IncomingRequest extends Request
{
$postMaxSize = ini_get('post_max_size');
switch (strtoupper(substr($postMaxSize, -1))) {
case 'G':
$postMaxSize = (int) str_replace('G', '', $postMaxSize) * 1024 ** 3;
break;
case 'M':
$postMaxSize = (int) str_replace('M', '', $postMaxSize) * 1024 ** 2;
break;
case 'K':
$postMaxSize = (int) str_replace('K', '', $postMaxSize) * 1024;
break;
default:
$postMaxSize = (int) $postMaxSize;
}
return $postMaxSize;
return match (strtoupper(substr($postMaxSize, -1))) {
'G' => (int) str_replace('G', '', $postMaxSize) * 1024 ** 3,
'M' => (int) str_replace('M', '', $postMaxSize) * 1024 ** 2,
'K' => (int) str_replace('K', '', $postMaxSize) * 1024,
default => (int) $postMaxSize,
};
}
/**
@ -238,20 +226,11 @@ class IncomingRequest extends Request
$protocol = 'REQUEST_URI';
}
switch ($protocol) {
case 'REQUEST_URI':
$this->path = $this->parseRequestURI();
break;
case 'QUERY_STRING':
$this->path = $this->parseQueryString();
break;
case 'PATH_INFO':
default:
$this->path = $this->fetchGlobal('server', $protocol) ?? $this->parseRequestURI();
break;
}
$this->path = match ($protocol) {
'REQUEST_URI' => $this->parseRequestURI(),
'QUERY_STRING' => $this->parseQueryString(),
default => $this->fetchGlobal('server', $protocol) ?? $this->parseRequestURI(),
};
return $this->path;
}
@ -299,7 +278,7 @@ class IncomingRequest extends Request
// This section ensures that even on servers that require the URI to contain the query string (Nginx) a correct
// URI is found, and also fixes the QUERY_STRING Server var and $_GET array.
if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0) {
if (trim($uri, '/') === '' && str_starts_with($query, '/')) {
$query = explode('?', $query, 2);
$uri = $query[0];
$_SERVER['QUERY_STRING'] = $query[1] ?? '';
@ -332,7 +311,7 @@ class IncomingRequest extends Request
return '/';
}
if (strncmp($uri, '/', 1) === 0) {
if (str_starts_with($uri, '/')) {
$uri = explode('?', $uri, 2);
$_SERVER['QUERY_STRING'] = $uri[1] ?? '';
$uri = $uri[0];
@ -358,21 +337,13 @@ class IncomingRequest extends Request
$this->negotiator = Services::negotiator($this, true);
}
switch (strtolower($type)) {
case 'media':
return $this->negotiator->media($supported, $strictMatch);
case 'charset':
return $this->negotiator->charset($supported);
case 'encoding':
return $this->negotiator->encoding($supported);
case 'language':
return $this->negotiator->language($supported);
}
throw HTTPException::forInvalidNegotiationType($type);
return match (strtolower($type)) {
'media' => $this->negotiator->media($supported, $strictMatch),
'charset' => $this->negotiator->charset($supported),
'encoding' => $this->negotiator->encoding($supported),
'language' => $this->negotiator->language($supported),
default => throw HTTPException::forInvalidNegotiationType($type),
};
}
/**
@ -392,7 +363,7 @@ class IncomingRequest extends Request
}
if ($valueUpper === 'JSON') {
return strpos($this->getHeaderLine('Content-Type'), 'application/json') !== false;
return str_contains($this->getHeaderLine('Content-Type'), 'application/json');
}
if ($valueUpper === 'AJAX') {
@ -528,7 +499,7 @@ class IncomingRequest extends Request
public function getVar($index = null, $filter = null, $flags = null)
{
if (
strpos($this->getHeaderLine('Content-Type'), 'application/json') !== false
str_contains($this->getHeaderLine('Content-Type'), 'application/json')
&& $this->body !== null
) {
return $this->getJsonVar($index, false, $filter, $flags);

View File

@ -37,7 +37,7 @@ class RedirectResponse extends Response
{
// If it appears to be a relative URL, then convert to full URL
// for better security.
if (strpos($uri, 'http') !== 0) {
if (! str_starts_with($uri, 'http')) {
$uri = site_url($uri);
}

View File

@ -86,7 +86,7 @@ trait RequestTrait
// @TODO Extract all this IP address logic to another class.
foreach ($proxyIPs as $proxyIP => $header) {
// Check if we have an IP address or a subnet
if (strpos($proxyIP, '/') === false) {
if (! str_contains($proxyIP, '/')) {
// An IP address (and not a subnet) is specified.
// We can compare right away.
if ($proxyIP === $this->ipAddress) {
@ -107,7 +107,7 @@ trait RequestTrait
}
// If the proxy entry doesn't match the IP protocol - skip it
if (strpos($proxyIP, $separator) === false) {
if (! str_contains($proxyIP, $separator)) {
continue;
}

View File

@ -448,7 +448,7 @@ trait ResponseTrait
if (
$method === 'auto'
&& isset($_SERVER['SERVER_SOFTWARE'])
&& strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false
&& str_contains($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS')
) {
$method = 'refresh';
} elseif ($method !== 'refresh' && $code === null) {
@ -472,15 +472,10 @@ trait ResponseTrait
$code = 302;
}
switch ($method) {
case 'refresh':
$this->setHeader('Refresh', '0;url=' . $uri);
break;
default:
$this->setHeader('Location', $uri);
break;
}
match ($method) {
'refresh' => $this->setHeader('Refresh', '0;url=' . $uri),
default => $this->setHeader('Location', $uri),
};
$this->setStatusCode($code);

View File

@ -28,7 +28,7 @@ class SiteURI extends URI
/**
* The current baseURL.
*/
private URI $baseURL;
private readonly URI $baseURL;
/**
* The path part of baseURL.

View File

@ -26,13 +26,8 @@ use Config\App;
*/
final class SiteURIFactory
{
private App $appConfig;
private Superglobals $superglobals;
public function __construct(App $appConfig, Superglobals $superglobals)
public function __construct(private readonly App $appConfig, private readonly Superglobals $superglobals)
{
$this->appConfig = $appConfig;
$this->superglobals = $superglobals;
}
/**
@ -97,20 +92,11 @@ final class SiteURIFactory
$protocol = $this->appConfig->uriProtocol;
}
switch ($protocol) {
case 'REQUEST_URI':
$routePath = $this->parseRequestURI();
break;
case 'QUERY_STRING':
$routePath = $this->parseQueryString();
break;
case 'PATH_INFO':
default:
$routePath = $this->superglobals->server($protocol) ?? $this->parseRequestURI();
break;
}
$routePath = match ($protocol) {
'REQUEST_URI' => $this->parseRequestURI(),
'QUERY_STRING' => $this->parseQueryString(),
default => $this->superglobals->server($protocol) ?? $this->parseRequestURI(),
};
return ($routePath === '/' || $routePath === '') ? '/' : ltrim($routePath, '/');
}
@ -163,7 +149,7 @@ final class SiteURIFactory
// This section ensures that even on servers that require the URI to
// contain the query string (Nginx) a correct URI is found, and also
// fixes the QUERY_STRING Server var and $_GET array.
if (trim($path, '/') === '' && strncmp($query, '/', 1) === 0) {
if (trim($path, '/') === '' && str_starts_with($query, '/')) {
$parts = explode('?', $query, 2);
$path = $parts[0];
$newQuery = $query[1] ?? '';
@ -195,7 +181,7 @@ final class SiteURIFactory
return '/';
}
if (strncmp($query, '/', 1) === 0) {
if (str_starts_with($query, '/')) {
$parts = explode('?', $query, 2);
$path = $parts[0];
$newQuery = $parts[1] ?? '';

View File

@ -17,13 +17,14 @@ use BadMethodCallException;
use CodeIgniter\HTTP\Exceptions\HTTPException;
use Config\App;
use InvalidArgumentException;
use Stringable;
/**
* Abstraction for a uniform resource identifier (URI).
*
* @see \CodeIgniter\HTTP\URITest
*/
class URI
class URI implements Stringable
{
/**
* Sub-delimiters used in query strings and fragments.
@ -174,7 +175,7 @@ class URI
}
if (isset($path) && $path !== '') {
$uri .= substr($uri, -1, 1) !== '/'
$uri .= ! str_ends_with($uri, '/')
? '/' . ltrim($path, '/')
: ltrim($path, '/');
}
@ -230,12 +231,12 @@ class URI
$output = trim($output, '/ ');
// Add leading slash if necessary
if (strpos($path, '/') === 0) {
if (str_starts_with($path, '/')) {
$output = '/' . $output;
}
// Add trailing slash if necessary
if ($output !== '/' && substr($path, -1, 1) === '/') {
if ($output !== '/' && str_ends_with($path, '/')) {
$output .= '/';
}
@ -654,14 +655,14 @@ class URI
$baseUri = new self($config->baseURL);
if (
substr($this->getScheme(), 0, 4) === 'http'
str_starts_with($this->getScheme(), 'http')
&& $this->getHost() === $baseUri->getHost()
) {
// Check for additional segments
$basePath = trim($baseUri->getPath(), '/') . '/';
$trimPath = ltrim($path, '/');
if ($basePath !== '/' && strpos($trimPath, $basePath) !== 0) {
if ($basePath !== '/' && ! str_starts_with($trimPath, $basePath)) {
$path = $basePath . $trimPath;
}
@ -879,7 +880,7 @@ class URI
*/
public function setQuery(string $query)
{
if (strpos($query, '#') !== false) {
if (str_contains($query, '#')) {
if ($this->silent) {
return $this;
}
@ -888,7 +889,7 @@ class URI
}
// Can't have leading ?
if ($query !== '' && strpos($query, '?') === 0) {
if ($query !== '' && str_starts_with($query, '?')) {
$query = substr($query, 1);
}
@ -1010,10 +1011,10 @@ class URI
$path = self::removeDotSegments($path);
// Fix up some leading slash edge cases...
if (strpos($orig, './') === 0) {
if (str_starts_with($orig, './')) {
$path = '/' . $path;
}
if (strpos($orig, '../') === 0) {
if (str_starts_with($orig, '../')) {
$path = '/' . $path;
}
@ -1114,7 +1115,7 @@ class URI
$transformed->setQuery($this->getQuery());
}
} else {
if (strpos($relative->getPath(), '/') === 0) {
if (str_starts_with($relative->getPath(), '/')) {
$transformed->setPath($relative->getPath());
} else {
$transformed->setPath($this->mergePaths($this, $relative));

View File

@ -14,13 +14,14 @@ declare(strict_types=1);
namespace CodeIgniter\HTTP;
use Config\UserAgents;
use Stringable;
/**
* Abstraction for an HTTP user agent
*
* @see \CodeIgniter\HTTP\UserAgentTest
*/
class UserAgent
class UserAgent implements Stringable
{
/**
* Current user-agent

View File

@ -55,7 +55,7 @@ if (! function_exists('directory_map')) {
closedir($fp);
return $fileData;
} catch (Throwable $e) {
} catch (Throwable) {
return [];
}
}
@ -131,7 +131,7 @@ if (! function_exists('write_file')) {
fclose($fp);
return is_int($result);
} catch (Throwable $e) {
} catch (Throwable) {
return false;
}
}
@ -180,7 +180,7 @@ if (! function_exists('delete_files')) {
}
return true;
} catch (Throwable $e) {
} catch (Throwable) {
return false;
}
}
@ -229,7 +229,7 @@ if (! function_exists('get_filenames')) {
}
}
}
} catch (Throwable $e) {
} catch (Throwable) {
return [];
}
@ -279,7 +279,7 @@ if (! function_exists('get_dir_file_info')) {
closedir($fp);
return $fileData;
} catch (Throwable $fe) {
} catch (Throwable) {
return [];
}
}

View File

@ -33,9 +33,9 @@ if (! function_exists('form_open')) {
if ($action === '') {
$action = current_url(true);
} // If an action is not a full URL then turn it into one
elseif (strpos($action, '://') === false) {
elseif (! str_contains($action, '://')) {
// If an action has {locale}
if (strpos($action, '{locale}') !== false) {
if (str_contains($action, '{locale}')) {
$action = str_replace('{locale}', service('request')->getLocale(), $action);
}
@ -62,7 +62,7 @@ if (! function_exists('form_open')) {
// Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
$before = service('filters')->getFilters()['before'];
if ((in_array('csrf', $before, true) || array_key_exists('csrf', $before)) && strpos($action, base_url()) !== false && ! stripos($form, 'method="get"')) {
if ((in_array('csrf', $before, true) || array_key_exists('csrf', $before)) && str_contains($action, base_url()) && ! stripos($form, 'method="get"')) {
$form .= csrf_field($csrfId ?? null);
}

View File

@ -110,7 +110,7 @@ if (! function_exists('img')) {
$img = '<img';
// Check for a relative URI
if (! preg_match('#^([a-z]+:)?//#i', $src['src']) && strpos($src['src'], 'data:') !== 0) {
if (! preg_match('#^([a-z]+:)?//#i', $src['src']) && ! str_starts_with($src['src'], 'data:')) {
if ($indexPage === true) {
$img .= ' src="' . site_url($src['src']) . '"';
} else {

View File

@ -28,7 +28,7 @@ if (! function_exists('number_to_size')) {
try {
// @phpstan-ignore-next-line
$num = 0 + str_replace(',', '', (string) $num);
} catch (ErrorException $ee) {
} catch (ErrorException) {
// Catch "Warning: A non-numeric value encountered"
return false;
}
@ -83,7 +83,7 @@ if (! function_exists('number_to_amount')) {
try {
// @phpstan-ignore-next-line
$num = 0 + str_replace(',', '', $num);
} catch (ErrorException $ee) {
} catch (ErrorException) {
return false;
}

View File

@ -343,7 +343,7 @@ if (! function_exists('word_wrap')) {
$str = preg_replace('| +|', ' ', $str);
// Standardize newlines
if (strpos($str, "\r") !== false) {
if (str_contains($str, "\r")) {
$str = str_replace(["\r\n", "\r"], "\n", $str);
}

View File

@ -42,7 +42,7 @@ class Honeypot
{
$this->config = $config;
if ($this->config->container === '' || strpos($this->config->container, '{template}') === false) {
if ($this->config->container === '' || ! str_contains($this->config->container, '{template}')) {
$this->config->container = '<div style="display:none">{template}</div>';
}

View File

@ -473,31 +473,16 @@ abstract class BaseHandler implements ImageHandlerInterface
{
$orientation = $this->getEXIF('Orientation', $silent);
switch ($orientation) {
case 2:
return $this->flip('horizontal');
case 3:
return $this->rotate(180);
case 4:
return $this->rotate(180)->flip('horizontal');
case 5:
return $this->rotate(270)->flip('horizontal');
case 6:
return $this->rotate(270);
case 7:
return $this->rotate(90)->flip('horizontal');
case 8:
return $this->rotate(90);
default:
return $this;
}
return match ($orientation) {
2 => $this->flip('horizontal'),
3 => $this->rotate(180),
4 => $this->rotate(180)->flip('horizontal'),
5 => $this->rotate(270)->flip('horizontal'),
6 => $this->rotate(270),
7 => $this->rotate(90)->flip('horizontal'),
8 => $this->rotate(90),
default => $this,
};
}
/**

View File

@ -455,30 +455,15 @@ class ImageMagickHandler extends BaseHandler
{
$orientation = $this->getEXIF('Orientation', $silent);
switch ($orientation) {
case 2:
return $this->flip('horizontal');
case 3:
return $this->rotate(180);
case 4:
return $this->rotate(180)->flip('horizontal');
case 5:
return $this->rotate(90)->flip('horizontal');
case 6:
return $this->rotate(90);
case 7:
return $this->rotate(270)->flip('horizontal');
case 8:
return $this->rotate(270);
default:
return $this;
}
return match ($orientation) {
2 => $this->flip('horizontal'),
3 => $this->rotate(180),
4 => $this->rotate(180)->flip('horizontal'),
5 => $this->rotate(90)->flip('horizontal'),
6 => $this->rotate(90),
7 => $this->rotate(270)->flip('horizontal'),
8 => $this->rotate(270),
default => $this,
};
}
}

View File

@ -94,7 +94,7 @@ class Language
public function getLine(string $line, array $args = [])
{
// if no file is given, just parse the line
if (strpos($line, '.') === false) {
if (! str_contains($line, '.')) {
return $this->formatMessage($line, $args);
}

View File

@ -144,7 +144,7 @@ class ChromeLoggerHandler extends BaseHandler
// @todo Modify formatting of objects once we can view them in browser.
$objectArray = (array) $object;
$objectArray['___class_name'] = get_class($object);
$objectArray['___class_name'] = $object::class;
return $objectArray;
}

View File

@ -90,7 +90,7 @@ class FileHandler extends BaseHandler
}
// Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format
if (strpos($this->dateFormat, 'u') !== false) {
if (str_contains($this->dateFormat, 'u')) {
$microtimeFull = microtime(true);
$microtimeShort = sprintf('%06d', ($microtimeFull - floor($microtimeFull)) * 1_000_000);
$date = new DateTime(date('Y-m-d H:i:s.' . $microtimeShort, (int) $microtimeFull));

View File

@ -341,7 +341,7 @@ class Logger implements LoggerInterface
$replace['{env}'] = ENVIRONMENT;
// Allow us to log the file/line that we are logging from
if (strpos($message, '{file}') !== false) {
if (str_contains($message, '{file}')) {
[$file, $line] = $this->determineFile();
$replace['{file}'] = $file;
@ -349,7 +349,7 @@ class Logger implements LoggerInterface
}
// Match up environment variables in {env:foo} tags.
if (strpos($message, 'env:') !== false) {
if (str_contains($message, 'env:')) {
preg_match('/env:[^}]+/', $message, $matches);
foreach ($matches as $str) {

View File

@ -567,7 +567,7 @@ class Model extends BaseModel
return [];
}
return [get_class($this->db) => $error['message']];
return [$this->db::class => $error['message']];
}
/**

View File

@ -427,7 +427,7 @@ class Pager implements PagerInterface
try {
$this->groups[$group]['currentPage'] = (int) $this->groups[$group]['currentUri']
->setSilent(false)->getSegment($this->segment[$group]);
} catch (HTTPException $e) {
} catch (HTTPException) {
$this->groups[$group]['currentPage'] = 1;
}
} else {

View File

@ -72,9 +72,9 @@ class Publisher extends FileCollection
*
* @var array<string,string>
*/
private array $restrictions;
private readonly array $restrictions;
private ContentReplacer $replacer;
private readonly ContentReplacer $replacer;
/**
* Base path to use for the source.
@ -169,7 +169,7 @@ class Publisher extends FileCollection
// Make sure the destination is allowed
foreach (array_keys($this->restrictions) as $directory) {
if (strpos($this->destination, $directory) === 0) {
if (str_starts_with($this->destination, $directory)) {
return;
}
}
@ -472,7 +472,7 @@ class Publisher extends FileCollection
{
// Verify this is an allowed file for its destination
foreach ($this->restrictions as $directory => $pattern) {
if (strpos($to, $directory) === 0 && self::matchFiles([$to], $pattern) === []) {
if (str_starts_with($to, $directory) && self::matchFiles([$to], $pattern) === []) {
throw PublisherException::forFileNotAllowed($from, $directory, $pattern);
}
}

View File

@ -71,7 +71,7 @@ abstract class BaseResource extends Controller
}
if (! empty($this->model) && empty($this->modelName)) {
$this->modelName = get_class($this->model);
$this->modelName = $this->model::class;
}
}
}

View File

@ -22,53 +22,37 @@ use CodeIgniter\HTTP\ResponseInterface;
*/
final class AutoRouter implements AutoRouterInterface
{
/**
* List of CLI routes that do not contain '*' routes.
*
* @var array<string, (Closure(mixed...): (ResponseInterface|string|void))|string> [routeKey => handler]
*/
private array $cliRoutes;
/**
* Sub-directory that contains the requested controller class.
* Primarily used by 'autoRoute'.
*/
private ?string $directory = null;
/**
* The name of the controller class.
*/
private string $controller;
/**
* The name of the method to use.
*/
private string $method;
/**
* Whether dashes in URI's should be converted
* to underscores when determining method names.
*/
private bool $translateURIDashes;
/**
* Default namespace for controllers.
*/
private string $defaultNamespace;
public function __construct(
array $cliRoutes,
string $defaultNamespace,
string $defaultController,
string $defaultMethod,
bool $translateURIDashes
/**
* List of CLI routes that do not contain '*' routes.
*
* @var array<string, (Closure(mixed...): (ResponseInterface|string|void))|string> [routeKey => handler]
*/
private readonly array $cliRoutes,
/**
* Default namespace for controllers.
*/
private readonly string $defaultNamespace,
/**
* The name of the controller class.
*/
private string $controller,
/**
* The name of the method to use.
*/
private string $method,
/**
* Whether dashes in URI's should be converted
* to underscores when determining method names.
*/
private bool $translateURIDashes
) {
$this->cliRoutes = $cliRoutes;
$this->defaultNamespace = $defaultNamespace;
$this->translateURIDashes = $translateURIDashes;
$this->controller = $defaultController;
$this->method = $defaultMethod;
}
/**
@ -132,13 +116,13 @@ final class AutoRouter implements AutoRouterInterface
$handler = strtolower($handler);
// Like $routes->cli('hello/(:segment)', 'Home::$1')
if (strpos($handler, '::$') !== false) {
if (str_contains($handler, '::$')) {
throw new PageNotFoundException(
'Cannot access CLI Route: ' . $uri
);
}
if (strpos($handler, $controller . '::' . $methodName) === 0) {
if (str_starts_with($handler, $controller . '::' . $methodName)) {
throw new PageNotFoundException(
'Cannot access CLI Route: ' . $uri
);
@ -164,7 +148,7 @@ final class AutoRouter implements AutoRouterInterface
// Ensure the controller stores the fully-qualified class name
// We have to check for a length over 1, since by default it will be '\'
if (strpos($this->controller, '\\') === false && strlen($this->defaultNamespace) > 1) {
if (! str_contains($this->controller, '\\') && strlen($this->defaultNamespace) > 1) {
$this->controller = '\\' . ltrim(
str_replace(
'/',

Some files were not shown because too many files have changed in this diff Show More