Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions system/Autoloader/Autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use Config\Autoload;
use Config\Kint as KintConfig;
use Config\Modules;
use Kint;
use Kint\Kint;
use Kint\Renderer\CliRenderer;
use Kint\Renderer\RichRenderer;

Expand Down Expand Up @@ -67,29 +67,29 @@ class Autoloader
/**
* Stores namespaces as key, and path as values.
*
* @var array<string, list<string>>
* @var array<non-empty-string, list<non-empty-string>>
*/
protected $prefixes = [];

/**
* Stores class name as key, and path as values.
*
* @var array<class-string, string>
* @var array<class-string, non-empty-string>
*/
protected $classmap = [];

/**
* Stores files as a list.
*
* @var list<string>
* @var list<non-empty-string>
*/
protected $files = [];

/**
* Stores helper list.
* Always load the URL helper, it should be used in most apps.
*
* @var list<string>
* @var list<non-empty-string>
*/
protected $helpers = ['url'];

Expand Down Expand Up @@ -147,36 +147,35 @@ private function loadComposerAutoloader(Modules $modules): void

// Should we load through Composer's namespaces, also?
if ($modules->discoverInComposer) {
// @phpstan-ignore-next-line
$this->loadComposerNamespaces($composer, $modules->composerPackages ?? []);
$composerPackages = $modules->composerPackages;
$this->loadComposerNamespaces($composer, $composerPackages ?? []);
}

unset($composer);
}

/**
* Register the loader with the SPL autoloader stack.
* Register the loader with the SPL autoloader stack
* in the following order:
*
* 1. Classmap loader
* 2. PSR-4 autoloader
* 3. Non-class files
*
* @return void
*/
public function register()
{
// Register classmap loader for the files in our class map.
spl_autoload_register($this->loadClassmap(...), true);

// Register the PSR-4 autoloader.
spl_autoload_register($this->loadClass(...), true);

// Load our non-class files
foreach ($this->files as $file) {
$this->includeFile($file);
}
}

/**
* Unregister autoloader.
*
* This method is for testing.
* Unregisters the autoloader from the SPL autoload stack.
*/
public function unregister(): void
{
Expand All @@ -187,7 +186,7 @@ public function unregister(): void
/**
* Registers namespaces with the autoloader.
*
* @param array<string, list<string>|string>|string $namespace
* @param array<non-empty-string, list<non-empty-string>|non-empty-string>|non-empty-string $namespace
*
* @return $this
*/
Expand Down Expand Up @@ -219,7 +218,7 @@ public function addNamespace($namespace, ?string $path = null)
*
* If a prefix param is set, returns only paths to the given prefix.
*
* @return ($prefix is null ? array<string, list<string>> : list<string>)
* @return ($prefix is null ? array<non-empty-string, list<non-empty-string>> : list<non-empty-string>)
*/
public function getNamespace(?string $prefix = null)
{
Expand Down Expand Up @@ -247,6 +246,8 @@ public function removeNamespace(string $namespace)
/**
* Load a class using available class mapping.
*
* @param class-string $class The fully qualified class name.
*
* @internal For `spl_autoload_register` use.
*/
public function loadClassmap(string $class): void
Expand All @@ -261,9 +262,9 @@ public function loadClassmap(string $class): void
/**
* Loads the class file for a given class name.
*
* @internal For `spl_autoload_register` use.
* @param class-string $class The fully qualified class name.
*
* @param string $class The fully qualified class name.
* @internal For `spl_autoload_register` use.
*/
public function loadClass(string $class): void
{
Expand All @@ -273,9 +274,9 @@ public function loadClass(string $class): void
/**
* Loads the class file for a given class name.
*
* @param string $class The fully-qualified class name
* @param class-string $class The fully qualified class name.
*
* @return false|string The mapped file name on success, or boolean false on fail
* @return false|non-empty-string The mapped file name on success, or boolean false on fail
*/
protected function loadInNamespace(string $class)
{
Expand All @@ -293,21 +294,20 @@ protected function loadInNamespace(string $class)
$filePath = $directory . $relativeClassPath . '.php';
$filename = $this->includeFile($filePath);

if ($filename) {
if ($filename !== false) {
return $filename;
}
}
}
}

// never found a mapped file
return false;
}

/**
* A central way to include a file. Split out primarily for testing purposes.
*
* @return false|string The filename on success, false if the file is not loaded
* @return false|non-empty-string The filename on success, false if the file is not loaded
*/
protected function includeFile(string $file)
{
Expand Down
25 changes: 12 additions & 13 deletions system/Autoloader/FileLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function __construct(Autoloader $autoloader)
* Attempts to locate a file by examining the name for a namespace
* and looking through the PSR-4 namespaced files that we know about.
*
* @param string $file The relative file path or namespaced file to
* @param non-empty-string $file The relative file path or namespaced file to
* locate. If not namespaced, search in the app
* folder.
* @param non-empty-string|null $folder The folder within the namespace that we should
Expand All @@ -53,7 +53,7 @@ public function __construct(Autoloader $autoloader)
* folder.
* @param string $ext The file extension the file should have.
*
* @return false|string The path to the file, or false if not found.
* @return false|non-empty-string The path to the file, or false if not found.
*/
public function locateFile(string $file, ?string $folder = null, string $ext = 'php')
{
Expand Down Expand Up @@ -156,9 +156,11 @@ public function getClassname(string $file): string
$dlm = false;
}

if (($tokens[$i - 2][0] === T_CLASS || (isset($tokens[$i - 2][1]) && $tokens[$i - 2][1] === 'phpclass'))
if (
($tokens[$i - 2][0] === T_CLASS || (isset($tokens[$i - 2][1]) && $tokens[$i - 2][1] === 'phpclass'))
&& $tokens[$i - 1][0] === T_WHITESPACE
&& $token[0] === T_STRING) {
&& $token[0] === T_STRING
) {
$className = $token[1];
break;
}
Expand All @@ -184,7 +186,7 @@ public function getClassname(string $file): string
* 'app/Modules/bar/Config/Routes.php',
* ]
*
* @return list<string>
* @return list<non-empty-string>
*/
public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array
{
Expand Down Expand Up @@ -213,7 +215,6 @@ public function search(string $path, string $ext = 'php', bool $prioritizeApp =
$foundPaths = [...$foundPaths, ...$appPaths];
}

// Remove any duplicates
return array_values(array_unique($foundPaths));
}

Expand All @@ -236,13 +237,12 @@ protected function ensureExt(string $path, string $ext): string
/**
* Return the namespace mappings we know about.
*
* @return array<int, array<string, string>>
* @return list<array{prefix: non-empty-string, path: non-empty-string}>
*/
protected function getNamespaces()
{
$namespaces = [];

// Save system for last
$system = [];

foreach ($this->autoloader->getNamespace() as $prefix => $paths) {
Expand All @@ -263,6 +263,7 @@ protected function getNamespaces()
}
}

// Save system for last
return array_merge($namespaces, $system);
}

Expand Down Expand Up @@ -295,19 +296,17 @@ public function findQualifiedNameFromPath(string $path)
);

// Remove the file extension (.php)
/** @var class-string */
/** @var class-string $className */
$className = mb_substr($className, 0, -4);

if (in_array($className, $this->invalidClassnames, true)) {
continue;
}

// Check if this exists
if (class_exists($className)) {
return $className;
}

// If the class does not exist, it is an invalid classname.
$this->invalidClassnames[] = $className;
}
}
Expand Down Expand Up @@ -353,11 +352,11 @@ public function listFiles(string $path): array
* Scans the provided namespace, returning a list of all files
* that are contained within the sub path specified by $path.
*
* @return list<string> List of file paths
* @return list<non-empty-string> List of file paths
*/
public function listNamespaceFiles(string $prefix, string $path): array
{
if ($path === '' || ($prefix === '')) {
if ($path === '' || $prefix === '') {
return [];
}

Expand Down
2 changes: 1 addition & 1 deletion system/Autoloader/FileLocatorCached.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public function getClassname(string $file): string
}

/**
* @return list<string>
* @return list<non-empty-string>
*/
public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array
{
Expand Down
8 changes: 5 additions & 3 deletions system/Autoloader/FileLocatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface FileLocatorInterface
* Attempts to locate a file by examining the name for a namespace
* and looking through the PSR-4 namespaced files that we know about.
*
* @param string $file The relative file path or namespaced file to
* @param non-empty-string $file The relative file path or namespaced file to
* locate. If not namespaced, search in the app
* folder.
* @param non-empty-string|null $folder The folder within the namespace that we should
Expand All @@ -32,12 +32,14 @@ interface FileLocatorInterface
* folder.
* @param string $ext The file extension the file should have.
*
* @return false|string The path to the file, or false if not found.
* @return false|non-empty-string The path to the file, or false if not found.
*/
public function locateFile(string $file, ?string $folder = null, string $ext = 'php');

/**
* Examines a file and returns the fully qualified class name.
*
* @param non-empty-string $file
*/
public function getClassname(string $file): string;

Expand All @@ -54,7 +56,7 @@ public function getClassname(string $file): string;
* 'app/Modules/bar/Config/Routes.php',
* ]
*
* @return list<string>
* @return list<non-empty-string>
*/
public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array;

Expand Down
2 changes: 1 addition & 1 deletion tests/system/Autoloader/AutoloaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ public function testAutoloaderLoadsNonClassFiles(): void

$this->assertTrue(function_exists('autoload_foo'));
$this->assertSame('I am autoloaded by Autoloader through $files!', autoload_foo());
$this->assertTrue(defined('AUTOLOAD_CONSTANT'));
$this->assertTrue(defined('AUTOLOAD_CONSTANT')); // @phpstan-ignore method.alreadyNarrowedType
$this->assertSame('foo', AUTOLOAD_CONSTANT);

$loader->unregister();
Expand Down
2 changes: 1 addition & 1 deletion utils/phpstan-baseline/loader.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# total 3075 errors
# total 3074 errors
includes:
- argument.type.neon
- assign.propertyType.neon
Expand Down
7 changes: 1 addition & 6 deletions utils/phpstan-baseline/method.alreadyNarrowedType.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# total 24 errors
# total 23 errors

parameters:
ignoreErrors:
Expand All @@ -7,11 +7,6 @@ parameters:
count: 1
path: ../../admin/starter/tests/unit/HealthTest.php

-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with bool will always evaluate to true\.$#'
count: 1
path: ../../tests/system/Autoloader/AutoloaderTest.php

-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertIsBool\(\) with bool will always evaluate to true\.$#'
count: 1
Expand Down
Loading