diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
index 1aeb152161471..83a17d95f9681 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
@@ -74,14 +74,16 @@ protected function execute(InputInterface $input, OutputInterface $output)
foreach ($this->container->get('kernel')->getBundles() as $bundle) {
if (is_dir($originDir = $bundle->getPath().'/Resources/public')) {
- $targetDir = $input->getArgument('target').'/bundles/'.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
+ $bundlesDir = $input->getArgument('target').'/bundles/';
+ $targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
$output->writeln(sprintf('Installing assets for %s into %s', $bundle->getNamespace(), $targetDir));
$filesystem->remove($targetDir);
if ($input->getOption('symlink')) {
- $filesystem->symlink($originDir, $targetDir);
+ $relativeOriginDir = $this->makePathRelative($originDir, realpath($bundlesDir));
+ $filesystem->symlink($relativeOriginDir, $targetDir);
} else {
$filesystem->mkdir($targetDir, 0777);
$filesystem->mirror($originDir, $targetDir);
@@ -89,4 +91,31 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
}
+
+ /**
+ * Given an existing path, convert it to a path relative to a given starting path
+ *
+ * @var string Absolute path of target
+ * @var string Absolute path where traversal begins
+ * @return string Path of target relative to starting path
+ */
+ protected function makePathRelative($endPath, $startPath)
+ {
+ // Find for which character the the common path stops
+ $offset = 0;
+ while ($startPath[$offset] === $endPath[$offset]) {
+ $offset++;
+ }
+
+ // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
+ $depth = substr_count(substr($startPath, $offset), DIRECTORY_SEPARATOR) + 1;
+
+ // Repeated "../" for each level need to reach the common path
+ $traverser = str_repeat('../', $depth);
+
+ // Construct $endPath from traversing to the common path, then to the remaining $endPath
+ $relativePath = $traverser.substr($endPath, $offset);
+
+ return $relativePath;
+ }
}