20 use Symfony\Component\Console\Command\Command;
21 use Symfony\Component\Console\Input\InputInterface;
22 use Symfony\Component\Console\Output\OutputInterface;
23 use Symfony\Component\Console\Input\InputOption;
24 use Symfony\Component\Console\Input\InputArgument;
48 private $dependencyChecker;
62 private $themeCollection;
76 private $cleanupFiles;
83 private $backupRollbackFactory;
90 private $themeValidator;
97 private $themePackageInfo;
104 private $themeUninstaller;
111 private $themeDependencyChecker;
116 private $maintenanceModeEnabler;
151 $this->cleanupFiles = $cleanupFiles;
152 $this->composer = $composer;
153 $this->dependencyChecker = $dependencyChecker;
154 $this->themeCollection = $themeCollection;
155 $this->backupRollbackFactory = $backupRollbackFactory;
156 $this->themeValidator = $themeValidator;
157 $this->themePackageInfo = $themePackageInfo;
158 $this->themeUninstaller = $themeUninstaller;
159 $this->themeDependencyChecker = $themeDependencyChecker;
160 $this->maintenanceModeEnabler =
162 parent::__construct();
170 $this->setName(
'theme:uninstall');
171 $this->setDescription(
'Uninstalls theme');
173 self::INPUT_KEY_BACKUP_CODE,
175 InputOption::VALUE_NONE,
176 'Take code backup (excluding temporary files)' 179 self::INPUT_KEY_THEMES,
180 InputArgument::IS_ARRAY | InputArgument::REQUIRED,
181 'Path of the theme. Theme path should be specified as full path which is area/vendor/name.' 182 .
' For example, frontend/Magento/blank' 185 self::INPUT_KEY_CLEAR_STATIC_CONTENT,
187 InputOption::VALUE_NONE,
188 'Clear generated static view files.' 199 $themePaths = $input->getArgument(self::INPUT_KEY_THEMES);
200 $messages = array_merge($messages, $this->validate($themePaths));
201 if (!empty($messages)) {
204 return \Magento\Framework\Console\Cli::RETURN_FAILURE;
206 $messages = array_merge(
208 $this->themeValidator->validateIsThemeInUse($themePaths),
209 $this->themeDependencyChecker->checkChildTheme($themePaths),
210 $this->checkDependencies($themePaths)
212 if (!empty($messages)) {
214 '<error>Unable to uninstall. Please resolve the following issues:</error>' 215 . PHP_EOL . implode(PHP_EOL, $messages)
218 return \Magento\Framework\Console\Cli::RETURN_FAILURE;
221 $result = $this->maintenanceModeEnabler->executeInMaintenanceMode(
222 function () use ($input,
$output, $themePaths) {
224 if ($input->getOption(self::INPUT_KEY_BACKUP_CODE)) {
226 $codeBackup = $this->backupRollbackFactory->create(
$output);
227 $codeBackup->codeBackup($time);
230 $this->themeUninstaller->uninstallRegistry(
$output, $themePaths);
231 $this->themeUninstaller->uninstallCode(
$output, $themePaths);
233 $this->cleanup($input,
$output);
234 return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
235 }
catch (\Exception $e) {
236 $output->writeln(
'<error>' . $e->getMessage() .
'</error>');
237 $output->writeln(
'<error>Please disable maintenance mode after you resolved above issues</error>');
239 return \Magento\Framework\Console\Cli::RETURN_FAILURE;
255 private function validate($themePaths)
260 if (!empty($incorrectThemes)) {
261 $text =
'Theme path should be specified as full path which is area/vendor/name.';
262 $messages[] =
'<error>Incorrect theme(s) format: ' . implode(
', ', $incorrectThemes)
263 .
'. ' .
$text .
'</error>';
270 $unknownPackages = array_diff($unknownPackages, $unknownThemes);
271 if (!empty($unknownPackages)) {
272 $text = count($unknownPackages) > 1 ?
273 ' are not installed Composer packages' :
' is not an installed Composer package';
274 $messages[] =
'<error>' . implode(
', ', $unknownPackages) .
$text .
'</error>';
277 if (!empty($unknownThemes)) {
278 $messages[] =
'<error>Unknown theme(s): ' . implode(
', ', $unknownThemes) .
'</error>';
293 foreach ($themePaths as $themePath) {
294 if (!preg_match(
'/^[^\/]+\/[^\/]+\/[^\/]+$/', $themePath)) {
310 $installedPackages = $this->composer->getRootRequiredPackages();
313 foreach ($themePaths as $themePath) {
314 if (array_search($this->themePackageInfo->getPackageName($themePath), $installedPackages) ===
false) {
330 foreach ($themePaths as $themePath) {
331 if (!$this->themeCollection->hasTheme($this->themeCollection->getThemeByFullPath($themePath))) {
344 private function checkDependencies($themePaths)
348 foreach ($themePaths as $themePath) {
349 $packageToPath[$this->themePackageInfo->getPackageName($themePath)] = $themePath;
351 $dependencies = $this->dependencyChecker->checkDependencies(array_keys($packageToPath),
true);
352 foreach ($dependencies as $package => $dependingPackages) {
353 if (!empty($dependingPackages)) {
355 '<error>' . $packageToPath[$package] .
356 " has the following dependent package(s):</error>" .
357 PHP_EOL .
"\t<error>" . implode(
'</error>' . PHP_EOL .
"\t<error>", $dependingPackages)
371 private function cleanup(InputInterface $input, OutputInterface
$output)
373 $this->cache->clean();
374 $output->writeln(
'<info>Cache cleared successfully.</info>');
376 if ($input->getOption(self::INPUT_KEY_CLEAR_STATIC_CONTENT)) {
377 $this->cleanupFiles->clearMaterializedViewFiles();
378 $output->writeln(
'<info>Generated static view files cleared successfully.</info>');
381 '<error>Alert: Generated static view files were not cleared.' 382 .
' You can clear them using the --' . self::INPUT_KEY_CLEAR_STATIC_CONTENT .
' option.' 383 .
' Failure to clear static view files might cause display issues in the Admin and storefront.</error>' getIncorrectThemes($themePaths)
getUnknownThemes($themePaths)
__construct(Cache $cache, CleanupFiles $cleanupFiles, ComposerInformation $composer, MaintenanceMode $maintenanceMode, DependencyChecker $dependencyChecker, Collection $themeCollection, BackupRollbackFactory $backupRollbackFactory, ThemeValidator $themeValidator, ThemePackageInfo $themePackageInfo, ThemeUninstaller $themeUninstaller, ThemeDependencyChecker $themeDependencyChecker, MaintenanceModeEnabler $maintenanceModeEnabler=null)
const INPUT_KEY_CLEAR_STATIC_CONTENT
execute(InputInterface $input, OutputInterface $output)
getUnknownPackages($themePaths)
const INPUT_KEY_BACKUP_CODE