Skip to content

Commit

Permalink
[TASK] Add custom container and kernel (#1610)
Browse files Browse the repository at this point in the history
Resolves: #1609
  • Loading branch information
sabbelasichon authored Nov 17, 2020
1 parent 9d70de2 commit 591ba88
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 5 deletions.
4 changes: 2 additions & 2 deletions bin/typo3-rector
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use Rector\Core\Configuration\MinimalVersionChecker\ComposerJsonReader;
use Ssch\TYPO3Rector\Bootstrap\Typo3RectorConfigsResolver;
use Ssch\TYPO3Rector\Console\Application;
use Rector\Core\Console\Style\SymfonyStyleFactory;
use Rector\Core\DependencyInjection\RectorContainerFactory;
use Ssch\TYPO3Rector\DependencyInjection\Typo3RectorContainerFactory;
use Rector\Core\Exception\NoRectorsLoadedException;
use Symplify\SetConfigResolver\Bootstrap\InvalidSetReporter;
use Symplify\PackageBuilder\Console\ShellCode;
Expand Down Expand Up @@ -51,7 +51,7 @@ try {
$configFileInfos = $rectorConfigsResolver->provide();

// Build DI container
$rectorContainerFactory = new RectorContainerFactory();
$rectorContainerFactory = new Typo3RectorContainerFactory([]);

// shift configs as last so parameters with main config have higher priority
$configShifter = new ConfigShifter();
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
},
"autoload": {
"psr-4": {
"Ssch\\TYPO3Rector\\": "src"
"Ssch\\TYPO3Rector\\": "src",
"Ssch\\TYPO3Rector\\PHPStan\\": "utils/phpstan/src"
}
},
"bin": [
Expand All @@ -31,7 +32,6 @@
"autoload-dev": {
"psr-4": {
"Ssch\\TYPO3Rector\\Tests\\": "tests",
"Ssch\\TYPO3Rector\\PHPStan\\": "utils/phpstan/src",
"Ssch\\TYPO3Rector\\PHPStan\\Tests\\": "utils/phpstan/tests"
},
"exclude-from-classmap": ["**.php.inc"]
Expand Down
2 changes: 2 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
__DIR__ . '/../src/Rector',
__DIR__ . '/../src/Set',
__DIR__ . '/../src/Bootstrap',
__DIR__ . '/../src/DependencyInjection',
__DIR__ . '/../src/HttpKernel',
__DIR__ . '/../src/Compiler',
]
);
Expand Down
53 changes: 53 additions & 0 deletions src/DependencyInjection/Typo3RectorContainerFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\DependencyInjection;

use Psr\Container\ContainerInterface;
use Rector\Core\Stubs\StubLoader;
use Ssch\TYPO3Rector\HttpKernel\Typo3RectorKernel;
use Symplify\PackageBuilder\Console\Input\InputDetector;
use Symplify\SmartFileSystem\SmartFileInfo;

final class Typo3RectorContainerFactory
{
/**
* @param SmartFileInfo[] $configFileInfos
* @api
*/
public function createFromConfigs(array $configFileInfos): ContainerInterface
{
// to override the configs without clearing cache
$environment = 'prod' . random_int(1, 10000000);
$isDebug = InputDetector::isDebug();

$rectorKernel = new Typo3RectorKernel($environment, $isDebug);
if ([] !== $configFileInfos) {
$configFilePaths = $this->unpackRealPathsFromFileInfos($configFileInfos);
$rectorKernel->setConfigs($configFilePaths);
}

$stubLoader = new StubLoader();
$stubLoader->loadStubs();

$rectorKernel->boot();

return $rectorKernel->getContainer();
}

/**
* @param SmartFileInfo[] $configFileInfos
* @return string[]
*/
private function unpackRealPathsFromFileInfos(array $configFileInfos): array
{
$configFilePaths = [];
foreach ($configFileInfos as $configFileInfo) {
// getRealPath() cannot be used, as it breaks in phar
$configFilePaths[] = $configFileInfo->getRealPath() ?: $configFileInfo->getPathname();
}

return $configFilePaths;
}
}
121 changes: 121 additions & 0 deletions src/HttpKernel/Typo3RectorKernel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\HttpKernel;

use Migrify\PhpConfigPrinter\Bundle\PhpConfigPrinterBundle;
use Rector\Core\Contract\Rector\RectorInterface;
use Rector\Core\DependencyInjection\Collector\ConfigureCallValuesCollector;
use Rector\Core\DependencyInjection\CompilerPass\MakeRectorsPublicCompilerPass;
use Rector\Core\DependencyInjection\CompilerPass\MergeImportedRectorConfigureCallValuesCompilerPass;
use Rector\Core\DependencyInjection\Loader\ConfigurableCallValuesCollectingPhpFileLoader;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\Loader\GlobFileLoader;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\HttpKernel\Kernel;
use Symplify\AutowireArrayParameter\DependencyInjection\CompilerPass\AutowireArrayParameterCompilerPass;
use Symplify\ComposerJsonManipulator\ComposerJsonManipulatorBundle;
use Symplify\ConsoleColorDiff\ConsoleColorDiffBundle;
use Symplify\PackageBuilder\Contract\HttpKernel\ExtraConfigAwareKernelInterface;
use Symplify\PackageBuilder\DependencyInjection\CompilerPass\AutowireInterfacesCompilerPass;

final class Typo3RectorKernel extends Kernel implements ExtraConfigAwareKernelInterface
{
/**
* @var string[]
*/
private $configs = [];

/**
* @var ConfigureCallValuesCollector
*/
private $configureCallValuesCollector;

public function __construct(string $environment, bool $debug)
{
$this->configureCallValuesCollector = new ConfigureCallValuesCollector();

parent::__construct($environment, $debug);
}

public function getCacheDir(): string
{
// manually configured, so it can be replaced in phar
return sys_get_temp_dir() . '/_rector';
}

public function getLogDir(): string
{
// manually configured, so it can be replaced in phar
return sys_get_temp_dir() . '/_rector_log';
}

public function registerContainerConfiguration(LoaderInterface $loader): void
{
$loader->load(__DIR__ . '/../../vendor/rector/rector/config/config.php');
$loader->load(__DIR__ . '/../../config/services.php');

foreach ($this->configs as $config) {
$loader->load($config);
}
}

/**
* @param string[] $configs
*/
public function setConfigs(array $configs): void
{
$this->configs = $configs;
}

/**
* @return BundleInterface[]
*/
public function registerBundles(): array
{
return [new ConsoleColorDiffBundle(), new PhpConfigPrinterBundle(), new ComposerJsonManipulatorBundle()];
}

protected function build(ContainerBuilder $containerBuilder): void
{
$containerBuilder->addCompilerPass(new AutowireArrayParameterCompilerPass());

// autowire Rectors by default (mainly for 3rd party code)
$containerBuilder->addCompilerPass(new AutowireInterfacesCompilerPass([RectorInterface::class]));

$containerBuilder->addCompilerPass(new MakeRectorsPublicCompilerPass());

// add all merged arguments of Rector services
$containerBuilder->addCompilerPass(
new MergeImportedRectorConfigureCallValuesCompilerPass($this->configureCallValuesCollector)
);
}

/**
* This allows to use "%vendor%" variables in imports
*/
protected function getContainerLoader(ContainerInterface $container): DelegatingLoader
{
$fileLocator = new FileLocator($this);

$loaders = [new GlobFileLoader($fileLocator)];

if ($container instanceof ContainerBuilder) {
$loaders[] = new ConfigurableCallValuesCollectingPhpFileLoader(
$container,
$fileLocator,
$this->configureCallValuesCollector
);
}

$loaderResolver = new LoaderResolver($loaders);

return new DelegatingLoader($loaderResolver);
}
}
2 changes: 1 addition & 1 deletion src/Set/Typo3RectorSetProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function provideByName(string $desiredSetName): ?Set
return $foundSet;
}

// sencond approach by set path
// second approach by set path
foreach ($this->sets as $set) {
if (! file_exists($desiredSetName)) {
continue;
Expand Down

0 comments on commit 591ba88

Please sign in to comment.