8000 feature #14235 [FrameworkBundle] Refactored assets:install command an… · symfony/symfony@8e1af88 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8e1af88

Browse files
committed
feature #14235 [FrameworkBundle] Refactored assets:install command and apply Symfony styles (1ed)
This PR was submitted for the 2.7 branch but it was merged into the 2.8 branch instead (closes #14235). Discussion ---------- [FrameworkBundle] Refactored assets:install command and apply Symfony styles | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Replaces #13057 ![screenshot from 2015-04-06 17 26 47](https://cloud.githubusercontent.com/assets/162986/7006783/242312f0-dc84-11e4-80ae-7d584ceae2f2.png) ![screenshot from 2015-04-06 17 26 16](https://cloud.githubusercontent.com/assets/162986/7006784/24237ff6-dc84-11e4-9678-ca5afe4b73fe.png) ![screenshot from 2015-04-09 10 24 59](https://cloud.githubusercontent.com/assets/162986/7063056/96c71baa-dea3-11e4-981c-a4ef4fa59cfb.png) ![screenshot from 2015-04-06 17 33 46](https://cloud.githubusercontent.com/assets/162986/7006782/2421e22c-dc84-11e4-9d1f-c1b91a7c0abe.png) ![screenshot from 2015-04-06 20 14 57](https://cloud.githubusercontent.com/assets/162986/7009308/a1aae2e2-dc99-11e4-9c00-c1f60bc55abf.png) Commits ------- 8b7b251 [FrameworkBundle] Refactor assets:install command and apply SymfonyStyle
2 parents 3ebe466 + 8b7b251 commit 8e1af88

File tree

1 file changed

+152
-53
lines changed

1 file changed

+152
-53
lines changed

src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php

Lines changed: 152 additions & 53 deletions
< 8000 /tr>
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,34 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Command;
1313

14+
use Symfony\Component\Console\Helper\Table;
1415
use Symfony\Component\Console\Input\InputArgument;
15-
use Symfony\Component\Console\Input\InputOption;
1616
use Symfony\Component\Console\Input\InputInterface;
17+
use Symfony\Component\Console\Input\InputOption;
1718
use Symfony\Component\Console\Output\OutputInterface;
19+
use Symfony\Component\Console\Style\SymfonyStyle;
1820
use Symfony\Component\Filesystem\Exception\IOException;
21+
use Symfony\Component\Filesystem\Filesystem;
1922
use Symfony\Component\Finder\Finder;
23+
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
2024

2125
/**
2226
* Command that places bundle web assets into a given directory.
2327
*
2428
* @author Fabien Potencier <fabien@symfony.com>
29+
* @author Gábor Egyed <gabor.egyed@gmail.com>
2530
*/
2631
class AssetsInstallCommand extends ContainerAwareCommand
2732
{
33+
const METHOD_COPY = 'copy';
34+
const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink';
35+
const METHOD_RELATIVE_SYMLINK = 'relative symlink';
36+
37+
/**
38+
* @var Filesystem
39+
*/
40+
private $filesystem;
41+
2842
/**
2943
* {@inheritdoc}
3044
*/
@@ -63,8 +77,6 @@ protected function configure()
6377

6478
/**
6579
* {@inheritdoc}
66-
*
67-
* @throws \InvalidArgumentException When the target directory does not exist or symlink cannot be used
6880
*/
6981
protected function execute(InputInterface $input, OutputInterface $output)
7082
{
@@ -74,77 +86,164 @@ protected function execute(InputInterface $input, OutputInterface $output)
7486
throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
7587
}
7688

77-
$filesystem = $this->getContainer()->get('filesystem');
89+
$this->filesystem = $this->getContainer()->get('filesystem');
7890

7991
// Create the bundles directory otherwise symlink will fail.
8092
$bundlesDir = $targetArg.'/bundles/';
81-
$filesystem->mkdir($bundlesDir, 0777);
93+
$this->filesystem->mkdir($bundlesDir, 0777);
8294

83-
// relative implies symlink
84-
$symlink = $input->getOption('symlink') || $input->getOption('relative');
95+
$io = new SymfonyStyle($input, $output);
96+
$io->newLine();
8597

86-
if ($symlink) {
87-
$output->writeln('Trying to install assets as <comment>symbolic links</comment>.');
98+
if ($input->getOption('relative')) {
99+
$expectedMethod = self::METHOD_RELATIVE_SYMLINK;
100+
$io->text('Trying to install assets as <info>relative symbolic links</info>.');
101+
} elseif ($input->getOption('symlink')) {
102+
$expectedMethod = self::METHOD_ABSOLUTE_SYMLINK;
103+
$io->text('Trying to install assets as <info>absolute symbolic links</info>.');
88104
} else {
89-
$output->writeln('Installing assets as <comment>hard copies</comment>.');
105+
$expectedMethod = self::METHOD_COPY;
106+
$io->text('Installing assets as <info>hard copies</info>.');
90107
}
91108

109+
$io->newLine();
110+
111+
$rows = array();
112+
$copyUsed = false;
113+
$exitCode = 0;
114+
/** @var BundleInterface $bundle */
92115
foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) {
93-
if (is_dir($originDir = $bundle->getPath().'/Resources/public')) {
94-
$targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
95-
96-
$output->writeln(sprintf('Installing assets for <comment>%s</comment> into <comment>%s</comment>', $bundle->getNamespace(), $targetDir));
97-
98-
$filesystem->remove($targetDir);
99-
100-
if ($symlink) {
101-
if ($input->getOption('relative')) {
102-
$relativeOriginDir = $filesystem->makePathRelative($originDir, realpath($bundlesDir));
103-
} else {
104-
$relativeOriginDir = $originDir;
105-
}
106-
107-
try {
108-
$filesystem->symlink($relativeOriginDir, $targetDir);
109-
if (!file_exists($targetDir)) {
110-
throw new IOException('Symbolic link is broken');
111-
}
112-
$output->writeln('The assets were installed using symbolic links.');
113-
} catch (IOException $e) {
114-
if (!$input->getOption('relative')) {
115-
$this->hardCopy($originDir, $targetDir);
116-
$output->writeln('It looks like your system doesn\'t support symbolic links, so the assets were installed by copying them.');
117-
}
118-
119-
// try again without the relative option
120-
try {
121-
$filesystem->symlink($originDir, $targetDir);
122-
if (!file_exists($targetDir)) {
123-
throw new IOException('Symbolic link is broken');
124-
}
125-
$output->writeln('It looks like your system doesn\'t support relative symbolic links, so the assets were installed by using absolute symbolic links.');
126-
} catch (IOException $e) {
127-
$this->hardCopy($originDir, $targetDir);
128-
$output->writeln('It looks like your system doesn\'t support symbolic links, so the assets were installed by copying them.');
129-
}
130-
}
116+
if (!is_dir($originDir = $bundle->getPath().'/Resources/public')) {
117+
continue;
118+
}
119+
120+
$targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
121+
122+
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
123+
$message = sprintf("%s\n-> %s", $bundle->getName(), $targetDir);
124+
} else {
125+
$message = $bundle->getName();
126+
}
127+
128+
try {
129+
$this->filesystem->remove($targetDir);
130+
131+
if (self::METHOD_RELATIVE_SYMLINK === $expectedMethod) {
132+
$method = $this->relativeSymlinkWithFallback($originDir, $targetDir);
133+
} elseif (self::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) {
134+
$method = $this->absoluteSymlinkWithFallback($originDir, $targetDir);
135+
} else {
136+
$method = $this->hardCopy($originDir, $targetDir);
137+
}
138+
139+
if (self::METHOD_COPY === $method) {
140+
$copyUsed = true;
141+
}
142+
143+
if ($method === $expectedMethod) {
144+
$rows[] = array(sprintf('<fg=green;options=bold>%s</>', '\\' === DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */), $message, $method);
131145
} else {
132-
$this->hardCopy($originDir, $targetDir);
146+
$rows[] = array(sprintf('<fg=yellow;options=bold>%s</>', '\\' === DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method);
133147
}
148+
} catch (\Exception $e) {
149+
$exitCode = 1;
150+
$rows[] = array(sprintf('<fg=red;options=bold>%s</>', '\\' === DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage());
151+
}
152+
}
153+
154+
$io->table(array('', 'Bundle', 'Method / Error'), $rows);
155+
156+
if (0 !== $exitCode) {
157+
$io->error('Some errors occurred while installing assets.');
158+
} else {
159+
if ($copyUsed) {
160+
$io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.');
134161
}
162+
$io->success('All assets were successfully installed.');
135163
}
164+
165+
return $exitCode;
136166
}
137167

138168
/**
169+
* Try to create relative symlink.
170+
*
171+
* Falling back to absolute symlink and finally hard copy.
172+
*
139173
* @param string $originDir
140174
* @param string $targetDir
175+
*
176+
* @return string
141177
*/
142-
private function hardCopy($originDir, $targetDir)
178+
private function relativeSymlinkWithFallback($originDir, $targetDir)
179+
{
180+
try {
181+
$this->symlink($originDir, $targetDir, true);
182+
$method = self::METHOD_RELATIVE_SYMLINK;
183+
} catch (IOException $e) {
184+
$method = $this->absoluteSymlinkWithFallback($originDir, $targetDir);
185+
}
186+
187+
return $method;
188+
}
189+
190+
/**
191+
* Try to create absolute symlink.
192+
*
193+
* Falling back to hard copy.
194+
*
195+
* @param string $originDir
196+
* @param string $targetDir
197+
*
198+
* @return string
199+
*/
200+
private function absoluteSymlinkWithFallback($originDir, $targetDir)
201+
{
202+
try {
203+
$this->symlink($originDir, $targetDir);
204+
$method = self::METHOD_ABSOLUTE_SYMLINK;
205+
} catch (IOException $e) {
206+
// fall back to copy
207+
$method = $this->hardCopy($originDir, $targetDir);
208+
}
209+
210+
return $method;
211+
}
212+
213+
/**
214+
* Creates symbolic link.
215+
*
216+
* @param string $originDir
217+
* @param string $targetDir
218+
* @param bool $relative
219+
*
220+
* @throws IOException If link can not be created.
221+
*/
222+
private function symlink($originDir, $targetDir, $relative = false)
143223
{
144-
$filesystem = $this->getContainer()->get('filesystem');
224+
if ($relative) {
225+
$originDir = $this->filesystem->makePathRelative($originDir, realpath(dirname($targetDir)));
226+
}
227+
$this->filesystem->symlink($originDir, $targetDir);
228+
if (!file_exists($targetDir)) {
229+
throw new IOException(sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir);
230+
}
231+
}
145232

146-
$filesystem->mkdir($targetDir, 0777);
233+
/**
234+
* Copies origin to target.
235+
*
236+
* @param string $originDir
237+
* @param string $targetDir
238+
*
239+
* @return string
240+
*/
241+
private function hardCopy($originDir, $targetDir)
242+
{
243+
$this->filesystem->mkdir($targetDir, 0777);
147244
// We use a custom iterator to ignore VCS files
148-
$filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir));
245+
$this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir));
246+
247+
return self::METHOD_COPY;
149248
}
150249
}

0 commit comments

Comments
 (0)
0