116 lines
3.7 KiB
PHP
116 lines
3.7 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\Flex;
|
|
|
|
use Composer\Composer;
|
|
use Composer\Package\PackageInterface;
|
|
|
|
/**
|
|
* @author Fabien Potencier <fabien@symfony.com>
|
|
*/
|
|
class SymfonyBundle
|
|
{
|
|
private $package;
|
|
private $operation;
|
|
private $vendorDir;
|
|
|
|
public function __construct(Composer $composer, PackageInterface $package, string $operation)
|
|
{
|
|
$this->package = $package;
|
|
$this->operation = $operation;
|
|
$this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
|
|
}
|
|
|
|
public function getClassNames(): array
|
|
{
|
|
$uninstall = 'uninstall' === $this->operation;
|
|
$classes = [];
|
|
$autoload = $this->package->getAutoload();
|
|
$isSyliusPlugin = 'sylius-plugin' === $this->package->getType();
|
|
foreach (['psr-4' => true, 'psr-0' => false] as $psr => $isPsr4) {
|
|
if (!isset($autoload[$psr])) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($autoload[$psr] as $namespace => $paths) {
|
|
if (!\is_array($paths)) {
|
|
$paths = [$paths];
|
|
}
|
|
foreach ($paths as $path) {
|
|
foreach ($this->extractClassNames($namespace, $isSyliusPlugin) as $class) {
|
|
// we only check class existence on install as we do have the code available
|
|
// in contrast to uninstall operation
|
|
if (!$uninstall && !$this->isBundleClass($class, $path, $isPsr4)) {
|
|
continue;
|
|
}
|
|
|
|
$classes[] = $class;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $classes;
|
|
}
|
|
|
|
private function extractClassNames(string $namespace, bool $isSyliusPlugin): array
|
|
{
|
|
$namespace = trim($namespace, '\\');
|
|
$class = $namespace.'\\';
|
|
$parts = explode('\\', $namespace);
|
|
$suffix = $parts[\count($parts) - 1];
|
|
$endOfWord = substr($suffix, -6);
|
|
|
|
if ($isSyliusPlugin) {
|
|
if ('Bundle' !== $endOfWord && 'Plugin' !== $endOfWord) {
|
|
$suffix .= 'Bundle';
|
|
}
|
|
} elseif ('Bundle' !== $endOfWord) {
|
|
$suffix .= 'Bundle';
|
|
}
|
|
|
|
$classes = [$class.$suffix];
|
|
$acc = '';
|
|
foreach (\array_slice($parts, 0, -1) as $part) {
|
|
if ('Bundle' === $part || ($isSyliusPlugin && 'Plugin' === $part)) {
|
|
continue;
|
|
}
|
|
$classes[] = $class.$part.$suffix;
|
|
$acc .= $part;
|
|
$classes[] = $class.$acc.$suffix;
|
|
}
|
|
|
|
return array_unique($classes);
|
|
}
|
|
|
|
private function isBundleClass(string $class, string $path, bool $isPsr4): bool
|
|
{
|
|
$classPath = ($this->vendorDir ? $this->vendorDir.'/' : '').$this->package->getPrettyName().'/'.$path.'/';
|
|
$parts = explode('\\', $class);
|
|
$class = $parts[\count($parts) - 1];
|
|
if (!$isPsr4) {
|
|
$classPath .= str_replace('\\', '', implode('/', \array_slice($parts, 0, -1))).'/';
|
|
}
|
|
$classPath .= str_replace('\\', '/', $class).'.php';
|
|
|
|
if (!file_exists($classPath)) {
|
|
return false;
|
|
}
|
|
|
|
// heuristic that should work in almost all cases
|
|
$classContents = file_get_contents($classPath);
|
|
|
|
return str_contains($classContents, 'Symfony\Component\HttpKernel\Bundle\Bundle')
|
|
|| str_contains($classContents, 'Symfony\Component\HttpKernel\Bundle\AbstractBundle');
|
|
}
|
|
}
|