vendor/se7enxweb/legacy-bridge/bundle/Command/LegacyBundleInstallCommand.php line 97

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) eZ Systems AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. namespace eZ\Bundle\EzPublishLegacyBundle\Command;
  7. use eZ\Bundle\EzPublishLegacyBundle\LegacyBundles\LegacyExtensionsLocator;
  8. use RuntimeException;
  9. use Symfony\Component\Console\Command\Command;
  10. use Symfony\Component\Console\Input\InputOption;
  11. use Symfony\Component\Console\Input\InputInterface;
  12. use Symfony\Component\Console\Output\OutputInterface;
  13. use Symfony\Component\Filesystem\Exception\IOException;
  14. use Symfony\Component\Filesystem\Filesystem;
  15. use Symfony\Component\Finder\Finder;
  16. use Symfony\Component\HttpKernel\KernelInterface;
  17. class LegacyBundleInstallCommand extends Command
  18. {
  19. /** @var LegacyExtensionsLocator */
  20. private $legacyExtensionsLocator;
  21. /** @var KernelInterface */
  22. private $kernel;
  23. /** @var Filesystem */
  24. private $filesystem;
  25. /** @var string */
  26. private $legacyRootDir;
  27. public function __construct(
  28. LegacyExtensionsLocator $legacyExtensionsLocator,
  29. KernelInterface $kernel,
  30. Filesystem $filesystem,
  31. string $legacyRootDir
  32. ) {
  33. parent::__construct();
  34. $this->legacyExtensionsLocator = $legacyExtensionsLocator;
  35. $this->kernel = $kernel;
  36. $this->filesystem = $filesystem;
  37. $this->legacyRootDir = $legacyRootDir;
  38. }
  39. protected function configure()
  40. {
  41. $this
  42. ->setName('exponential:legacy:install-extensions')
  43. ->setAliases(['ezpublish:legacybundles:install_extensions'])
  44. ->addOption('copy', null, InputOption::VALUE_NONE, 'Creates copies of the extensions instead of using a symlink')
  45. ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks')
  46. ->addOption('force', null, InputOption::VALUE_NONE, 'Force overwriting of existing directory (will be removed)')
  47. ->setDescription('Installs legacy extensions (default: symlink) defined in Symfony bundles into ezpublish_legacy/extensions')
  48. ->setHelp(
  49. <<<EOT
  50. The command <info>%command.name%</info> installs <info>legacy extensions</info> stored in a Symfony bundle
  51. into the ezpublish_legacy/extension folder.
  52. EOT
  53. );
  54. }
  55. protected function execute(InputInterface $input, OutputInterface $output): int
  56. {
  57. $options = [
  58. 'copy' => (bool)$input->getOption('copy'),
  59. 'relative' => (bool)$input->getOption('relative'),
  60. 'force' => (bool)$input->getOption('force'),
  61. ];
  62. foreach ($this->kernel->getBundles() as $bundle) {
  63. foreach ($this->legacyExtensionsLocator->getExtensionDirectories($bundle->getPath()) as $extensionDir) {
  64. $output->writeln('- ' . $this->removeCwd($extensionDir));
  65. try {
  66. $target = $this->linkLegacyExtension($extensionDir, $options, $output);
  67. $output->writeln(' <info>' . ($options['copy'] ? 'Copied' : 'linked') . "</info> to $target</info>");
  68. } catch (RuntimeException $e) {
  69. $output->writeln(' <error>' . $e->getMessage() . '</error>');
  70. }
  71. }
  72. }
  73. return 0;
  74. }
  75. /**
  76. * Links the legacy extension at $path into ezpublish_legacy/extensions.
  77. *
  78. * @param string $extensionPath Absolute path to a legacy extension folder
  79. * @param array $options
  80. * @param OutputInterface $output
  81. *
  82. * @throws \RuntimeException If a target link/directory exists and $options[force] isn't set to true
  83. *
  84. * @return string The resulting link/directory
  85. */
  86. protected function linkLegacyExtension($extensionPath, array $options = [], OutputInterface $output)
  87. {
  88. $options += ['force' => false, 'copy' => false, 'relative' => false];
  89. $filesystem = $this->filesystem;
  90. $legacyRootDir = rtrim($this->legacyRootDir, '/');
  91. $relativeExtensionPath = $filesystem->makePathRelative($extensionPath, realpath("$legacyRootDir/extension/"));
  92. $targetPath = "$legacyRootDir/extension/" . basename($extensionPath);
  93. if (file_exists($targetPath) && $options['copy']) {
  94. if (!$options['force']) {
  95. throw new RuntimeException("Target directory $targetPath already exists");
  96. }
  97. $filesystem->remove($targetPath);
  98. }
  99. if (file_exists($targetPath) && !$options['copy']) {
  100. if (is_link($targetPath)) {
  101. $existingLinkTarget = readlink($targetPath);
  102. if ($existingLinkTarget == $extensionPath || $existingLinkTarget == $relativeExtensionPath) {
  103. return $targetPath;
  104. } elseif (!$options['force']) {
  105. throw new RuntimeException("Target $targetPath already exists with a different target");
  106. }
  107. } else {
  108. if (!$options['force']) {
  109. throw new RuntimeException("Target $targetPath already exists with a different target");
  110. }
  111. }
  112. $filesystem->remove($targetPath);
  113. }
  114. if (!$options['copy']) {
  115. if ($options['relative']) {
  116. try {
  117. $filesystem->symlink(
  118. $relativeExtensionPath,
  119. $targetPath
  120. );
  121. } catch (IOException $e) {
  122. $options['relative'] = false;
  123. $output->writeln('It looks like your system doesn\'t support relative symbolic links, so will fallback to absolute symbolic links instead!');
  124. }
  125. }
  126. if (!$options['relative']) {
  127. try {
  128. $filesystem->symlink(
  129. $extensionPath,
  130. $targetPath
  131. );
  132. } catch (IOException $e) {
  133. $options['copy'] = true;
  134. $output->writeln('It looks like your system doesn\'t support symbolic links, so will fallback to hard copy instead!');
  135. }
  136. }
  137. }
  138. if ($options['copy']) {
  139. $filesystem->mkdir($targetPath, 0777);
  140. $filesystem->mirror($extensionPath, $targetPath, Finder::create()->in($extensionPath));
  141. }
  142. return $targetPath;
  143. }
  144. /**
  145. * Removes the cwd from $path.
  146. *
  147. * @param string $path
  148. */
  149. private function removeCwd($path)
  150. {
  151. return str_replace(getcwd() . '/', '', $path);
  152. }
  153. }