Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: upgrade to PHP 8.1 with rector #8354

Merged
merged 9 commits into from
Apr 7, 2024
23 changes: 7 additions & 16 deletions app/Views/errors/cli/error_exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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 . ')';
Expand Down
6 changes: 3 additions & 3 deletions app/Views/errors/html/error_exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@

<pre>
Caused by:
<?= esc(get_class($prevException)), esc($prevException->getCode() ? ' #' . $prevException->getCode() : '') ?>
<?= esc($prevException::class), esc($prevException->getCode() ? ' #' . $prevException->getCode() : '') ?>

<?= nl2br(esc($prevException->getMessage())) ?>
<a href="https://www.duckduckgo.com/?q=<?= urlencode(get_class($prevException) . ' ' . preg_replace('#\'.*\'|".*"#Us', '', $prevException->getMessage())) ?>"
<a href="https://www.duckduckgo.com/?q=<?= urlencode($prevException::class . ' ' . preg_replace('#\'.*\'|".*"#Us', '', $prevException->getMessage())) ?>"
rel="noreferrer" target="_blank">search &rarr;</a>
<?= esc(clean_path($prevException->getFile()) . ':' . $prevException->getLine()) ?>
</pre>
Expand Down Expand Up @@ -121,7 +121,7 @@
<?php
$params = null;
// Reflection by name is not available for closure function
if (substr($row['function'], -1) !== '}') {
if (! str_ends_with($row['function'], '}')) {
$mirror = isset($row['class']) ? new ReflectionMethod($row['class'], $row['function']) : new ReflectionFunction($row['function']);
$params = $mirror->getParameters();
}
Expand Down
25 changes: 0 additions & 25 deletions phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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\\<object\\>, false given\\.$#',
'count' => 2,
'path' => __DIR__ . '/tests/system/CommonSingleServiceTest.php',
];
$ignoreErrors[] = [
'message' => '#^Accessing offset \'BAR\' directly on \\$_SERVER is discouraged\\.$#',
'count' => 1,
Expand Down
50 changes: 49 additions & 1 deletion rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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,
]);
Expand Down Expand Up @@ -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,
Expand Down
14 changes: 7 additions & 7 deletions system/Autoloader/Autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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(...));
}

/**
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down
10 changes: 5 additions & 5 deletions system/Autoloader/FileLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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, '/') . '/';
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
}
Expand Down
5 changes: 1 addition & 4 deletions system/Autoloader/FileLocatorCached.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
final class FileLocatorCached implements FileLocatorInterface
{
private FileLocator $locator;

/**
* @var CacheInterface|FileVarExportHandler
*/
Expand All @@ -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();
}
Expand Down
40 changes: 13 additions & 27 deletions system/BaseModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down Expand Up @@ -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),
};
}

/**
Expand All @@ -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,
};
}

/**
Expand Down
2 changes: 1 addition & 1 deletion system/CLI/CLI.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion system/CLI/Commands.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion system/CLI/GeneratorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Loading
Loading