/** * Run Composer dependency check for uninstall * * @param array $packages * @return array * @throws \RuntimeException */ public function runUninstallReadinessCheck(array $packages) { try { $packagesAndTypes = $this->composerInfo->getRootRequiredPackageTypesByName(); $dependencies = $this->packageDependencyChecker->checkDependencies($packages, true); $messages = []; $themes = []; foreach ($packages as $package) { if (!isset($packagesAndTypes[$package])) { throw new \RuntimeException('Package ' . $package . ' not found in the system.'); } switch ($packagesAndTypes[$package]) { case ComposerInformation::METAPACKAGE_PACKAGE_TYPE: unset($dependencies[$package]); break; case ComposerInformation::THEME_PACKAGE_TYPE: $themes[] = $package; break; } if (!empty($dependencies[$package])) { $messages[] = $package . " has the following dependent package(s): " . implode(', ', $dependencies[$package]); } } if (!empty($themes)) { $messages = array_merge($messages, $this->themeDependencyChecker->checkChildThemeByPackagesName($themes)); } if (!empty($messages)) { throw new \RuntimeException(implode(PHP_EOL, $messages)); } return ['success' => true]; } catch (\RuntimeException $e) { $message = str_replace(PHP_EOL, '<br/>', htmlspecialchars($e->getMessage())); return ['success' => false, 'error' => $message]; } }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $languages = $input->getArgument(self::PACKAGE_ARGUMENT); $packagesToRemove = []; $dependencies = $this->dependencyChecker->checkDependencies($languages, true); foreach ($languages as $package) { if (!$this->validate($package)) { $output->writeln("<info>Package {$package} is not a Magento language and will be skipped.</info>"); } else { if (sizeof($dependencies[$package]) > 0) { $output->writeln("<info>Package {$package} has dependencies and will be skipped.</info>"); } else { $packagesToRemove[] = $package; } } } if ($packagesToRemove !== []) { if ($input->getOption(self::BACKUP_CODE_OPTION)) { $backupRestore = $this->backupRollbackFactory->create($output); $backupRestore->codeBackup(time()); } else { $output->writeln('<info>You are removing language package without a code backup.</info>'); } $this->remove->remove($packagesToRemove); $this->cache->clean(); } else { $output->writeln('<info>Nothing is removed.</info>'); } }
/** * Check dependencies to given full theme paths * * @param string[] $themePaths * @return string[] */ private function checkDependencies($themePaths) { $messages = []; $packageToPath = []; foreach ($themePaths as $themePath) { $packageToPath[$this->themePackageInfo->getPackageName($themePath)] = $themePath; } $dependencies = $this->dependencyChecker->checkDependencies(array_keys($packageToPath), true); foreach ($dependencies as $package => $dependingPackages) { if (!empty($dependingPackages)) { $messages[] = '<error>' . $packageToPath[$package] . " has the following dependent package(s):</error>" . PHP_EOL . "\t<error>" . implode('</error>' . PHP_EOL . "\t<error>", $dependingPackages) . "</error>"; } } return $messages; }
public function testCheckDependenciesExcludeSelf() { $composerApp = $this->getMock('Composer\\Console\\Application', ['setAutoExit', 'resetComposer', 'run'], [], '', false); $directoryList = $this->getMock('Magento\\Framework\\App\\Filesystem\\DirectoryList', [], [], '', false); $directoryList->expects($this->exactly(3))->method('getRoot'); $composerApp->expects($this->once())->method('setAutoExit')->with(false); $composerApp->expects($this->at(2))->method('run')->willReturnCallback(function ($input, $buffer) { $output = 'magento/package-b requires magento/package-a (1.0)' . PHP_EOL . 'magento/package-c requires magento/package-a (1.0)' . PHP_EOL; $buffer->writeln($output); }); $composerApp->expects($this->at(4))->method('run')->willReturnCallback(function ($input, $buffer) { $output = 'magento/package-c requires magento/package-b (1.0)' . PHP_EOL . 'magento/package-d requires magento/package-b (1.0)' . PHP_EOL; $buffer->writeln($output); }); $composerApp->Expects($this->at(6))->method('run')->willReturnCallback(function ($input, $buffer) { $output = 'magento/package-d requires magento/package-c (1.0)' . PHP_EOL; $buffer->writeln($output); }); $dependencyChecker = new DependencyChecker($composerApp, $directoryList); $expected = ['magento/package-a' => [], 'magento/package-b' => ['magento/package-d'], 'magento/package-c' => ['magento/package-d']]; $this->assertEquals($expected, $dependencyChecker->checkDependencies(['magento/package-a', 'magento/package-b', 'magento/package-c'], true)); }