>, * psr-4?: array>, * classmap?: list, * files?: list, * exclude-from-classmap?: list * } * @psalm-type ComposerPackage array{ * name: string, * autoload: ComposerAutoload * } * @psalm-type Composer array{ * autoload: ComposerAutoload, * config?: array{vendor-dir?: string} * } */ final class MakeLocatorForComposerJson { public function __invoke(string $installationPath, Locator $astLocator): SourceLocator { $realInstallationPath = (string) realpath($installationPath); if (! is_dir($realInstallationPath)) { throw InvalidProjectDirectory::atPath($installationPath); } $composerJsonPath = $realInstallationPath . '/composer.json'; if (! is_file($composerJsonPath)) { throw MissingComposerJson::inProjectPath($installationPath); } $composerJsonContent = file_get_contents($composerJsonPath); assert(is_string($composerJsonContent)); /** @psalm-var array{autoload: ComposerAutoload}|null $composer */ $composer = json_decode($composerJsonContent, true); if (! is_array($composer)) { throw FailedToParseJson::inFile($composerJsonPath); } $pathPrefix = $realInstallationPath . '/'; $classMapPaths = $this->prefixPaths($this->packageToClassMapPaths($composer), $pathPrefix); $classMapFiles = array_filter($classMapPaths, 'is_file'); $classMapDirectories = array_values(array_filter($classMapPaths, 'is_dir')); $filePaths = $this->prefixPaths($this->packageToFilePaths($composer), $pathPrefix); return new AggregateSourceLocator(array_merge( [ new PsrAutoloaderLocator( Psr4Mapping::fromArrayMappings( $this->prefixWithInstallationPath($this->packageToPsr4AutoloadNamespaces($composer), $pathPrefix), ), $astLocator, ), new PsrAutoloaderLocator( Psr0Mapping::fromArrayMappings( $this->prefixWithInstallationPath($this->packageToPsr0AutoloadNamespaces($composer), $pathPrefix), ), $astLocator, ), new DirectoriesSourceLocator($classMapDirectories, $astLocator), ], ...array_map( static function (string $file) use ($astLocator): array { assert($file !== ''); return [new SingleFileSourceLocator($file, $astLocator)]; }, array_merge($classMapFiles, $filePaths), ), )); } /** * @param array{autoload: ComposerAutoload} $package * * @return array> */ private function packageToPsr4AutoloadNamespaces(array $package): array { return array_map(static fn (string|array $namespacePaths): array => (array) $namespacePaths, $package['autoload']['psr-4'] ?? []); } /** * @param array{autoload: ComposerAutoload} $package * * @return array> */ private function packageToPsr0AutoloadNamespaces(array $package): array { return array_map(static fn (string|array $namespacePaths): array => (array) $namespacePaths, $package['autoload']['psr-0'] ?? []); } /** * @param array{autoload: ComposerAutoload} $package * * @return list */ private function packageToClassMapPaths(array $package): array { return $package['autoload']['classmap'] ?? []; } /** * @param array{autoload: ComposerAutoload} $package * * @return list */ private function packageToFilePaths(array $package): array { return $package['autoload']['files'] ?? []; } /** * @param array> $paths * * @return array> */ private function prefixWithInstallationPath(array $paths, string $trimmedInstallationPath): array { return array_map(fn (array $paths): array => $this->prefixPaths($paths, $trimmedInstallationPath), $paths); } /** * @param list $paths * * @return list */ private function prefixPaths(array $paths, string $prefix): array { return array_map(static fn (string $path): string => $prefix . $path, $paths); } } __halt_compiler();----SIGNATURE:----M6nQL2jtyLmc1gnPDzfYPBRl4zh9fDQH1WpWJ8xfuUVDc0DYDuB9NCKEG6wG+bQDtYjl2meMW9gtkelkdYw/qTUhIQOeWYavlfvSPmMq9REXZW7Zz3aMXYYEXPSqYPt9FNqnubVhtvh8wgRYpqG2p5193mMGZ3ukrcDF/C4bIVSUcS1z/HuYT4/Dn9wrsfMmwk0xmAlupQQY+Y+gt4+D/QVpx8D6iRH4Yl7MOpJC0i1KBhJDTvncH+ZkKtG65OE+WXLRQYIZuhNKawl10PTwzDRNdrtygT/I5LrZENvDLHnxXXm7bD2eAAH6O2ly93mMgfbIpd9F+fCfw+MbpdGTpj1hCglUQ6FrUfxqqgPARpZg9WbqJ/FxGBOapSnmVs/ZUfZvsx0K1r8/NLdWXHadGMYjvPLI4P6ydFPhuuoUcE/bqwCLDMg9Xn4PeYq8GgHjNnrCW02VevOQcX/myu/xhpwbQPRuNFeFR+g6H43HfRW/mMglrJA5V1rQDyxi/VwnPzi8b1zJ5F13qTXp3z85NWWyEd6NASD2Eu3Tyf9mNFwqjl1vJtOcRopArGp9eWqg8eP2gk9HMOLTyUGh8FkdmkPjTqcXc90Q8TqPnKzDboAnd8xhMoo1WYOo9AfAJPHMAdLLZktGO4AtJnQW+RNDs8TIOoQOqVMa2ZcwCtyLSiE=----ATTACHMENT:----NjY0MzI3ODQ1Mzg5MDcxNyA4MjA1NDA4NTI3OTU1MjA3IDI4MTc3NTY1NDAyMjExOTE=