diff --git a/app/Views/errors/cli/error_exception.php b/app/Views/errors/cli/error_exception.php index 98d83b0ed3a6..9f47d25141d2 100644 --- a/app/Views/errors/cli/error_exception.php +++ b/app/Views/errors/cli/error_exception.php @@ -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 @@ $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 @@ $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 . ')'; diff --git a/app/Views/errors/html/error_exception.php b/app/Views/errors/html/error_exception.php index b58e6bd76382..44d749892473 100644 --- a/app/Views/errors/html/error_exception.php +++ b/app/Views/errors/html/error_exception.php @@ -61,10 +61,10 @@
     Caused by:
-    getCode() ? ' #' . $prevException->getCode() : '') ?>
+    getCode() ? ' #' . $prevException->getCode() : '') ?>
 
     getMessage())) ?>
-    getMessage())) ?>"
+    getMessage())) ?>"
        rel="noreferrer" target="_blank">search →
     getFile()) . ':' . $prevException->getLine()) ?>
     
@@ -121,7 +121,7 @@ getParameters(); } diff --git a/phpstan-baseline.php b/phpstan-baseline.php index d433aabf725e..9d658e715aad 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -1341,11 +1341,6 @@ '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 @@ '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 @@ '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 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/CommonSingleServiceTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Parameter \\#1 \\$expected of method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) expects class\\-string\\, false given\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/tests/system/CommonSingleServiceTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Accessing offset \'BAR\' directly on \\$_SERVER is discouraged\\.$#', 'count' => 1, diff --git a/rector.php b/rector.php index 8c889955123d..b9d51f872fdc 100644 --- a/rector.php +++ b/rector.php @@ -46,6 +46,10 @@ 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\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 @@ 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 @@ 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, diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index c8c1767a9d83..78d31eae0d7f 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -163,10 +163,10 @@ private function loadComposerAutoloader(Modules $modules): void 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 @@ public function register() */ 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 @@ public function loadClass(string $class): void */ 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 @@ private function loadComposerNamespaces(ClassLoader $composer, array $composerPa 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; } diff --git a/system/Autoloader/FileLocator.php b/system/Autoloader/FileLocator.php index 95490f8195b6..97da0fa275eb 100644 --- a/system/Autoloader/FileLocator.php +++ b/system/Autoloader/FileLocator.php @@ -53,12 +53,12 @@ public function locateFile(string $file, ?string $folder = null, string $ext = ' $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 @@ public function locateFile(string $file, ?string $folder = null, string $ext = ' // 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 @@ public function search(string $path, string $ext = 'php', bool $prioritizeApp = if ($prioritizeApp) { $foundPaths[] = $fullPath; - } elseif (strpos($fullPath, APPPATH) === 0) { + } elseif (str_starts_with($fullPath, APPPATH)) { $appPaths[] = $fullPath; } else { $foundPaths[] = $fullPath; @@ -216,7 +216,7 @@ protected function ensureExt(string $path, string $ext): string if ($ext !== '') { $ext = '.' . $ext; - if (substr($path, -strlen($ext)) !== $ext) { + if (! str_ends_with($path, $ext)) { $path .= $ext; } } diff --git a/system/Autoloader/FileLocatorCached.php b/system/Autoloader/FileLocatorCached.php index 215f297c36b9..adf453308de3 100644 --- a/system/Autoloader/FileLocatorCached.php +++ b/system/Autoloader/FileLocatorCached.php @@ -23,8 +23,6 @@ */ 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(); } diff --git a/system/BaseModel.php b/system/BaseModel.php index a75b0f6a979f..5d08ec59e04c 100644 --- a/system/BaseModel.php +++ b/system/BaseModel.php @@ -634,7 +634,7 @@ public function find($id = null) */ public function findColumn(string $columnName) { - if (strpos($columnName, ',') !== false) { + if (str_contains($columnName, ',')) { throw DataException::forFindColumnHaveMultipleColumns(); } @@ -1397,19 +1397,12 @@ protected function setDate(?int $userData = null) */ 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 @@ protected function intToDate(int $value) */ 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, + }; } /** diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index 490c9135789a..865241b75cbf 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -592,7 +592,7 @@ public static function color(string $text, string $foreground, ?string $backgrou $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); diff --git a/system/CLI/Commands.php b/system/CLI/Commands.php index 67bfe5d4445c..30bd2c2652cd 100644 --- a/system/CLI/Commands.php +++ b/system/CLI/Commands.php @@ -183,7 +183,7 @@ protected function getCommandAlternatives(string $name, array $collection): arra 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; } } diff --git a/system/CLI/GeneratorTrait.php b/system/CLI/GeneratorTrait.php index 47701e0f7b28..5640a7ae1ac8 100644 --- a/system/CLI/GeneratorTrait.php +++ b/system/CLI/GeneratorTrait.php @@ -268,7 +268,7 @@ protected function qualifyClassName(): string // 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 } diff --git a/system/CLI/InputOutput.php b/system/CLI/InputOutput.php index 5b6c1da02f4d..b69c19e2eee1 100644 --- a/system/CLI/InputOutput.php +++ b/system/CLI/InputOutput.php @@ -21,7 +21,7 @@ class InputOutput /** * Is the readline library on the system? */ - private bool $readlineSupport; + private readonly bool $readlineSupport; public function __construct() { diff --git a/system/Cache/Handlers/PredisHandler.php b/system/Cache/Handlers/PredisHandler.php index d08205222a30..59e35aa4208f 100644 --- a/system/Cache/Handlers/PredisHandler.php +++ b/system/Cache/Handlers/PredisHandler.php @@ -88,22 +88,12 @@ public function get(string $key) 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, + }; } /** diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php index e80119de8906..9e1003d10ac2 100644 --- a/system/Cache/Handlers/RedisHandler.php +++ b/system/Cache/Handlers/RedisHandler.php @@ -114,22 +114,12 @@ public function get(string $key) 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, + }; } /** diff --git a/system/Cache/ResponseCache.php b/system/Cache/ResponseCache.php index e584b56314ae..388931813c7c 100644 --- a/system/Cache/ResponseCache.php +++ b/system/Cache/ResponseCache.php @@ -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; } /** diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 1d30e436b568..03ba1550d0bc 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -871,7 +871,7 @@ protected function startController() $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 @@ public function storePreviousURL($uri) } // 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; } diff --git a/system/Commands/Database/CreateDatabase.php b/system/Commands/Database/CreateDatabase.php index 4122e315ff9d..0c8d2016dc93 100644 --- a/system/Commands/Database/CreateDatabase.php +++ b/system/Commands/Database/CreateDatabase.php @@ -109,7 +109,7 @@ public function run(array $params) $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'); diff --git a/system/Commands/Encryption/GenerateKey.php b/system/Commands/Encryption/GenerateKey.php index 4409560b0440..820ec48137c9 100644 --- a/system/Commands/Encryption/GenerateKey.php +++ b/system/Commands/Encryption/GenerateKey.php @@ -168,7 +168,7 @@ protected function writeNewEncryptionKeyToFile(string $oldKey, string $newKey): $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; } diff --git a/system/Commands/Utilities/Publish.php b/system/Commands/Utilities/Publish.php index 35a9163404dc..3e19685cba81 100644 --- a/system/Commands/Utilities/Publish.php +++ b/system/Commands/Utilities/Publish.php @@ -85,13 +85,13 @@ public function run(array $params) 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'); diff --git a/system/Commands/Utilities/Routes/AutoRouteCollector.php b/system/Commands/Utilities/Routes/AutoRouteCollector.php index 6a3f1ae12b90..73009b9c9eb8 100644 --- a/system/Commands/Utilities/Routes/AutoRouteCollector.php +++ b/system/Commands/Utilities/Routes/AutoRouteCollector.php @@ -20,22 +20,11 @@ */ 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; } /** diff --git a/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php b/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php index dd32c1a3e1cf..8cbd81fbb02e 100644 --- a/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php +++ b/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php @@ -24,43 +24,19 @@ 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 - */ - 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 $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; } /** diff --git a/system/Commands/Utilities/Routes/AutoRouterImproved/ControllerMethodReader.php b/system/Commands/Utilities/Routes/AutoRouterImproved/ControllerMethodReader.php index 70232f5fd1aa..e08a16ff7a60 100644 --- a/system/Commands/Utilities/Routes/AutoRouterImproved/ControllerMethodReader.php +++ b/system/Commands/Utilities/Routes/AutoRouterImproved/ControllerMethodReader.php @@ -24,27 +24,17 @@ */ final class ControllerMethodReader { - /** - * @var string the default namespace - */ - private string $namespace; - - /** - * @var list - */ - private array $httpMethods; - - private bool $translateURIDashes; - private bool $translateUriToCamelCase; + private readonly bool $translateURIDashes; + private readonly bool $translateUriToCamelCase; /** - * @param string $namespace the default namespace + * @param string $namespace the default namespace + * @param list $httpMethods */ - 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 @@ public function read(string $class, string $defaultController = 'Home', string $ $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); diff --git a/system/Commands/Utilities/Routes/ControllerFinder.php b/system/Commands/Utilities/Routes/ControllerFinder.php index 0dbd09ea5890..71de1681b547 100644 --- a/system/Commands/Utilities/Routes/ControllerFinder.php +++ b/system/Commands/Utilities/Routes/ControllerFinder.php @@ -22,20 +22,15 @@ */ 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'); } /** diff --git a/system/Commands/Utilities/Routes/ControllerMethodReader.php b/system/Commands/Utilities/Routes/ControllerMethodReader.php index 86294c646316..c443b669465a 100644 --- a/system/Commands/Utilities/Routes/ControllerMethodReader.php +++ b/system/Commands/Utilities/Routes/ControllerMethodReader.php @@ -23,17 +23,11 @@ */ 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; } /** diff --git a/system/Commands/Utilities/Routes/FilterCollector.php b/system/Commands/Utilities/Routes/FilterCollector.php index e51e4595df61..002a529b953e 100644 --- a/system/Commands/Utilities/Routes/FilterCollector.php +++ b/system/Commands/Utilities/Routes/FilterCollector.php @@ -27,16 +27,14 @@ */ 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 + ) { } /** diff --git a/system/Commands/Utilities/Routes/FilterFinder.php b/system/Commands/Utilities/Routes/FilterFinder.php index 57128e4a53d1..82ea26979517 100644 --- a/system/Commands/Utilities/Routes/FilterFinder.php +++ b/system/Commands/Utilities/Routes/FilterFinder.php @@ -26,8 +26,8 @@ */ 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 @@ public function find(string $uri): array $this->filters->initialize($uri); return $this->filters->getFilters(); - } catch (RedirectException $e) { + } catch (RedirectException) { return [ 'before' => [], 'after' => [], ]; - } catch (PageNotFoundException $e) { + } catch (PageNotFoundException) { return [ 'before' => [''], 'after' => [''], diff --git a/system/Commands/Utilities/Routes/SampleURIGenerator.php b/system/Commands/Utilities/Routes/SampleURIGenerator.php index 3b71e2b1752d..45eb2f93201b 100644 --- a/system/Commands/Utilities/Routes/SampleURIGenerator.php +++ b/system/Commands/Utilities/Routes/SampleURIGenerator.php @@ -23,7 +23,7 @@ */ final class SampleURIGenerator { - private RouteCollection $routes; + private readonly RouteCollection $routes; /** * Sample URI path for placeholder. @@ -53,7 +53,7 @@ public function get(string $routeKey): string { $sampleUri = $routeKey; - if (strpos($routeKey, '{locale}') !== false) { + if (str_contains($routeKey, '{locale}')) { $sampleUri = str_replace( '{locale}', config(App::class)->defaultLocale, diff --git a/system/Common.php b/system/Common.php index 75d185255e48..f96e9f100f00 100644 --- a/system/Common.php +++ b/system/Common.php @@ -94,29 +94,18 @@ function clean_path(string $path): string // 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 @@ function env(string $key, $default = null) } // 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 @@ function helper($filenames): void $appHelper = null; $localIncludes = []; - if (strpos($filename, '_helper') === false) { + if (! str_contains($filename, '_helper')) { $filename .= '_helper'; } @@ -613,7 +594,7 @@ function helper($filenames): void // 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 @@ function helper($filenames): void $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 @@ function view_cell(string $library, $params = null, int $ttl = 0, ?string $cache */ 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 @@ function class_basename($class) function class_uses_recursive($class) { if (is_object($class)) { - $class = get_class($class); + $class = $class::class; } $results = []; diff --git a/system/ComposerScripts.php b/system/ComposerScripts.php index 3e3ec7bd1db7..661247dab532 100644 --- a/system/ComposerScripts.php +++ b/system/ComposerScripts.php @@ -73,7 +73,7 @@ public static function postUpdate() 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; } diff --git a/system/Config/BaseConfig.php b/system/Config/BaseConfig.php index 51aac022b271..8a82cbf7ce64 100644 --- a/system/Config/BaseConfig.php +++ b/system/Config/BaseConfig.php @@ -119,10 +119,10 @@ public function __construct() $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); } diff --git a/system/Config/DotEnv.php b/system/Config/DotEnv.php index 4abb2a038c10..db7152fd09d5 100644 --- a/system/Config/DotEnv.php +++ b/system/Config/DotEnv.php @@ -70,12 +70,12 @@ public function parse(): ?array 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 @@ protected function setVariable(string $name, string $value = '') 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 @@ protected function sanitizeValue(string $value): string */ protected function resolveNestedVariables(string $value): string { - if (strpos($value, '$') !== false) { + if (str_contains($value, '$')) { $value = preg_replace_callback( '/\${([a-zA-Z0-9_\.]+)}/', function ($matchedPatterns) { diff --git a/system/Config/Factories.php b/system/Config/Factories.php index d32f16a5739b..f8102118bc1d 100644 --- a/system/Config/Factories.php +++ b/system/Config/Factories.php @@ -331,7 +331,7 @@ class_exists($alias, false) */ private static function isNamespaced(string $alias): bool { - return strpos($alias, '\\') !== false; + return str_contains($alias, '\\'); } /** @@ -349,10 +349,10 @@ private static function verifyPreferApp(array $options, string $alias): bool // 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 @@ public static function injectMock(string $component, string $alias, object $inst // 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; diff --git a/system/Cookie/Cookie.php b/system/Cookie/Cookie.php index 7a0532e9eefb..78dc44258eb9 100644 --- a/system/Cookie/Cookie.php +++ b/system/Cookie/Cookie.php @@ -182,7 +182,7 @@ public static function fromHeaderString(string $cookie, bool $raw = false) 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 @@ protected function validateName(string $name, bool $raw): void */ 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(); } } diff --git a/system/Cookie/CookieStore.php b/system/Cookie/CookieStore.php index d5334f6638ba..05ebf9925ee6 100644 --- a/system/Cookie/CookieStore.php +++ b/system/Cookie/CookieStore.php @@ -225,7 +225,7 @@ public function getIterator(): Traversable 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]); diff --git a/system/DataCaster/Cast/ArrayCast.php b/system/DataCaster/Cast/ArrayCast.php index f3fb5476b5c6..4bb0f4c74093 100644 --- a/system/DataCaster/Cast/ArrayCast.php +++ b/system/DataCaster/Cast/ArrayCast.php @@ -30,7 +30,7 @@ public static function get( 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]); } diff --git a/system/DataCaster/DataCaster.php b/system/DataCaster/DataCaster.php index 63650408e5f8..854a0b50b32c 100644 --- a/system/DataCaster/DataCaster.php +++ b/system/DataCaster/DataCaster.php @@ -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|null $castHandlers Custom convert handlers * @param array|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 ( diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 905578bff3b7..1f0807cdbbde 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -316,7 +316,7 @@ public function __construct($tableName, ConnectionInterface $db, ?array $options $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 @@ protected function maxMinAvgSum(string $select = '', string $alias = '', string 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 @@ protected function maxMinAvgSum(string $select = '', string $alias = '', string */ protected function createAliasFromTable(string $item): string { - if (strpos($item, '.') !== false) { + if (str_contains($item, '.')) { $item = explode('.', $item); return end($item); @@ -577,7 +577,7 @@ public function from($from, bool $overwrite = false): self } 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 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $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 @@ public function insert($set = null, ?bool $escape = null) */ 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 @@ protected function trackAliases($table) // 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 @@ protected function compileWhereHaving(string $qbKey): string 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); } diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 0d22d9af2a8e..e0bd7bb51217 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1093,7 +1093,7 @@ public function protectIdentifiers($item, bool $prefixSingle = false, ?bool $pro // 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 @@ public function protectIdentifiers($item, bool $prefixSingle = false, ?bool $pro // 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 @@ private function protectDotItem(string $item, string $alias, bool $protectIdenti } // 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 @@ public function escapeIdentifiers($item) if (ctype_digit($item) || $item[0] === "'" || ($this->escapeChar !== '"' && $item[0] === '"') - || strpos($item, '(') !== false) { + || str_contains($item, '(')) { return $item; } @@ -1256,7 +1256,7 @@ public function escapeIdentifiers($item) 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 public function affectedRows(): int; 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 @@ public function callFunction(string $functionName, ...$params): bool { $driver = $this->getDriverFunctionPrefix(); - if (strpos($driver, $functionName) === false) { + if (! str_contains($driver, $functionName)) { $functionName = $driver . $functionName; } diff --git a/system/Database/Database.php b/system/Database/Database.php index 8fda6dc9fb01..c2bc66d30d11 100644 --- a/system/Database/Database.php +++ b/system/Database/Database.php @@ -46,7 +46,7 @@ public function load(array $params = [], string $alias = '') 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 @@ protected function parseDSN(array $params): array */ protected function initDriver(string $driver, string $class, $argument): object { - $classname = (strpos($driver, '\\') === false) + $classname = (! str_contains($driver, '\\')) ? "CodeIgniter\\Database\\{$driver}\\{$class}" : $driver . '\\' . $class; diff --git a/system/Database/Forge.php b/system/Database/Forge.php index 93f1bd550d4c..797b685e861c 100644 --- a/system/Database/Forge.php +++ b/system/Database/Forge.php @@ -383,7 +383,7 @@ public function addField($fields) ]); $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 @@ public function dropTable(string $tableName, bool $ifExists = false, bool $casca 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)); } diff --git a/system/Database/MigrationRunner.php b/system/Database/MigrationRunner.php index 8586ef5600d6..719d45c15592 100644 --- a/system/Database/MigrationRunner.php +++ b/system/Database/MigrationRunner.php @@ -445,7 +445,7 @@ public function findNamespaceMigrations(string $namespace): array */ protected function migrationFromFile(string $path, string $namespace) { - if (substr($path, -4) !== '.php') { + if (! str_ends_with($path, '.php')) { return false; } diff --git a/system/Database/OCI8/Connection.php b/system/Database/OCI8/Connection.php index a813aacd634b..be7eb37cb9a9 100644 --- a/system/Database/OCI8/Connection.php +++ b/system/Database/OCI8/Connection.php @@ -223,7 +223,7 @@ protected function execute(string $sql) 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 @@ public function parseInsertTableName(string $sql): string 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 @@ protected function _listTables(bool $prefixLimit = false, ?string $tableName = n */ 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 @@ protected function _listColumns(string $table = ''): string */ 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 @@ protected function _fieldData(string $table): array */ 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 @@ protected function buildDSN() 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, '/') : ''; diff --git a/system/Database/OCI8/Forge.php b/system/Database/OCI8/Forge.php index bab1758a1349..69a42ed1dbeb 100644 --- a/system/Database/OCI8/Forge.php +++ b/system/Database/OCI8/Forge.php @@ -132,7 +132,7 @@ protected function _alterTable(string $alterType, string $table, $processedField // 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 @@ protected function _processColumn(array $processedField): string { $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'] . ')'; diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index b82cad80e9d0..45e30eb65365 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -358,10 +358,10 @@ protected function _indexData(string $table): array $_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 @@ protected function buildDSN() } // If UNIX sockets are used, we shouldn't set a port - if (strpos($this->hostname, '/') !== false) { + if (str_contains($this->hostname, '/')) { $this->port = ''; } diff --git a/system/Database/Query.php b/system/Database/Query.php index ebd9c279bdef..11085a91f6a0 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -13,10 +13,12 @@ namespace CodeIgniter\Database; +use Stringable; + /** * Query builder */ -class Query implements QueryInterface +class Query implements QueryInterface, Stringable { /** * The query string, as provided by the user. diff --git a/system/Database/RawSql.php b/system/Database/RawSql.php index 0a2abf0d1510..cb16131fe4c3 100644 --- a/system/Database/RawSql.php +++ b/system/Database/RawSql.php @@ -13,10 +13,12 @@ namespace CodeIgniter\Database; +use Stringable; + /** * @see \CodeIgniter\Database\RawSqlTest */ -class RawSql +class RawSql implements Stringable { /** * @var string Raw SQL string diff --git a/system/Database/SQLSRV/Builder.php b/system/Database/SQLSRV/Builder.php index 84531631d017..a624dced38d2 100755 --- a/system/Database/SQLSRV/Builder.php +++ b/system/Database/SQLSRV/Builder.php @@ -72,7 +72,7 @@ protected function _fromTables(): string $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 @@ private function getFullName(string $table): string { $alias = ''; - if (strpos($table, ' ') !== false) { + if (str_contains($table, ' ')) { $alias = explode(' ', $table); $table = array_shift($alias); $alias = ' ' . implode(' ', $alias); @@ -451,7 +451,7 @@ protected function maxMinAvgSum(string $select = '', string $alias = '', string throw DataException::forEmptyInputGiven('Select'); } - if (strpos($select, ',') !== false) { + if (str_contains($select, ',')) { throw DataException::forInvalidArgument('Column name not separated by comma'); } diff --git a/system/Database/SQLSRV/Connection.php b/system/Database/SQLSRV/Connection.php index 739cb064977e..411470d8e34c 100755 --- a/system/Database/SQLSRV/Connection.php +++ b/system/Database/SQLSRV/Connection.php @@ -123,7 +123,7 @@ public function connect(bool $persistent = false) 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 @@ protected function _indexData(string $table): array $_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; diff --git a/system/Database/SQLite3/Connection.php b/system/Database/SQLite3/Connection.php index 07dd84e7342f..d15c64213952 100644 --- a/system/Database/SQLite3/Connection.php +++ b/system/Database/SQLite3/Connection.php @@ -82,7 +82,7 @@ public function connect(bool $persistent = false) } 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; } diff --git a/system/Database/SQLite3/Forge.php b/system/Database/SQLite3/Forge.php index a3cb93c5da68..32e447829c29 100644 --- a/system/Database/SQLite3/Forge.php +++ b/system/Database/SQLite3/Forge.php @@ -169,7 +169,7 @@ protected function _alterTable(string $alterType, string $table, $processedField */ 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'] . ')'; } diff --git a/system/Database/SQLite3/Table.php b/system/Database/SQLite3/Table.php index c40df0329cde..5db002a1060b 100644 --- a/system/Database/SQLite3/Table.php +++ b/system/Database/SQLite3/Table.php @@ -98,7 +98,7 @@ public function fromTable(string $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 @@ protected function formatFields($fields) */ private function isIntegerType(string $type): bool { - return strpos(strtoupper($type), 'INT') !== false; + return str_contains(strtoupper($type), 'INT'); } /** diff --git a/system/Database/Seeder.php b/system/Database/Seeder.php index 364c81775c59..be7cfcdf8a8c 100644 --- a/system/Database/Seeder.php +++ b/system/Database/Seeder.php @@ -125,7 +125,7 @@ public function call(string $class) 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)) { diff --git a/system/Debug/BaseExceptionHandler.php b/system/Debug/BaseExceptionHandler.php index d650df4599e1..dbccdcd07790 100644 --- a/system/Debug/BaseExceptionHandler.php +++ b/system/Debug/BaseExceptionHandler.php @@ -83,8 +83,8 @@ protected function collectVars(Throwable $exception, int $statusCode): array } 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 @@ private function maskData($args, array $keysToMask, string $path = '') $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 @@ protected static function highlightFile(string $file, int $lineNumber, int $line try { $source = file_get_contents($file); - } catch (Throwable $e) { + } catch (Throwable) { return false; } diff --git a/system/Debug/ExceptionHandler.php b/system/Debug/ExceptionHandler.php index 03576f2ffa69..d6f97b76a32b 100644 --- a/system/Debug/ExceptionHandler.php +++ b/system/Debug/ExceptionHandler.php @@ -56,7 +56,7 @@ public function handle( 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 @@ public function handle( ); } - 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) : ''; diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php index a5daa1032617..e5f7ecb04881 100644 --- a/system/Debug/Exceptions.php +++ b/system/Debug/Exceptions.php @@ -108,8 +108,8 @@ public function __construct(ExceptionsConfig $config) */ 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 @@ public function exceptionHandler(Throwable $exception) $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 @@ public function exceptionHandler(Throwable $exception) 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 @@ public function exceptionHandler(Throwable $exception) 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 @@ public function exceptionHandler(Throwable $exception) 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 @@ public function shutdownHandler() 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 @@ protected function collectVars(Throwable $exception, int $statusCode): array } 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 @@ private function maskData($args, array $keysToMask, string $path = '') $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 @@ private function handleDeprecationError(string $message, ?string $file = null, ? */ 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 @@ public static function highlightFile(string $file, int $lineNumber, int $lines = try { $source = file_get_contents($file); - } catch (Throwable $e) { + } catch (Throwable) { return false; } @@ -609,23 +597,12 @@ private static function renderBacktrace(array $backtrace): string $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( diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index 22693e035e68..c631e4162da4 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -410,7 +410,7 @@ public function prepare(?RequestInterface $request = null, ?ResponseInterface $r // 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 @@ public function prepare(?RequestInterface $request = null, ?ResponseInterface $r . $kintScript . PHP_EOL; - if (strpos($response->getBody(), '') !== false) { + if (str_contains($response->getBody(), '')) { $response->setBody( preg_replace( '//', diff --git a/system/Debug/Toolbar/Collectors/Database.php b/system/Debug/Toolbar/Collectors/Database.php index 4c91ff50af47..ee9f829b05b8 100644 --- a/system/Debug/Toolbar/Collectors/Database.php +++ b/system/Debug/Toolbar/Collectors/Database.php @@ -163,7 +163,7 @@ public function display(): array } // 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']; } diff --git a/system/Debug/Toolbar/Collectors/Files.php b/system/Debug/Toolbar/Collectors/Files.php index df226d00f6cb..a573388f960e 100644 --- a/system/Debug/Toolbar/Collectors/Files.php +++ b/system/Debug/Toolbar/Collectors/Files.php @@ -62,7 +62,7 @@ public function display(): array foreach ($rawFiles as $file) { $path = clean_path($file); - if (strpos($path, 'SYSTEMPATH') !== false) { + if (str_contains($path, 'SYSTEMPATH')) { $coreFiles[] = [ 'path' => $path, 'name' => basename($file), diff --git a/system/Debug/Toolbar/Collectors/Routes.php b/system/Debug/Toolbar/Collectors/Routes.php index 19b883ec1972..737c86bff692 100644 --- a/system/Debug/Toolbar/Collectors/Routes.php +++ b/system/Debug/Toolbar/Collectors/Routes.php @@ -65,7 +65,7 @@ public function display(): array } 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. diff --git a/system/Email/Email.php b/system/Email/Email.php index e6c6728234ca..a686ca0ca06e 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -660,7 +660,7 @@ public function setMessage($body) 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 @@ public function setHeader($header, $value) 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 @@ protected function getEncoding() } 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 @@ public function wordWrap($str, $charlim = null) $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 @@ protected function prepQuotedPrintable($str) $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 @@ protected function unwrapSpecials() { $this->finalBody = preg_replace_callback( '/\{unwrap\}(.*?)\{\/unwrap\}/si', - [ - $this, - 'removeNLCallback', - ], + $this->removeNLCallback(...), $this->finalBody ); } @@ -1675,7 +1672,7 @@ protected function unwrapSpecials() */ 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 @@ protected function sendWithSmtp() $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 @@ protected function SMTPAuthenticate() $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 @@ protected function SMTPAuthenticate() $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 @@ protected function SMTPAuthenticate() $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; diff --git a/system/Entity/Cast/ArrayCast.php b/system/Entity/Cast/ArrayCast.php index 02b67078bd73..1c810645dec6 100644 --- a/system/Entity/Cast/ArrayCast.php +++ b/system/Entity/Cast/ArrayCast.php @@ -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); } diff --git a/system/Entity/Entity.php b/system/Entity/Entity.php index f7242103f2ce..5de8a42187a4 100644 --- a/system/Entity/Entity.php +++ b/system/Entity/Entity.php @@ -181,7 +181,7 @@ public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recu { $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( diff --git a/system/Entity/Exceptions/CastException.php b/system/Entity/Exceptions/CastException.php index f0e95576c96d..90d3885d9b62 100644 --- a/system/Entity/Exceptions/CastException.php +++ b/system/Entity/Exceptions/CastException.php @@ -43,25 +43,14 @@ public static function forInvalidInterface(string $class) */ 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')), + }; } /** diff --git a/system/Exceptions/FrameworkException.php b/system/Exceptions/FrameworkException.php index a223f8ec927a..1fe47be49a6b 100644 --- a/system/Exceptions/FrameworkException.php +++ b/system/Exceptions/FrameworkException.php @@ -64,7 +64,7 @@ public static function forCopyError(string $path) */ 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.', diff --git a/system/Files/File.php b/system/Files/File.php index c1c97b7d528b..02c8f181b19b 100644 --- a/system/Files/File.php +++ b/system/Files/File.php @@ -76,16 +76,11 @@ public function getSize() */ 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 @@ public function getDestination(string $destination, string $delimiter = '_', int $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))) { diff --git a/system/Files/FileCollection.php b/system/Files/FileCollection.php index 97d6bc8e31b5..b9456dcc15ba 100644 --- a/system/Files/FileCollection.php +++ b/system/Files/FileCollection.php @@ -85,7 +85,7 @@ final protected static function filterFiles(array $files, string $directory): ar { $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 @@ public function add($paths, bool $recursive = true) try { // Test for a directory self::resolveDirectory($path); - } catch (FileException $e) { + } catch (FileException) { $this->addFile($path); continue; diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index 963638bdfb8f..d8e22835e2ed 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -197,7 +197,7 @@ private function runBefore(array $filterClasses) $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 @@ private function runAfter(array $filterClasses): ResponseInterface $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 @@ private function getCleanName(string $name): array { $arguments = []; - if (strpos($name, ':') !== false) { + if (str_contains($name, ':')) { [$name, $arguments] = explode(':', $name); $arguments = explode(',', $arguments); diff --git a/system/Filters/InvalidChars.php b/system/Filters/InvalidChars.php index da5b09fabc87..542b12d7ffbe 100644 --- a/system/Filters/InvalidChars.php +++ b/system/Filters/InvalidChars.php @@ -92,7 +92,7 @@ public function after(RequestInterface $request, ResponseInterface $response, $a protected function checkEncoding($value) { if (is_array($value)) { - array_map([$this, 'checkEncoding'], $value); + array_map($this->checkEncoding(...), $value); return $value; } @@ -114,7 +114,7 @@ protected function checkEncoding($value) protected function checkControl($value) { if (is_array($value)) { - array_map([$this, 'checkControl'], $value); + array_map($this->checkControl(...), $value); return $value; } diff --git a/system/Filters/PageCache.php b/system/Filters/PageCache.php index ea6121562d0a..a3d3af832a65 100644 --- a/system/Filters/PageCache.php +++ b/system/Filters/PageCache.php @@ -26,7 +26,7 @@ */ class PageCache implements FilterInterface { - private ResponseCache $pageCache; + private readonly ResponseCache $pageCache; public function __construct() { diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 8f7ba0a30707..725195918209 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -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 @@ protected function parseOptions(array $options) 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 @@ public function send(string $method, string $url) // 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 @@ protected function setResponseHeaders(array $headers = []) } 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])) { diff --git a/system/HTTP/ContentSecurityPolicy.php b/system/HTTP/ContentSecurityPolicy.php index c4b0616a0889..945c3e08d3ce 100644 --- a/system/HTTP/ContentSecurityPolicy.php +++ b/system/HTTP/ContentSecurityPolicy.php @@ -802,7 +802,7 @@ protected function addToHeader(string $name, $values = null) $reportOnly = $this->reportOnly; } - if (strpos($value, 'nonce-') === 0) { + if (str_starts_with($value, 'nonce-')) { $value = "'{$value}'"; } diff --git a/system/HTTP/DownloadResponse.php b/system/HTTP/DownloadResponse.php index 11bf2f9091cc..6b293fbca239 100644 --- a/system/HTTP/DownloadResponse.php +++ b/system/HTTP/DownloadResponse.php @@ -38,7 +38,7 @@ class DownloadResponse extends Response /** * mime set flag */ - private bool $setMime; + private readonly bool $setMime; /** * Download for binary diff --git a/system/HTTP/Files/FileCollection.php b/system/HTTP/Files/FileCollection.php index 8b5cb0ef262c..079d5e73114f 100644 --- a/system/HTTP/Files/FileCollection.php +++ b/system/HTTP/Files/FileCollection.php @@ -59,7 +59,7 @@ public function getFile(string $name) $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 @@ public function getFileMultiple(string $name) $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 @@ public function hasFile(string $fileID): bool { $this->populateFiles(); - if (strpos($fileID, '.') !== false) { + if (str_contains($fileID, '.')) { $segments = explode('.', $fileID); $el = $this->files; diff --git a/system/HTTP/Files/UploadedFile.php b/system/HTTP/Files/UploadedFile.php index d993d6c91e4e..b40ba1ef3101 100644 --- a/system/HTTP/Files/UploadedFile.php +++ b/system/HTTP/Files/UploadedFile.php @@ -153,7 +153,7 @@ public function move(string $targetPath, ?string $name = null, bool $overwrite = try { $this->hasMoved = move_uploaded_file($this->path, $destination); - } catch (Exception $e) { + } catch (Exception) { $error = error_get_last(); $message = strip_tags($error['message'] ?? ''); diff --git a/system/HTTP/Header.php b/system/HTTP/Header.php index 10cbf1b6cea6..3832a4413a47 100644 --- a/system/HTTP/Header.php +++ b/system/HTTP/Header.php @@ -13,6 +13,8 @@ namespace CodeIgniter\HTTP; +use Stringable; + /** * Class Header * @@ -20,7 +22,7 @@ * * @see \CodeIgniter\HTTP\HeaderTest */ -class Header +class Header implements Stringable { /** * The name of the header. diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index 20f3804fb713..ec13e40f6ff5 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -141,7 +141,7 @@ public function __construct($config, ?URI $uri = null, $body = 'php://input', ?U $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 @@ private function getPostMaxSize(): int { $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 @@ public function detectPath(string $protocol = ''): string $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 @@ protected function parseRequestURI(): string // 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 @@ protected function parseQueryString(): string 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 @@ public function negotiate(string $type, array $supported, bool $strictMatch = fa $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 @@ public function is(string $type): bool } 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 @@ public function getDefaultLocale(): string 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); diff --git a/system/HTTP/RedirectResponse.php b/system/HTTP/RedirectResponse.php index cd1108fb2dbb..95bfadcd4299 100644 --- a/system/HTTP/RedirectResponse.php +++ b/system/HTTP/RedirectResponse.php @@ -37,7 +37,7 @@ public function to(string $uri, ?int $code = null, string $method = 'auto') { // 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); } diff --git a/system/HTTP/RequestTrait.php b/system/HTTP/RequestTrait.php index 3f935ea6ab4c..cfdc52b55f69 100644 --- a/system/HTTP/RequestTrait.php +++ b/system/HTTP/RequestTrait.php @@ -86,7 +86,7 @@ public function getIPAddress(): string // @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 @@ public function getIPAddress(): string } // If the proxy entry doesn't match the IP protocol - skip it - if (strpos($proxyIP, $separator) === false) { + if (! str_contains($proxyIP, $separator)) { continue; } diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 40b9c3f57067..2d4295116807 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -448,7 +448,7 @@ public function redirect(string $uri, string $method = 'auto', ?int $code = null 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 @@ public function redirect(string $uri, string $method = 'auto', ?int $code = null $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); diff --git a/system/HTTP/SiteURI.php b/system/HTTP/SiteURI.php index 02ea01f6e7a6..def61b65e17b 100644 --- a/system/HTTP/SiteURI.php +++ b/system/HTTP/SiteURI.php @@ -28,7 +28,7 @@ class SiteURI extends URI /** * The current baseURL. */ - private URI $baseURL; + private readonly URI $baseURL; /** * The path part of baseURL. diff --git a/system/HTTP/SiteURIFactory.php b/system/HTTP/SiteURIFactory.php index e0c20b617443..c87898c0470e 100644 --- a/system/HTTP/SiteURIFactory.php +++ b/system/HTTP/SiteURIFactory.php @@ -26,13 +26,8 @@ */ 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 @@ public function detectRoutePath(string $protocol = ''): string $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 @@ private function parseRequestURI(): string // 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 @@ private function parseQueryString(): string return '/'; } - if (strncmp($query, '/', 1) === 0) { + if (str_starts_with($query, '/')) { $parts = explode('?', $query, 2); $path = $parts[0]; $newQuery = $parts[1] ?? ''; diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index 37290a329791..efa99cf778a8 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -17,13 +17,14 @@ 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 @@ public static function createURIString( } if (isset($path) && $path !== '') { - $uri .= substr($uri, -1, 1) !== '/' + $uri .= ! str_ends_with($uri, '/') ? '/' . ltrim($path, '/') : ltrim($path, '/'); } @@ -230,12 +231,12 @@ public static function removeDotSegments(string $path): string $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 @@ private function changeSchemeAndPath(string $scheme, string $path): array $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 @@ public function refreshPath() */ public function setQuery(string $query) { - if (strpos($query, '#') !== false) { + if (str_contains($query, '#')) { if ($this->silent) { return $this; } @@ -888,7 +889,7 @@ public function setQuery(string $query) } // Can't have leading ? - if ($query !== '' && strpos($query, '?') === 0) { + if ($query !== '' && str_starts_with($query, '?')) { $query = substr($query, 1); } @@ -1010,10 +1011,10 @@ protected function filterPath(?string $path = null): string $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 @@ public function resolveRelativeURI(string $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)); diff --git a/system/HTTP/UserAgent.php b/system/HTTP/UserAgent.php index 2fb0b5b64083..6a5104779a92 100644 --- a/system/HTTP/UserAgent.php +++ b/system/HTTP/UserAgent.php @@ -14,13 +14,14 @@ 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 diff --git a/system/Helpers/filesystem_helper.php b/system/Helpers/filesystem_helper.php index abb2ad703fb7..2b86654c960e 100644 --- a/system/Helpers/filesystem_helper.php +++ b/system/Helpers/filesystem_helper.php @@ -55,7 +55,7 @@ function directory_map(string $sourceDir, int $directoryDepth = 0, bool $hidden closedir($fp); return $fileData; - } catch (Throwable $e) { + } catch (Throwable) { return []; } } @@ -131,7 +131,7 @@ function write_file(string $path, string $data, string $mode = 'wb'): bool fclose($fp); return is_int($result); - } catch (Throwable $e) { + } catch (Throwable) { return false; } } @@ -180,7 +180,7 @@ function delete_files(string $path, bool $delDir = false, bool $htdocs = false, } return true; - } catch (Throwable $e) { + } catch (Throwable) { return false; } } @@ -229,7 +229,7 @@ function get_filenames( } } } - } catch (Throwable $e) { + } catch (Throwable) { return []; } @@ -279,7 +279,7 @@ function get_dir_file_info(string $sourceDir, bool $topLevelOnly = true, bool $r closedir($fp); return $fileData; - } catch (Throwable $fe) { + } catch (Throwable) { return []; } } diff --git a/system/Helpers/form_helper.php b/system/Helpers/form_helper.php index 0089e320b558..1e3ea4a9152a 100644 --- a/system/Helpers/form_helper.php +++ b/system/Helpers/form_helper.php @@ -33,9 +33,9 @@ function form_open(string $action = '', $attributes = [], array $hidden = []): s 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 @@ function form_open(string $action = '', $attributes = [], array $hidden = []): s // 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); } diff --git a/system/Helpers/html_helper.php b/system/Helpers/html_helper.php index df41cc6a0436..f3d33611dcef 100755 --- a/system/Helpers/html_helper.php +++ b/system/Helpers/html_helper.php @@ -110,7 +110,7 @@ function img($src = '', bool $indexPage = false, $attributes = ''): string $img = '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 = '
{template}
'; } diff --git a/system/Images/Handlers/BaseHandler.php b/system/Images/Handlers/BaseHandler.php index a35096cd752f..eb704b564670 100644 --- a/system/Images/Handlers/BaseHandler.php +++ b/system/Images/Handlers/BaseHandler.php @@ -473,31 +473,16 @@ public function reorient(bool $silent = false) { $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, + }; } /** diff --git a/system/Images/Handlers/ImageMagickHandler.php b/system/Images/Handlers/ImageMagickHandler.php index 02a330f3b201..fa226ccf2289 100644 --- a/system/Images/Handlers/ImageMagickHandler.php +++ b/system/Images/Handlers/ImageMagickHandler.php @@ -455,30 +455,15 @@ public function reorient(bool $silent = false) { $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, + }; } } diff --git a/system/Language/Language.php b/system/Language/Language.php index 226a9dde87de..1ab2c5269195 100644 --- a/system/Language/Language.php +++ b/system/Language/Language.php @@ -94,7 +94,7 @@ public function getLocale(): string 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); } diff --git a/system/Log/Handlers/ChromeLoggerHandler.php b/system/Log/Handlers/ChromeLoggerHandler.php index 32d93b896465..8d39d4c06705 100644 --- a/system/Log/Handlers/ChromeLoggerHandler.php +++ b/system/Log/Handlers/ChromeLoggerHandler.php @@ -144,7 +144,7 @@ protected function format($object) // @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; } diff --git a/system/Log/Handlers/FileHandler.php b/system/Log/Handlers/FileHandler.php index aaf8899da3b5..42dd9ceefc0f 100644 --- a/system/Log/Handlers/FileHandler.php +++ b/system/Log/Handlers/FileHandler.php @@ -90,7 +90,7 @@ public function handle($level, $message): bool } // 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)); diff --git a/system/Log/Logger.php b/system/Log/Logger.php index 3586ef85c340..fca608f91ff8 100644 --- a/system/Log/Logger.php +++ b/system/Log/Logger.php @@ -341,7 +341,7 @@ protected function interpolate($message, array $context = []) $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 @@ protected function interpolate($message, array $context = []) } // 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) { diff --git a/system/Model.php b/system/Model.php index c45b3605283a..61f4350f3117 100644 --- a/system/Model.php +++ b/system/Model.php @@ -567,7 +567,7 @@ protected function doErrors() return []; } - return [get_class($this->db) => $error['message']]; + return [$this->db::class => $error['message']]; } /** diff --git a/system/Pager/Pager.php b/system/Pager/Pager.php index e9dc47554e02..af0e9accfaee 100644 --- a/system/Pager/Pager.php +++ b/system/Pager/Pager.php @@ -427,7 +427,7 @@ protected function calculateCurrentPage(string $group) 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 { diff --git a/system/Publisher/Publisher.php b/system/Publisher/Publisher.php index beaaa42eafc3..90c966623b2a 100644 --- a/system/Publisher/Publisher.php +++ b/system/Publisher/Publisher.php @@ -72,9 +72,9 @@ class Publisher extends FileCollection * * @var array */ - 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 @@ public function __construct(?string $source = null, ?string $destination = null) // 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 @@ private function verifyAllowed(string $from, string $to): void { // 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); } } diff --git a/system/RESTful/BaseResource.php b/system/RESTful/BaseResource.php index d14d1e2637a4..0360bdb12fc5 100644 --- a/system/RESTful/BaseResource.php +++ b/system/RESTful/BaseResource.php @@ -71,7 +71,7 @@ public function setModel($which = null) } if (! empty($this->model) && empty($this->modelName)) { - $this->modelName = get_class($this->model); + $this->modelName = $this->model::class; } } } diff --git a/system/Router/AutoRouter.php b/system/Router/AutoRouter.php index 216d958ed8f4..6e9f3248c86e 100644 --- a/system/Router/AutoRouter.php +++ b/system/Router/AutoRouter.php @@ -22,53 +22,37 @@ */ final class AutoRouter implements AutoRouterInterface { - /** - * List of CLI routes that do not contain '*' routes. - * - * @var array [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 [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 @@ public function getRoute(string $uri, string $httpVerb): array $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 @@ public function getRoute(string $uri, string $httpVerb): array // 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( '/', diff --git a/system/Router/AutoRouterImproved.php b/system/Router/AutoRouterImproved.php index b6c7c82d2a8c..0db5ebc1ddc2 100644 --- a/system/Router/AutoRouterImproved.php +++ b/system/Router/AutoRouterImproved.php @@ -26,13 +26,6 @@ */ final class AutoRouterImproved implements AutoRouterInterface { - /** - * List of controllers in Defined Routes that should not be accessed via this Auto-Routing. - * - * @var list - */ - private array $protectedControllers; - /** * Sub-directory that contains the requested controller class. */ @@ -59,29 +52,13 @@ final class AutoRouterImproved implements AutoRouterInterface * Whether to translate dashes in URIs for controller/method to CamelCase. * E.g., blog-controller -> BlogController */ - private bool $translateUriToCamelCase; - - /** - * Whether dashes in URI's should be converted - * to underscores when determining method names. - */ - private bool $translateURIDashes; + private readonly bool $translateUriToCamelCase; /** * The namespace for controllers. */ private string $namespace; - /** - * The name of the default controller class. - */ - private string $defaultController; - - /** - * The name of the default method without HTTP verb prefix. - */ - private string $defaultMethod; - /** * Map of URI segments and namespaces. * @@ -130,17 +107,23 @@ final class AutoRouterImproved implements AutoRouterInterface * @param string $defaultController Short classname */ public function __construct( - array $protectedControllers, + /** + * List of controllers in Defined Routes that should not be accessed via this Auto-Routing. + */ + private readonly array $protectedControllers, string $namespace, - string $defaultController, - string $defaultMethod, - bool $translateURIDashes + private readonly string $defaultController, + /** + * The name of the default method without HTTP verb prefix. + */ + private readonly string $defaultMethod, + /** + * Whether dashes in URI's should be converted + * to underscores when determining method names. + */ + private readonly bool $translateURIDashes ) { - $this->protectedControllers = $protectedControllers; - $this->namespace = rtrim($namespace, '\\'); - $this->translateURIDashes = $translateURIDashes; - $this->defaultController = $defaultController; - $this->defaultMethod = $defaultMethod; + $this->namespace = rtrim($namespace, '\\'); $routingConfig = config(Routing::class); $this->moduleRoutes = $routingConfig->moduleRoutes; @@ -377,7 +360,7 @@ public function getRoute(string $uri, string $httpVerb): array // Check parameter count try { $this->checkParameters(); - } catch (MethodNotFoundException $e) { + } catch (MethodNotFoundException) { throw PageNotFoundException::forControllerNotFound($this->controller, $this->method); } @@ -444,14 +427,14 @@ private function checkParameters(): void { try { $refClass = new ReflectionClass($this->controller); - } catch (ReflectionException $e) { + } catch (ReflectionException) { throw PageNotFoundException::forControllerNotFound($this->controller, $this->method); } try { $refMethod = $refClass->getMethod($this->method); $refParams = $refMethod->getParameters(); - } catch (ReflectionException $e) { + } catch (ReflectionException) { throw new MethodNotFoundException(); } @@ -478,7 +461,7 @@ private function checkRemap(): void 'AutoRouterImproved does not support `_remap()` method.' . ' Controller:' . $this->controller ); - } catch (ReflectionException $e) { + } catch (ReflectionException) { // Do nothing. } } @@ -492,7 +475,7 @@ private function checkUnderscore(): void $paramPos = $this->paramPos ?? count($this->segments); for ($i = 0; $i < $paramPos; $i++) { - if (strpos($this->segments[$i], '_') !== false) { + if (str_contains($this->segments[$i], '_')) { throw new PageNotFoundException( 'AutoRouterImproved prohibits access to the URI' . ' containing underscores ("' . $this->segments[$i] . '")' diff --git a/system/Router/DefinedRouteCollector.php b/system/Router/DefinedRouteCollector.php index 47ce7aa92553..8d4f1dc5b1b7 100644 --- a/system/Router/DefinedRouteCollector.php +++ b/system/Router/DefinedRouteCollector.php @@ -23,11 +23,8 @@ */ final class DefinedRouteCollector { - private RouteCollection $routeCollection; - - public function __construct(RouteCollection $routes) + public function __construct(private readonly RouteCollection $routeCollection) { - $this->routeCollection = $routes; } /** diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 8ac8aaca578e..3198d342aa9d 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -1208,8 +1208,8 @@ public function reverseRoute(string $search, ...$params) // Add the default namespace if needed. $namespace = trim($this->defaultNamespace, '\\') . '\\'; if ( - substr($search, 0, 1) !== '\\' - && substr($search, 0, strlen($namespace)) !== $namespace + ! str_starts_with($search, '\\') + && ! str_starts_with($search, $namespace) ) { $search = $namespace . $search; } @@ -1233,7 +1233,7 @@ public function reverseRoute(string $search, ...$params) // If there's any chance of a match, then it will // be with $search at the beginning of the $to string. - if (strpos($to, $search) !== 0) { + if (! str_starts_with($to, $search)) { continue; } @@ -1355,7 +1355,7 @@ protected function buildReverseRoute(string $from, array $params): string preg_match_all('/\(([^)]+)\)/', $from, $matches); if (empty($matches[0])) { - if (strpos($from, '{locale}') !== false) { + if (str_contains($from, '{locale}')) { $locale = $params[0] ?? null; } @@ -1410,7 +1410,7 @@ protected function buildReverseRoute(string $from, array $params): string */ private function replaceLocale(string $route, ?string $locale = null): string { - if (strpos($route, '{locale}') === false) { + if (! str_contains($route, '{locale}')) { return $route; } @@ -1515,7 +1515,7 @@ protected function create(string $verb, string $from, $to, ?array $options = nul // If is redirect, No processing if (! isset($options['redirect']) && is_string($to)) { // If no namespace found, add the default namespace - if (strpos($to, '\\') === false || strpos($to, '\\') > 0) { + if (! str_contains($to, '\\') || strpos($to, '\\') > 0) { $namespace = $options['namespace'] ?? $this->defaultNamespace; $to = trim($namespace, '\\') . '\\' . $to; } @@ -1654,7 +1654,7 @@ private function determineCurrentSubdomain() // on the URL else parse_url will mis-interpret // 'host' as the 'path'. $url = $this->httpHost; - if (strpos($url, 'http') !== 0) { + if (! str_starts_with($url, 'http')) { $url = 'http://' . $url; } diff --git a/system/Router/Router.php b/system/Router/Router.php index 6a58d2ddc3e8..de996f534618 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -423,7 +423,7 @@ protected function checkRoutes(string $uri): bool $matchedKey = $routeKey; // Are we dealing with a locale? - if (strpos($routeKey, '{locale}') !== false) { + if (str_contains($routeKey, '{locale}')) { $routeKey = str_replace('{locale}', '[^/]+', $routeKey); } @@ -445,7 +445,7 @@ protected function checkRoutes(string $uri): bool } // Store our locale so CodeIgniter object can // assign it to the Request. - if (strpos($matchedKey, '{locale}') !== false) { + if (str_contains($matchedKey, '{locale}')) { preg_match( '#^' . str_replace('{locale}', '(?[^/]+)', $matchedKey) . '$#u', $uri, @@ -487,13 +487,13 @@ protected function checkRoutes(string $uri): bool } // Checks `/` in controller name - if (strpos($controller, '/') !== false) { + if (str_contains($controller, '/')) { throw RouterException::forInvalidControllerName($handler); } - if (strpos($handler, '$') !== false && strpos($routeKey, '(') !== false) { + if (str_contains($handler, '$') && str_contains($routeKey, '(')) { // Checks dynamic controller - if (strpos($controller, '$') !== false) { + if (str_contains($controller, '$')) { throw RouterException::forDynamicController($handler); } diff --git a/system/Security/Security.php b/system/Security/Security.php index 2b80ad1d2af2..077b3b9cdbb0 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -160,7 +160,7 @@ class Security implements SecurityInterface */ protected $samesite = Cookie::SAMESITE_LAX; - private IncomingRequest $request; + private readonly IncomingRequest $request; /** * CSRF Cookie Name without Prefix @@ -253,7 +253,7 @@ public function verify(RequestInterface $request) try { $token = ($postedToken !== null && $this->config->tokenRandomize) ? $this->derandomize($postedToken) : $postedToken; - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $token = null; } diff --git a/system/Test/CIUnitTestCase.php b/system/Test/CIUnitTestCase.php index a007e7888d79..62c0fff83844 100644 --- a/system/Test/CIUnitTestCase.php +++ b/system/Test/CIUnitTestCase.php @@ -479,7 +479,7 @@ public function assertCloseEnoughString($expected, $actual, string $message = '' $difference = abs($expected - $actual); $this->assertLessThanOrEqual($tolerance, $difference, $message); - } catch (Exception $e) { + } catch (Exception) { return false; } } @@ -517,7 +517,7 @@ protected function getHeaderEmitted(string $header, bool $ignoreCase = false, st foreach (xdebug_get_headers() as $emittedHeader) { $found = $ignoreCase ? (stripos($emittedHeader, $header) === 0) - : (strpos($emittedHeader, $header) === 0); + : (str_starts_with($emittedHeader, $header)); if ($found) { return $emittedHeader; diff --git a/system/Test/ControllerTestTrait.php b/system/Test/ControllerTestTrait.php index 3be014194999..ab1a1aef3907 100644 --- a/system/Test/ControllerTestTrait.php +++ b/system/Test/ControllerTestTrait.php @@ -204,7 +204,7 @@ public function execute(string $method, ...$params) // getStatusCode() throws for empty codes try { $response->getStatusCode(); - } catch (HTTPException $e) { + } catch (HTTPException) { // If no code has been set then assume success $response->setStatusCode(200); } diff --git a/system/Test/DOMParser.php b/system/Test/DOMParser.php index afcac96ccc05..fe9ee1d58b2a 100644 --- a/system/Test/DOMParser.php +++ b/system/Test/DOMParser.php @@ -260,11 +260,11 @@ public function parseSelector(string $selector) $attr = null; // ID? - if (strpos($selector, '#') !== false) { + if (str_contains($selector, '#')) { [$tag, $id] = explode('#', $selector); } // Attribute - elseif (strpos($selector, '[') !== false && strpos($selector, ']') !== false) { + elseif (str_contains($selector, '[') && str_contains($selector, ']')) { $open = strpos($selector, '['); $close = strpos($selector, ']'); @@ -282,7 +282,7 @@ public function parseSelector(string $selector) $attr = [$name => trim($value, '] ')]; } // Class? - elseif (strpos($selector, '.') !== false) { + elseif (str_contains($selector, '.')) { [$tag, $class] = explode('.', $selector); } // Otherwise, assume the entire string is our tag diff --git a/system/Test/DatabaseTestTrait.php b/system/Test/DatabaseTestTrait.php index 36d3e3df9e17..863ed542319d 100644 --- a/system/Test/DatabaseTestTrait.php +++ b/system/Test/DatabaseTestTrait.php @@ -263,7 +263,7 @@ protected function clearInsertCache() */ public function loadBuilder(string $tableName) { - $builderClass = str_replace('Connection', 'Builder', get_class($this->db)); + $builderClass = str_replace('Connection', 'Builder', $this->db::class); return new $builderClass($tableName, $this->db); } diff --git a/system/Test/Fabricator.php b/system/Test/Fabricator.php index a8a0e43d2ff7..8da0c60fc089 100644 --- a/system/Test/Fabricator.php +++ b/system/Test/Fabricator.php @@ -359,7 +359,7 @@ protected function guessFormatter($field): string $this->faker->getFormatter($field); return $field; - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // No match, keep going } @@ -574,18 +574,11 @@ public function create(?int $count = null, bool $mock = false) */ protected function createMock(?int $count = null) { - switch ($this->model->dateFormat) { - case 'datetime': - $datetime = date('Y-m-d H:i:s'); - break; - - case 'date': - $datetime = date('Y-m-d'); - break; - - default: - $datetime = Time::now()->getTimestamp(); - } + $datetime = match ($this->model->dateFormat) { + 'datetime' => date('Y-m-d H:i:s'), + 'date' => date('Y-m-d'), + default => Time::now()->getTimestamp(), + }; // Determine which fields we will need $fields = []; diff --git a/system/Test/FilterTestTrait.php b/system/Test/FilterTestTrait.php index 791fc0c2a6d0..93f273a39f1f 100644 --- a/system/Test/FilterTestTrait.php +++ b/system/Test/FilterTestTrait.php @@ -132,7 +132,7 @@ protected function getFilterCaller($filter, string $position): Closure if (is_string($filter)) { // Check for an alias (no namespace) - if (strpos($filter, '\\') === false) { + if (! str_contains($filter, '\\')) { if (! isset($this->filtersConfig->aliases[$filter])) { throw new RuntimeException("No filter found with alias '{$filter}'"); } @@ -150,7 +150,7 @@ protected function getFilterCaller($filter, string $position): Closure $filter = new $class(); if (! $filter instanceof FilterInterface) { - throw FilterException::forIncorrectInterface(get_class($filter)); + throw FilterException::forIncorrectInterface($filter::class); } $filterInstances[] = $filter; diff --git a/system/Test/TestLogger.php b/system/Test/TestLogger.php index 91fe1097bf6f..73fbab5571a7 100644 --- a/system/Test/TestLogger.php +++ b/system/Test/TestLogger.php @@ -85,7 +85,7 @@ public static function didLog(string $level, $message, bool $useExactComparison continue; } - if (strpos($log['message'], $message) !== false) { + if (str_contains($log['message'], $message)) { return true; } } diff --git a/system/Typography/Typography.php b/system/Typography/Typography.php index 3931f9c9ec0b..89687d72e2d1 100644 --- a/system/Typography/Typography.php +++ b/system/Typography/Typography.php @@ -84,7 +84,7 @@ public function autoTypography(string $str, bool $reduceLinebreaks = false): str } // Standardize Newlines to make matching easier - if (strpos($str, "\r") !== false) { + if (str_contains($str, "\r")) { $str = str_replace(["\r\n", "\r"], "\n", $str); } @@ -96,7 +96,7 @@ public function autoTypography(string $str, bool $reduceLinebreaks = false): str // HTML comment tags don't conform to patterns of normal tags, so pull them out separately, only if needed $htmlComments = []; - if (strpos($str, '