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

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('ezpublish:legacybundles:install_extensions')
  43. ->addOption('copy', null, InputOption::VALUE_NONE, 'Creates copies of the extensions instead of using a symlink')
  44. ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks')
  45. ->addOption('force', null, InputOption::VALUE_NONE, 'Force overwriting of existing directory (will be removed)')
  46. ->setDescription('Installs legacy extensions (default: symlink) defined in Symfony bundles into ezpublish_legacy/extensions')
  47. ->setHelp(
  48. <<<EOT
  49. The command <info>%command.name%</info> installs <info>legacy extensions</info> stored in a Symfony bundle
  50. into the ezpublish_legacy/extension folder.
  51. EOT
  52. );
  53. }
  54. protected function execute(InputInterface $input, OutputInterface $output): int
  55. {
  56. $options = [
  57. 'copy' => (bool)$input->getOption('copy'),
  58. 'relative' => (bool)$input->getOption('relative'),
  59. 'force' => (bool)$input->getOption('force'),
  60. ];
  61. foreach ($this->kernel->getBundles() as $bundle) {
  62. foreach ($this->legacyExtensionsLocator->getExtensionDirectories($bundle->getPath()) as $extensionDir) {
  63. $output->writeln('- ' . $this->removeCwd($extensionDir));
  64. try {
  65. $target = $this->linkLegacyExtension($extensionDir, $options, $output);
  66. $output->writeln(' <info>' . ($options['copy'] ? 'Copied' : 'linked') . "</info> to $target</info>");
  67. } catch (RuntimeException $e) {
  68. $output->writeln(' <error>' . $e->getMessage() . '</error>');
  69. }
  70. }
  71. }
  72. return 0;
  73. }
  74. /**
  75. * Links the legacy extension at $path into ezpublish_legacy/extensions.
  76. *
  77. * @param string $extensionPath Absolute path to a legacy extension folder
  78. * @param array $options
  79. * @param OutputInterface $output
  80. *
  81. * @throws \RuntimeException If a target link/directory exists and $options[force] isn't set to true
  82. *
  83. * @return string The resulting link/directory
  84. */
  85. protected function linkLegacyExtension($extensionPath, array $options = [], OutputInterface $output)
  86. {
  87. $options += ['force' => false, 'copy' => false, 'relative' => false];
  88. $filesystem = $this->filesystem;
  89. $legacyRootDir = rtrim($this->legacyRootDir, '/');
  90. $relativeExtensionPath = $filesystem->makePathRelative($extensionPath, realpath("$legacyRootDir/extension/"));
  91. $targetPath = "$legacyRootDir/extension/" . basename($extensionPath);
  92. if (file_exists($targetPath) && $options['copy']) {
  93. if (!$options['force']) {
  94. throw new RuntimeException("Target directory $targetPath already exists");
  95. }
  96. $filesystem->remove($targetPath);
  97. }
  98. if (file_exists($targetPath) && !$options['copy']) {
  99. if (is_link($targetPath)) {
  100. $existingLinkTarget = readlink($targetPath);
  101. if ($existingLinkTarget == $extensionPath || $existingLinkTarget == $relativeExtensionPath) {
  102. return $targetPath;
  103. } elseif (!$options['force']) {
  104. throw new RuntimeException("Target $targetPath already exists with a different target");
  105. }
  106. } else {
  107. if (!$options['force']) {
  108. throw new RuntimeException("Target $targetPath already exists with a different target");
  109. }
  110. }
  111. $filesystem->remove($targetPath);
  112. }
  113. if (!$options['copy']) {
  114. if ($options['relative']) {
  115. try {
  116. $filesystem->symlink(
  117. $relativeExtensionPath,
  118. $targetPath
  119. );
  120. } catch (IOException $e) {
  121. $options['relative'] = false;
  122. $output->writeln('It looks like your system doesn\'t support relative symbolic links, so will fallback to absolute symbolic links instead!');
  123. }
  124. }
  125. if (!$options['relative']) {
  126. try {
  127. $filesystem->symlink(
  128. $extensionPath,
  129. $targetPath
  130. );
  131. } catch (IOException $e) {
  132. $options['copy'] = true;
  133. $output->writeln('It looks like your system doesn\'t support symbolic links, so will fallback to hard copy instead!');
  134. }
  135. }
  136. }
  137. if ($options['copy']) {
  138. $filesystem->mkdir($targetPath, 0777);
  139. $filesystem->mirror($extensionPath, $targetPath, Finder::create()->in($extensionPath));
  140. }
  141. return $targetPath;
  142. }
  143. /**
  144. * Removes the cwd from $path.
  145. *
  146. * @param string $path
  147. */
  148. private function removeCwd($path)
  149. {
  150. return str_replace(getcwd() . '/', '', $path);
  151. }
  152. }