Command/ThemeAssetsInstallCommand.php
protected function execute(InputInterface $input, OutputInterface $output)
    {
        $targetArg = rtrim($input->getArgument('target'), '/');
        if (!is_dir($targetArg)) {
            throw new InvalidArgumentException(sprintf('The target directory "%s" does not exist.',
                $input->getArgument('target')));
        }

        // Create the themes directory otherwise symlink will fail.
        $themesDir = $targetArg . DIRECTORY_SEPARATOR . self::THEMES_DIR . DIRECTORY_SEPARATOR;
        $this->filesystem->mkdir($themesDir, 0777);

        $io = new SymfonyStyle($input, $output);
        $io->newLine();
        if ($input->getOption('relative')) {
            $expectedMethod = AssetsInstallCommand::METHOD_RELATIVE_SYMLINK;
            $io->text('Trying to install theme assets as <info>relative symbolic links</info>.');
        } elseif ($input->getOption('symlink')) {
            $expectedMethod = AssetsInstallCommand::METHOD_ABSOLUTE_SYMLINK;
            $io->text('Trying to install theme assets as <info>absolute symbolic links</info>.');
        } else {
            $expectedMethod = AssetsInstallCommand::METHOD_COPY;
            $io->text('Installing theme assets as <info>hard copies</info>.');
        }
        $io->newLine();

        $rows     = [];
        $copyUsed = false;
        $exitCode = 0;

        foreach ($this->kernel->getThemes() as $theme) {
            $originDir = $theme->getPath() . DIRECTORY_SEPARATOR . self::ASSETS_DIR;
            if (!is_dir($originDir)) {
                continue;
            }
            $targetDir = $themesDir . $theme->getShortName();

            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $message = sprintf("%s\n-> %s", $theme->getIdentifier(), $targetDir);
            } else {
                $message = $theme->getIdentifier();
            }

            try {
                $this->filesystem->remove($targetDir);

                if (AssetsInstallCommand::METHOD_RELATIVE_SYMLINK === $expectedMethod) {
                    $method = $this->_relativeSymlinkWithFallback($originDir, $targetDir);
                } elseif (AssetsInstallCommand::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) {
                    $method = $this->_absoluteSymlinkWithFallback($originDir, $targetDir);
                } else {
                    $method = $this->_hardCopy($originDir, $targetDir);
                }

                if (AssetsInstallCommand::METHOD_COPY === $method) {
                    $copyUsed = true;
                }

                if ($method === $expectedMethod) {
                    $rows[] = [
                        sprintf('<fg=green;options=bold>%s</>',
                            '\\' === DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */),
                        $message,
                        $method
                    ];
                } else {
                    $rows[] = [
                        sprintf('<fg=yellow;options=bold>%s</>', '\\' === DIRECTORY_SEPARATOR ? 'WARNING' : '!'),
                        $message,
                        $method
                    ];
                }
            }
            catch (\Exception $e) {
                $exitCode = 1;
                $rows[]   = [
                    sprintf('<fg=red;options=bold>%s</>',
                        '\\' === DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */),
                    $message,
                    $e->getMessage()
                ];
            }
        }

        $io->table(['', 'Theme', 'Method / Error'], $rows);

        if (0 !== $exitCode) {
            $io->error('Some errors occurred while installing assets.');
        } else {
            if ($copyUsed) {
                $io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.');
            }
            $io->success('All assets were successfully installed.');
        }

        return $exitCode;
    }
protected function execute(InputInterface $input, OutputInterface $output)
    {
        $targetArg = rtrim($input->getArgument('target'), '/');
        if (!is_dir($targetArg)) {
            throw new InvalidArgumentException(sprintf('The target directory "%s" does not exist.',
                $input->getArgument('target')));
        }

        // Create the themes directory otherwise symlink will fail.
        $themesDir = $targetArg . DIRECTORY_SEPARATOR . self::THEMES_DIR . DIRECTORY_SEPARATOR;
        $this->filesystem->mkdir($themesDir, 0777);

        $io = new SymfonyStyle($input, $output);
        $io->newLine();
        if ($input->getOption('relative')) {
            $expectedMethod = AssetsInstallCommand::METHOD_RELATIVE_SYMLINK;
            $io->text('Trying to install theme assets as <info>relative symbolic links</info>.');
        } elseif ($input->getOption('symlink')) {
            $expectedMethod = AssetsInstallCommand::METHOD_ABSOLUTE_SYMLINK;
            $io->text('Trying to install theme assets as <info>absolute symbolic links</info>.');
        } else {
            $expectedMethod = AssetsInstallCommand::METHOD_COPY;
            $io->text('Installing theme assets as <info>hard copies</info>.');
        }
        $io->newLine();

        $rows     = [];
        $copyUsed = false;
        $exitCode = 0;

        foreach ($this->kernel->getThemes() as $theme) {
            $originDir = $theme->getPath() . DIRECTORY_SEPARATOR . self::ASSETS_DIR;
            if (!is_dir($originDir)) {
                continue;
            }
            $targetDir = $themesDir . $theme->getShortName();

            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $message = sprintf("%s\n-> %s", $theme->getIdentifier(), $targetDir);
            } else {
                $message = $theme->getIdentifier();
            }

            try {
                $this->filesystem->remove($targetDir);

                if (AssetsInstallCommand::METHOD_RELATIVE_SYMLINK === $expectedMethod) {
                    $method = $this->_relativeSymlinkWithFallback($originDir, $targetDir);
                } elseif (AssetsInstallCommand::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) {
                    $method = $this->_absoluteSymlinkWithFallback($originDir, $targetDir);
                } else {
                    $method = $this->_hardCopy($originDir, $targetDir);
                }

                if (AssetsInstallCommand::METHOD_COPY === $method) {
                    $copyUsed = true;
                }

                if ($method === $expectedMethod) {
                    $rows[] = [
                        sprintf('<fg=green;options=bold>%s</>',
                            '\\' === DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */),
                        $message,
                        $method
                    ];
                } else {
                    $rows[] = [
                        sprintf('<fg=yellow;options=bold>%s</>', '\\' === DIRECTORY_SEPARATOR ? 'WARNING' : '!'),
                        $message,
                        $method
                    ];
                }
            }
            catch (\Exception $e) {
                $exitCode = 1;
                $rows[]   = [
                    sprintf('<fg=red;options=bold>%s</>',
                        '\\' === DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */),
                    $message,
                    $e->getMessage()
                ];
            }
        }

        $io->table(['', 'Theme', 'Method / Error'], $rows);

        if (0 !== $exitCode) {
            $io->error('Some errors occurred while installing assets.');
        } else {
            if ($copyUsed) {
                $io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.');
            }
            $io->success('All assets were successfully installed.');
        }

        return $exitCode;
    }
Executes the current command.
This method is not abstract because you can use this class
as a concrete class. In this case, instead of defining the
execute() method, you set the code to execute by passing
a Closure to the setCode() method.

@param InputInterface  $input  An InputInterface instance
@param OutputInterface $output An OutputInterface instance

@return null|int null or 0 if everything went fine, or an error code
@throws LogicException When this abstract method is not implemented
@see setCode()