├── .gitignore ├── .gitattributes ├── .editorconfig ├── src ├── Filesystem.php ├── LocalFilesystem.php ├── Plugin.php └── PluginInstaller.php ├── rector.php ├── .github └── workflows │ ├── rector_install.yaml │ └── code_analysis.yaml ├── LICENSE └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | /src/GeneratedConfig.php 2 | /vendor 3 | composer.lock 4 | 5 | .phpunit.result.cache 6 | 7 | /e2e/vendor 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ecs.php export-ignore 2 | e2e export-ignore 3 | phpstan.neon export-ignore 4 | README.md export-ignore 5 | phpunit.xml export-ignore 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | indent_style = space 9 | indent_size = 4 10 | -------------------------------------------------------------------------------- /src/Filesystem.php: -------------------------------------------------------------------------------- 1 | services(); 11 | 12 | $services->set(TypedPropertyRector::class); 13 | $services->set(ClassPropertyAssignToConstructorPromotionRector::class); 14 | }; 15 | -------------------------------------------------------------------------------- /.github/workflows/rector_install.yaml: -------------------------------------------------------------------------------- 1 | # inspired at https://github.com/phpstan/extension-installer/blob/master/.github/workflows/integration-tests.yml 2 | name: Rector Install 3 | 4 | on: [push, pull_request] 5 | 6 | env: 7 | # see https://github.com/composer/composer/issues/9368#issuecomment-718112361 8 | COMPOSER_ROOT_VERSION: "dev-main" 9 | 10 | jobs: 11 | rector_install: 12 | name: "Rector install" 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - 17 | uses: actions/checkout@v2 18 | 19 | - 20 | uses: shivammathur/setup-php@v2 21 | with: 22 | php-version: 8.0 23 | 24 | - 25 | run: composer install --no-interaction --no-progress 26 | working-directory: e2e 27 | 28 | # this must run without error and show 1 diff, or the rector/rector-nette config was not registered propperly 29 | - 30 | run: vendor/bin/rector 31 | working-directory: e2e 32 | -------------------------------------------------------------------------------- /.github/workflows/code_analysis.yaml: -------------------------------------------------------------------------------- 1 | name: Code Analysis 2 | 3 | on: 4 | pull_request: null 5 | push: 6 | branches: 7 | - main 8 | 9 | env: 10 | # see https://github.com/composer/composer/issues/9368#issuecomment-718112361 11 | COMPOSER_ROOT_VERSION: "dev-main" 12 | 13 | jobs: 14 | code_analysis: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | actions: 19 | - 20 | name: 'PHPStan' 21 | run: composer phpstan 22 | - 23 | name: 'ECS' 24 | run: composer check-cs 25 | 26 | name: ${{ matrix.actions.name }} 27 | 28 | steps: 29 | - uses: actions/checkout@v2 30 | 31 | - 32 | uses: shivammathur/setup-php@v2 33 | with: 34 | php-version: 8.1 35 | coverage: none 36 | 37 | - uses: "ramsey/composer-install@v1" 38 | 39 | - run: ${{ matrix.actions.run }} 40 | -------------------------------------------------------------------------------- /src/LocalFilesystem.php: -------------------------------------------------------------------------------- 1 | getIO(); 31 | $composer = $event->getComposer(); 32 | $installationManager = $composer->getInstallationManager(); 33 | 34 | $repositoryManager = $composer->getRepositoryManager(); 35 | $localRepository = $repositoryManager->getLocalRepository(); 36 | 37 | $configurationFile = __DIR__ . '/GeneratedConfig.php'; 38 | $pluginInstaller = new PluginInstaller( 39 | new LocalFilesystem(), 40 | $localRepository, 41 | $io, 42 | $installationManager, 43 | new \Composer\Util\Filesystem(), 44 | $configurationFile 45 | ); 46 | 47 | $pluginInstaller->install(); 48 | } 49 | 50 | /** 51 | * @return array 52 | */ 53 | public static function getSubscribedEvents(): array 54 | { 55 | return [ 56 | ScriptEvents::POST_INSTALL_CMD => 'process', 57 | ScriptEvents::POST_UPDATE_CMD => 'process', 58 | ]; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/PluginInstaller.php: -------------------------------------------------------------------------------- 1 | filesystem->isFile($this->configurationFile)) { 64 | $oldGeneratedConfigFileHash = $this->filesystem->hashFile($this->configurationFile); 65 | } 66 | 67 | $installedPackages = []; 68 | $data = []; 69 | 70 | foreach ($this->localRepository->getPackages() as $package) { 71 | if ($this->shouldSkip($package)) { 72 | continue; 73 | } 74 | 75 | $absoluteInstallPath = $this->installationManager->getInstallPath($package); 76 | $data[$package->getName()] = [ 77 | 'install_path' => $absoluteInstallPath, 78 | 'relative_install_path' => $this->composerFilesystem->findShortestPath( 79 | dirname($this->configurationFile), 80 | $absoluteInstallPath, 81 | true 82 | ), 83 | 'extra' => $package->getExtra()[self::RECTOR_EXTRA_KEY] ?? null, 84 | 'version' => $package->getFullPrettyVersion(), 85 | ]; 86 | 87 | $installedPackages[$package->getName()] = true; 88 | } 89 | 90 | ksort($data); 91 | ksort($installedPackages); 92 | 93 | $generatedConfigFileContents = sprintf(self::$generatedFileTemplate, var_export($data, true), true); 94 | 95 | if ($this->filesystem->hashEquals((string) $oldGeneratedConfigFileHash, $generatedConfigFileContents)) { 96 | return; 97 | } 98 | 99 | $this->filesystem->writeFile($this->configurationFile, $generatedConfigFileContents); 100 | $this->io->write('rector/rector-installer: Extensions installed'); 101 | 102 | foreach (array_keys($installedPackages) as $name) { 103 | $this->io->write(sprintf('> %s: installed', $name)); 104 | } 105 | } 106 | 107 | private function shouldSkip(PackageInterface $package): bool 108 | { 109 | if ($package->getType() === self::RECTOR_EXTENSION_TYPE) { 110 | return false; 111 | } 112 | 113 | if (isset($package->getExtra()[self::RECTOR_EXTRA_KEY])) { 114 | return false; 115 | } 116 | 117 | return true; 118 | } 119 | } 120 | --------------------------------------------------------------------------------