File: /var/www/admin.fixgini.com/vendor/pestphp/pest-plugin-arch/src/Repositories/ObjectsRepository.php
<?php
declare(strict_types=1);
namespace Pest\Arch\Repositories;
use Pest\Arch\Factories\ObjectDescriptionFactory;
use Pest\Arch\Objects\FunctionDescription;
use Pest\Arch\Support\Composer;
use Pest\Arch\Support\PhpCoreExpressions;
use Pest\Arch\Support\UserDefinedFunctions;
use PHPUnit\Architecture\Elements\ObjectDescription;
use ReflectionFunction;
use SplFileInfo;
use Symfony\Component\Finder\Finder;
/**
* @internal
*/
final class ObjectsRepository
{
/**
* Creates a new Objects Repository singleton instance, if any.
*/
private static ?self $instance = null;
/**
* Holds the Objects Descriptions of the previous resolved prefixes.
*
* @var array<string, array{0?: array<int, ObjectDescription|FunctionDescription>, 1?: array<int, ObjectDescription|FunctionDescription>}>
*/
private array $cachedObjectsPerPrefix = [];
/**
* Creates a new Objects Repository.
*
* @param array<string, array<int, string>> $prefixes
*/
public function __construct(private readonly array $prefixes)
{
// ...
}
/**
* Creates a new Composer Namespace Repositories instance from the "global" autoloader.
*/
public static function getInstance(): self
{
if (self::$instance instanceof \Pest\Arch\Repositories\ObjectsRepository) {
return self::$instance;
}
$loader = Composer::loader();
$namespaces = [];
foreach ((fn (): array => $loader->getPrefixesPsr4())->call($loader) as $namespacePrefix => $directories) {
$namespace = rtrim($namespacePrefix, '\\');
$namespaces[$namespace] = $directories;
}
return self::$instance = new self($namespaces);
}
/**
* Gets the objects of the given namespace.
*
* @return array<int, ObjectDescription|FunctionDescription>
*/
public function allByNamespace(string $namespace, bool $onlyUserDefinedUses = true): array
{
if (PhpCoreExpressions::getClass($namespace) !== null) {
return [
FunctionDescription::make($namespace),
];
}
if (function_exists($namespace) && (new ReflectionFunction($namespace))->getName() === $namespace) {
return [
FunctionDescription::make($namespace),
];
}
$directoriesByNamespace = $this->directoriesByNamespace($namespace);
if ($directoriesByNamespace === []) {
return [];
}
$objects = [];
foreach ($directoriesByNamespace as $prefix => $directories) {
if (array_key_exists($prefix, $this->cachedObjectsPerPrefix)) {
if (array_key_exists((int) $onlyUserDefinedUses, $this->cachedObjectsPerPrefix[$prefix])) {
$objects = [...$objects, ...$this->cachedObjectsPerPrefix[$prefix][(int) $onlyUserDefinedUses]];
continue;
}
} else {
$this->cachedObjectsPerPrefix[$prefix] = [];
}
$objectsPerPrefix = array_values(array_filter(array_reduce($directories, fn (array $files, string $fileOrDirectory): array => array_merge($files, array_values(array_map(
static fn (SplFileInfo $file): ?ObjectDescription => ObjectDescriptionFactory::make($file->getPathname(), $onlyUserDefinedUses),
is_dir($fileOrDirectory) ? iterator_to_array(Finder::create()->files()->in($fileOrDirectory)->name('*.php')) : [new SplFileInfo($fileOrDirectory)],
))), [])));
$objects = [...$objects, ...$this->cachedObjectsPerPrefix[$prefix][(int) $onlyUserDefinedUses] = $objectsPerPrefix];
}
return [...$objects, ...array_map(
static fn (string $function): FunctionDescription => FunctionDescription::make($function),
$this->functionsByNamespace($namespace),
)];
}
/**
* Gets all the functions for the given namespace.
*
* @return array<int, string>
*/
private function functionsByNamespace(string $name): array
{
return array_map(
static function ($functionName): string {
$reflection = new ReflectionFunction($functionName);
return $reflection->getName();
},
array_values(array_filter(UserDefinedFunctions::get(), fn (string $function): bool => str_starts_with(
mb_strtolower($function), mb_strtolower($name)
)))
);
}
/**
* Gets all the directories for the given namespace.
*
* @return array<string, array<int, string>>
*/
private function directoriesByNamespace(string $name): array
{
$directoriesByNamespace = [];
foreach ($this->prefixes as $prefix => $directories) {
if (str_starts_with($name, $prefix)) {
$directories = array_values(array_filter($directories, static fn (string $directory): bool => is_dir($directory)));
$prefix = str_replace('\\', DIRECTORY_SEPARATOR, ltrim(str_replace($prefix, '', $name), '\\'));
$directoriesByNamespace[$name] = [...$directoriesByNamespace[$name] ?? [], ...array_values(array_filter(array_map(static function (string $directory) use ($prefix): string {
$fileOrDirectory = $directory.DIRECTORY_SEPARATOR.$prefix;
if (is_dir($fileOrDirectory)) {
return $fileOrDirectory;
}
return $fileOrDirectory.'.php';
}, $directories), static fn (string $fileOrDirectory): bool => is_dir($fileOrDirectory) || file_exists($fileOrDirectory)))];
}
}
return $directoriesByNamespace;
}
}