Skip to content

Commit

Permalink
[TASK] Add custom binary (#1581)
Browse files Browse the repository at this point in the history
  • Loading branch information
sabbelasichon authored Nov 9, 2020
1 parent 61c7303 commit 8e12ff1
Show file tree
Hide file tree
Showing 23 changed files with 1,301 additions and 11 deletions.
16 changes: 16 additions & 0 deletions bin/compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env php
<?php

declare(strict_types = 1);

use Ssch\TYPO3Rector\Compiler\Console\RectorCompilerConsoleApplication;
use Ssch\TYPO3Rector\Compiler\DependencyInjection\ContainerFactory;

require_once __DIR__ . '/../vendor/autoload.php';

$containerFactory = new ContainerFactory();
$container = $containerFactory->create();

/** @var RectorCompilerConsoleApplication $application */
$application = $container->get(RectorCompilerConsoleApplication::class);
exit($application->run());
185 changes: 185 additions & 0 deletions bin/typo3-rector
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#!/usr/bin/env php
<?php

declare(strict_types=1);

use Rector\Caching\Detector\ChangedFilesDetector;
use Rector\Core\Bootstrap\ConfigShifter;
use Rector\Core\Bootstrap\NoRectorsLoadedReporter;
use Rector\Core\Configuration\Configuration;
use Rector\Core\Configuration\MinimalVersionChecker;
use Rector\Core\Configuration\MinimalVersionChecker\ComposerJsonParser;
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 Rector\Core\Exception\NoRectorsLoadedException;
use Symplify\SetConfigResolver\Bootstrap\InvalidSetReporter;
use Symplify\PackageBuilder\Console\ShellCode;
use Symplify\PackageBuilder\Reflection\PrivatesCaller;
use Symplify\SetConfigResolver\Exception\SetNotFoundException;

@ini_set('memory_limit', '-1'); // @ intentionally: continue anyway

// Performance boost
error_reporting(E_ALL);
ini_set('display_errors', 'stderr');
gc_disable();

define('__RECTOR_RUNNING__', true);

// Require Composer autoload.php
$autoloadIncluder = new AutoloadIncluder();
$autoloadIncluder->includeCwdVendorAutoloadIfExists();
$autoloadIncluder->autoloadProjectAutoloaderFile('/../../autoload.php');
$autoloadIncluder->includeDependencyOrRepositoryVendorAutoloadIfExists();
$autoloadIncluder->autoloadFromCommandLine();

$symfonyStyleFactory = new SymfonyStyleFactory(new PrivatesCaller());
$symfonyStyle = $symfonyStyleFactory->create();

try {
$composerJsonReader = new ComposerJsonReader(__DIR__ . '/../composer.json');
$versionChecker = new MinimalVersionChecker(
PHP_VERSION,
new ComposerJsonParser($composerJsonReader->read())
);
$versionChecker->check();

$rectorConfigsResolver = new Typo3RectorConfigsResolver();
$configFileInfos = $rectorConfigsResolver->provide();

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

// shift configs as last so parameters with main config have higher priority
$configShifter = new ConfigShifter();
$firstResolvedConfig = $rectorConfigsResolver->getFirstResolvedConfig();
if ($firstResolvedConfig !== null) {
$configFileInfos = $configShifter->shiftInputConfigAsLast($configFileInfos, $firstResolvedConfig);
}

$container = $rectorContainerFactory->createFromConfigs($configFileInfos);

if ($rectorConfigsResolver->getFirstResolvedConfig()) {
/** @var Configuration $configuration */
$configuration = $container->get(Configuration::class);
$configuration->setFirstResolverConfigFileInfo($rectorConfigsResolver->getFirstResolvedConfig());

/** @var ChangedFilesDetector $changedFilesDetector */
$changedFilesDetector = $container->get(ChangedFilesDetector::class);
$changedFilesDetector->setFirstResolvedConfigFileInfo($rectorConfigsResolver->getFirstResolvedConfig());
}
} catch (SetNotFoundException $setNotFoundException) {
(new InvalidSetReporter())->report($setNotFoundException);
exit(ShellCode::ERROR);
} catch (Throwable $throwable) {
$symfonyStyle->error($throwable->getMessage());
exit(ShellCode::ERROR);
}

/** @var Application $application */
$application = $container->get(Application::class);
exit($application->run());

final class AutoloadIncluder
{
/**
* @var string[]
*/
private $alreadyLoadedAutoloadFiles = [];

public function includeCwdVendorAutoloadIfExists(): void
{
$cwdVendorAutoload = getcwd() . '/vendor/autoload.php';
if (!is_file($cwdVendorAutoload)) {
return;
}

$this->loadIfNotLoadedYet($cwdVendorAutoload, __METHOD__ . '()" on line ' . __LINE__);
}

public function includeDependencyOrRepositoryVendorAutoloadIfExists(): void
{
// Rector's vendor is already loaded
if (class_exists('Rector\HttpKernel\RectorKernel')) {
return;
}

$devOrPharVendorAutoload = __DIR__ . '/../vendor/autoload.php';
if (! is_file($devOrPharVendorAutoload)) {
return;
}

$this->loadIfNotLoadedYet($devOrPharVendorAutoload, __METHOD__ . '()" on line ' . __LINE__);
}

/**
* Inspired by https://github.com/phpstan/phpstan-src/blob/e2308ecaf49a9960510c47f5a992ce7b27f6dba2/bin/phpstan#L19
*/
public function autoloadProjectAutoloaderFile(string $file): void
{
$path = dirname(__DIR__) . $file;
if (!extension_loaded('phar')) {
if (is_file($path)) {
$this->loadIfNotLoadedYet($path, __METHOD__ . '()" on line ' . __LINE__);
}
return;
}

$pharPath = Phar::running(false);
if ($pharPath === '') {
if (is_file($path)) {
$this->loadIfNotLoadedYet($path, __METHOD__ . '()" on line ' . __LINE__);
}
} else {
$path = dirname($pharPath) . $file;
if (is_file($path)) {
$this->loadIfNotLoadedYet($path, __METHOD__ . '()" on line ' . __LINE__);
}
}
}

public function autoloadFromCommandLine(): void
{
$cliArgs = $_SERVER['argv'];

$autoloadOptionPosition = array_search('-a', $cliArgs) ?: array_search('--autoload-file', $cliArgs);
if (! $autoloadOptionPosition) {
return;
}

$autoloadFileValuePosition = $autoloadOptionPosition + 1;
$fileToAutoload = $cliArgs[$autoloadFileValuePosition] ?? null;
if ($fileToAutoload=== null) {
return;
}

$this->loadIfNotLoadedYet($fileToAutoload, __METHOD__);
}

private function loadIfNotLoadedYet(string $file, string $location): void
{
if (in_array($file, $this->alreadyLoadedAutoloadFiles, true)) {
return;
}

if ($this->isDebugOption()) {
echo sprintf(sprintf(
'File "%s" is about to be loaded in "%s"' . PHP_EOL,
$file,
$location
));
}

$this->alreadyLoadedAutoloadFiles[] = realpath($file);

require_once $file;
}

private function isDebugOption(): bool
{
return in_array('--debug', $_SERVER['argv'], true);
}
}
18 changes: 18 additions & 0 deletions build/box.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"alias": "typo3-rector.phar",
"banner": false,
"base-path": "..",
"check-requirements": false,
"directories": [
"vendor/rector/rector/config",
"vendor/rector/rector/src",
"vendor/rector/rector/rules",
"vendor/rector/rector/packages",
"config",
"src",
"Migrations"
],
"exclude-composer-files": false,
"force-autodiscovery": true,
"output": "tmp/typo3-rector.phar"
}
Binary file added build/box.phar
Binary file not shown.
4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"require": {
"php": "^7.2",
"nette/utils": "^3.1",
"phpstan/phpstan": "^0.12.52",
"rector/rector": "0.8.48"
},
"require-dev": {
Expand All @@ -24,6 +25,9 @@
"Ssch\\TYPO3Rector\\": "src"
}
},
"bin": [
"bin/typo3-rector"
],
"autoload-dev": {
"psr-4": {
"Ssch\\TYPO3Rector\\Tests\\": "tests",
Expand Down
37 changes: 37 additions & 0 deletions config/compiler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

use OndraM\CiDetector\CiDetector;
use Ssch\TYPO3Rector\Compiler\ValueObject\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\PackageBuilder\Parameter\ParameterProvider;
use Symplify\SmartFileSystem\SmartFileSystem;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();

$parameters->set(Option::DATA_DIR, __DIR__ . '/../build');
$parameters->set(Option::BUILD_DIR, __DIR__ . '/..');

$services = $containerConfigurator->services();

$services->defaults()
->public()
->autowire();

$services->load('Ssch\TYPO3Rector\Compiler\\', __DIR__ . '/../src/Compiler')
->exclude([
__DIR__ . '/../src/Compiler/Exception',
__DIR__ . '/../src/Compiler/DependencyInjection',
__DIR__ . '/../src/Compiler/HttpKernel',
__DIR__ . '/../src/Compiler/PhpScoper',
__DIR__ . '/../src/Compiler/ValueObject',
]);

$services->set(SmartFileSystem::class);

$services->set(CiDetector::class);

$services->set(ParameterProvider::class);
};
15 changes: 13 additions & 2 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

declare(strict_types=1);

use Ssch\TYPO3Rector\Console\Application;
use Ssch\TYPO3Rector\Helper\Database\Refactorings\DatabaseConnectionToDbalRefactoring;
use Symfony\Component\Console\Application as SymfonyApplication;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
Expand All @@ -16,6 +18,15 @@
->tag('database.dbal.refactoring')
->share(false);

$services->load('Ssch\TYPO3Rector\\', __DIR__ . '/../src/')
->exclude([__DIR__ . '/../src/Rector']);
$services->alias(SymfonyApplication::class, Application::class);

$services->load('Ssch\\TYPO3Rector\\', __DIR__ . '/../src')
->exclude(
[
__DIR__ . '/../src/Rector',
__DIR__ . '/../src/Set',
__DIR__ . '/../src/Bootstrap',
__DIR__ . '/../src/Compiler',
]
);
};
2 changes: 1 addition & 1 deletion config/typo3-8.7.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->import(__DIR__ . '/*');
$containerConfigurator->import(__DIR__ . '/v8/*');
};
4 changes: 4 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ parameters:
count: 1
path: src/Rector/v10/v2/InjectEnvironmentServiceIfNeededInResponseRector.php

-
message: "#^Method Ssch\\\\TYPO3Rector\\\\Set\\\\Typo3RectorSetProvider\\:\\:hydrateSetsFromConstants\\(\\) has parameter \\$setListReflectionClass with generic class ReflectionClass but does not specify its types\\: T$#"
count: 1
path: src/Set/Typo3RectorSetProvider.php

4 changes: 4 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
$services->set(AddCodeCoverageIgnoreToMethodRectorDefinitionRector::class);

$parameters->set(Option::PATHS, [__DIR__ . '/src', __DIR__ . '/tests']);
$parameters->set(
Option::EXCLUDE_PATHS,
[__DIR__ . '/src/Bootstrap', __DIR__ . '/src/Set', __DIR__ . '/src/Compiler']
);
# so Rector code is still PHP 7.2 compatible
$parameters->set(Option::PHP_VERSION_FEATURES, '7.2');
};
Loading

0 comments on commit 8e12ff1

Please sign in to comment.