diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php
index 090e8b5057..efcd24cdcd 100644
--- a/lib/Alchemy/Phrasea/Application.php
+++ b/lib/Alchemy/Phrasea/Application.php
@@ -88,6 +88,8 @@ use Alchemy\Phrasea\Core\Provider\FtpServiceProvider;
use Alchemy\Geonames\GeonamesServiceProvider;
use Alchemy\Phrasea\Core\Provider\InstallerServiceProvider;
use Alchemy\Phrasea\Core\Provider\JMSSerializerServiceProvider;
+use Alchemy\Phrasea\Core\Provider\LessBuilderServiceProvider;
+use Alchemy\Phrasea\Core\Provider\LessCompilerServiceProvider;
use Alchemy\Phrasea\Core\Provider\LocaleServiceProvider;
use Alchemy\Phrasea\Core\Provider\NotificationDelivererServiceProvider;
use Alchemy\Phrasea\Core\Provider\ORMServiceProvider;
@@ -255,6 +257,8 @@ class Application extends SilexApplication
$this->register(new PluginServiceProvider());
$this->register(new PHPExiftoolServiceProvider());
$this->register(new ReCaptchaServiceProvider());
+ $this->register(new LessCompilerServiceProvider());
+ $this->register(new LessBuilderServiceProvider());
$this['recaptcha.public-key'] = $this->share(function (Application $app) {
if ($app['phraseanet.registry']->get('GV_captchas')) {
diff --git a/lib/Alchemy/Phrasea/Command/Developer/LessCompiler.php b/lib/Alchemy/Phrasea/Command/Developer/LessCompiler.php
index d434d1cb49..4262a6fa7d 100644
--- a/lib/Alchemy/Phrasea/Command/Developer/LessCompiler.php
+++ b/lib/Alchemy/Phrasea/Command/Developer/LessCompiler.php
@@ -12,11 +12,9 @@
namespace Alchemy\Phrasea\Command\Developer;
use Alchemy\Phrasea\Command\Command;
-use Alchemy\Phrasea\Exception\RuntimeException;
use Alchemy\Phrasea\Utilities\Compiler\RecessLessCompiler;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Process\ProcessBuilder;
/**
* This command builds less file
@@ -40,29 +38,6 @@ class LessCompiler extends Command
*/
protected function doExecute(InputInterface $input, OutputInterface $output)
{
- $files = array(
- $this->container['root.path'] . '/www/skins/login/less/login.less' => $this->container['root.path'] . '/www/skins/build/login.css',
- $this->container['root.path'] . '/www/skins/account/account.less' => $this->container['root.path'] . '/www/skins/build/account.css',
- $this->container['root.path'] . '/www/assets/bootstrap/less/bootstrap.less' => $this->container['root.path'] . '/www/skins/build/bootstrap/css/bootstrap.css',
- $this->container['root.path'] . '/www/assets/bootstrap/less/responsive.less' => $this->container['root.path'] . '/www/skins/build/bootstrap/css/bootstrap-responsive.css',
- );
-
- $output->writeln('Building Assets...');
-
- $failures = 0;
- $errors = array();
- foreach ($files as $lessFile => $target) {
- $this->container['filesystem']->mkdir(dirname($target));
- $output->writeln(sprintf('Building %s', basename($lessFile)));
-
- try {
- $this->recessLessCompiler->compile($target, $lessFile);
- } catch (\Exception $e) {
- $failures++;
- $errors[] = $e->getMessage();
- }
- }
-
$copies = array(
$this->container['root.path'] . '/www/assets/bootstrap/img/glyphicons-halflings-white.png' => $this->container['root.path'] . '/www/skins/build/bootstrap/img/glyphicons-halflings-white.png',
$this->container['root.path'] . '/www/assets/bootstrap/img/glyphicons-halflings.png' => $this->container['root.path'] . '/www/skins/build/bootstrap/img/glyphicons-halflings.png',
@@ -73,14 +48,23 @@ class LessCompiler extends Command
$this->container['filesystem']->copy($source, $target);
}
- if (0 === $failures) {
- $output->writeln('Build done !');
+ $files = array(
+ $this->container['root.path'] . '/www/skins/login/less/login.less' => $this->container['root.path'] . '/www/skins/build/login.css',
+ $this->container['root.path'] . '/www/skins/account/account.less' => $this->container['root.path'] . '/www/skins/build/account.css',
+ $this->container['root.path'] . '/www/assets/bootstrap/less/bootstrap.less' => $this->container['root.path'] . '/www/skins/build/bootstrap/css/bootstrap.css',
+ $this->container['root.path'] . '/www/assets/bootstrap/less/responsive.less' => $this->container['root.path'] . '/www/skins/build/bootstrap/css/bootstrap-responsive.css',
+ );
- return 0;
+ $output->writeln('Building Assets...');
+
+ if (false === $this->container['phraseanet.less-builder']->build($files)) {
+ $output->writeln(sprintf('Errors occured during the build %s', implode(', ', $this->container['phraseanet.less-builder']->getErrors())));
+
+ return 1;
}
- $output->writeln(sprintf('%d errors occured during the build %s', $failures, implode(', ', $errors)));
+ $output->writeln('Build done !');
- return 1;
+ return 0;
}
}
diff --git a/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php b/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php
index e241c92d98..31d2437faf 100644
--- a/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php
+++ b/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php
@@ -37,5 +37,14 @@ abstract class AbstractPluginCommand extends Command
$output->write("Updating config files...");
$this->container['plugins.autoloader-generator']->write($manifests);
$output->writeln(" OK");
+
+ $output->write('Building Assets...');
+ if (false === $this->container['phraseanet.less-builder']->build(array(
+ $this->container['root.path'] . '/www/skins/login/less/login.less' => $this->container['root.path'] . '/www/skins/build/login.css',
+ $this->container['root.path'] . '/www/skins/account/account.less' => $this->container['root.path'] . '/www/skins/build/account.css',
+ ))) {
+ $output->writeln(sprintf('Error(s) occured during the build %s', implode(', ', $this->container['phraseanet.less-builder']->getErrors())));
+ }
+ $output->writeln(" OK");
}
}
diff --git a/lib/Alchemy/Phrasea/Core/Provider/LessBuilderServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/LessBuilderServiceProvider.php
new file mode 100644
index 0000000000..43d3dee191
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Core/Provider/LessBuilderServiceProvider.php
@@ -0,0 +1,30 @@
+share(function($app) {
+ return new LessBuilder($app['phraseanet.less-compiler'], $app['filesystem']);
+ });
+ }
+
+ public function boot(Application $app)
+ {
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Core/Provider/LessCompilerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/LessCompilerServiceProvider.php
new file mode 100644
index 0000000000..f19a829f5a
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Core/Provider/LessCompilerServiceProvider.php
@@ -0,0 +1,30 @@
+share(function($app) {
+ return LessCompiler::create($app);
+ });
+ }
+
+ public function boot(Application $app)
+ {
+ }
+}
\ No newline at end of file
diff --git a/lib/Alchemy/Phrasea/Plugin/Management/AutoloaderGenerator.php b/lib/Alchemy/Phrasea/Plugin/Management/AutoloaderGenerator.php
index 71a65b6ab2..40ed2822c6 100644
--- a/lib/Alchemy/Phrasea/Plugin/Management/AutoloaderGenerator.php
+++ b/lib/Alchemy/Phrasea/Plugin/Management/AutoloaderGenerator.php
@@ -28,11 +28,53 @@ class AutoloaderGenerator
->doWrite('autoload.php', $this->createLoader($manifests))
->doWrite('services.php', $this->createServices($manifests))
->doWrite('commands.php', $this->createCommands($manifests))
- ->doWrite('twig-paths.php', $this->createTwigPathsMap($manifests));
+ ->doWrite('twig-paths.php', $this->createTwigPathsMap($manifests))
+ ->doWrite('login.less', $this->createLoginLess($manifests))
+ ->doWrite('account.less', $this->createAccountLess($manifests));
return $this;
}
+ private function createLoginLess($manifests)
+ {
+ $buffer = <<pluginDirectory . DIRECTORY_SEPARATOR . $manifest->getName() . DIRECTORY_SEPARATOR . 'login.less';
+ if (is_file($filepath)) {
+ $relativePath = $manifest->getName() . DIRECTORY_SEPARATOR . 'login.less';
+ $buffer .= <<pluginDirectory . DIRECTORY_SEPARATOR . $manifest->getName() . DIRECTORY_SEPARATOR . 'account.less';
+ if (is_file($filepath)) {
+ $relativePath = $manifest->getName() . DIRECTORY_SEPARATOR . 'account.less';
+ $buffer .= <<pluginDirectory . DIRECTORY_SEPARATOR . $file, $data)) {
diff --git a/lib/Alchemy/Phrasea/Utilities/Compiler/RecessLessCompiler.php b/lib/Alchemy/Phrasea/Utilities/Compiler/RecessLessCompiler.php
deleted file mode 100644
index 96ee79f953..0000000000
--- a/lib/Alchemy/Phrasea/Utilities/Compiler/RecessLessCompiler.php
+++ /dev/null
@@ -1,59 +0,0 @@
-filesystem = $filesystem ?: new Filesystem();
- }
-
- public function compile($target, $files)
- {
- $this->filesystem->mkdir(dirname($target));
-
- if (!$files instanceof \Traversable) {
- $files = new \ArrayObject(is_array($files) ? $files : array($files));
- }
-
- $files = new ArrayCollection((array) $files);
-
- if ($files->forAll(function($file) {
- return is_file($file);
- })) {
- throw new RuntimeException(realpath($files) . ' does not exists.');
- }
-
- if (!is_writable(dirname($target))) {
- throw new RuntimeException(realpath(dirname($target)) . ' is not writable.');
- }
-
- $builder = ProcessBuilder::create(array_merge(array(
- 'recess',
- '--compile'
- ), $files->toArray()));
-
- $process = $builder->getProcess();
- $process->run();
-
- if (!$process->isSuccessful()) {
- throw new RuntimeException(sprintf('An errord occured during the build %s', $process->getErrorOutput()));
- }
-
- $this->filesystem->dumpFile($target, $process->getOutput());
- }
-}
\ No newline at end of file
diff --git a/lib/Alchemy/Phrasea/Utilities/Less/Builder.php b/lib/Alchemy/Phrasea/Utilities/Less/Builder.php
new file mode 100644
index 0000000000..5789aefcf8
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Utilities/Less/Builder.php
@@ -0,0 +1,71 @@
+compiler = $compiler;
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * Build LESS files
+ *
+ * @param array $files
+ */
+ public function build($files)
+ {
+ $failures = 0;
+ $this->errors = array();
+
+ foreach ($files as $lessFile => $target) {
+ $this->filesystem->mkdir(dirname($target));
+
+ try {
+ $this->compiler->compile($target, $lessFile);
+ } catch (\Exception $e) {
+ $failures++;
+ $this->errors[] = $e->getMessage();
+ }
+ }
+
+ return $this->hasErrors();
+ }
+
+ public function hasErrors()
+ {
+ return count($this->errors) === 0;
+ }
+
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Utilities/Less/Compiler.php b/lib/Alchemy/Phrasea/Utilities/Less/Compiler.php
new file mode 100644
index 0000000000..5047546f09
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Utilities/Less/Compiler.php
@@ -0,0 +1,69 @@
+filesystem = $filesystem;
+ $this->recess = $recess;
+ }
+
+ public static function create(Application $app)
+ {
+ $binaries = $app['phraseanet.configuration']['binaries'];
+
+ return new self($app['filesystem'], RecessDriver::create($binaries));
+ }
+
+ public function compile($target, $files)
+ {
+ $this->filesystem->mkdir(dirname($target));
+
+ if (!$files instanceof \Traversable) {
+ $files = new \ArrayObject(is_array($files) ? $files : array($files));
+ }
+
+ $files = new ArrayCollection((array) $files);
+
+ if ($files->forAll(function($file) {
+ return is_file($file);
+ })) {
+ throw new RuntimeException($files . ' does not exists.');
+ }
+
+ if (!is_writable(dirname($target))) {
+ throw new RuntimeException(realpath(dirname($target)) . ' is not writable.');
+ }
+
+ $commands = $files->toArray();
+ array_unshift($commands, '--compile');
+
+ try {
+ $output = $this->recess->command($commands);
+ $this->filesystem->dumpFile($target, $output);
+ } catch (ExecutionFailureException $e) {
+ throw new RuntimeException('Could not execute recess command.', $e->getCode(), $e);
+ }
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Utilities/Less/RecessDriver.php b/lib/Alchemy/Phrasea/Utilities/Less/RecessDriver.php
new file mode 100644
index 0000000000..be447d7948
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Utilities/Less/RecessDriver.php
@@ -0,0 +1,36 @@
+get('recess.binaries', array('recess'));
+
+ return static::load($binaries, $logger, $conf);
+ }
+}
diff --git a/tests/Alchemy/Tests/Phrasea/Core/Provider/LessBuilderServiceProviderTest.php b/tests/Alchemy/Tests/Phrasea/Core/Provider/LessBuilderServiceProviderTest.php
new file mode 100644
index 0000000000..d7922afa9a
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Core/Provider/LessBuilderServiceProviderTest.php
@@ -0,0 +1,16 @@
+cleanup($files);
@@ -65,6 +67,9 @@ class AutoloaderGeneratorTest extends \PHPUnit_Framework_TestCase
$mapping = require $pluginsDir . '/twig-paths.php';
$this->assertSame(array('plugin-test-plugin' => $pluginsDir . '/test-plugin/views', $pluginsDir . '/test-plugin/views', $pluginsDir . '/test-plugin/twig-views'), $mapping);
+ $this->assertRegExp('#@import#', file_get_contents($pluginsDir . '/login.less'));
+ $this->assertRegExp('#@import#', file_get_contents($pluginsDir . '/account.less'));
+
$this->cleanup($files);
}
diff --git a/tests/Alchemy/Tests/Phrasea/Utilities/Less/BuilderTest.php b/tests/Alchemy/Tests/Phrasea/Utilities/Less/BuilderTest.php
new file mode 100644
index 0000000000..811a0e761e
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Utilities/Less/BuilderTest.php
@@ -0,0 +1,34 @@
+getMockBuilder('Alchemy\Phrasea\Utilities\Less\Compiler')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $compiler->expects($this->once())->method('compile');
+
+ $filesystem = $this->getMock('Symfony\Component\Filesystem\Filesystem');
+ $filesystem->expects($this->once())->method('mkdir');
+
+ $builder = new Builder($compiler, $filesystem);
+
+ $build = $builder->build(array( __FILE__ => __DIR__ . '/output.css'));
+
+ $this->assertTrue($build);
+ }
+}
diff --git a/tests/Alchemy/Tests/Phrasea/Utilities/Less/CompilerTest.php b/tests/Alchemy/Tests/Phrasea/Utilities/Less/CompilerTest.php
new file mode 100644
index 0000000000..036acd8562
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Utilities/Less/CompilerTest.php
@@ -0,0 +1,31 @@
+getMock('Alchemy\BinaryDriver\BinaryInterface');
+ $recessDriver->expects($this->once())->method('command');
+
+ $filesystem = $this->getMock('Symfony\Component\Filesystem\Filesystem');
+ $filesystem->expects($this->once())->method('mkdir');
+ $filesystem->expects($this->once())->method('dumpFile');
+
+ $compiler = new Compiler($filesystem, $recessDriver);
+
+ $compiler->compile(__DIR__ . '/output.css', __FILE__);
+ }
+}
diff --git a/tests/Alchemy/Tests/Phrasea/Utilities/Less/RecessDriverTest.php b/tests/Alchemy/Tests/Phrasea/Utilities/Less/RecessDriverTest.php
new file mode 100644
index 0000000000..0543e1b314
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Utilities/Less/RecessDriverTest.php
@@ -0,0 +1,31 @@
+assertInstanceOf('Alchemy\BinaryDriver\BinaryInterface', $recessDriver);
+ }
+
+ public function testGetName()
+ {
+ $recessDriver = RecessDriver::create();
+
+ $this->assertEquals('recess', $recessDriver->getName());
+ }
+}
diff --git a/www/skins/account/account.less b/www/skins/account/account.less
index e8df9f5db4..b2d346b460 100644
--- a/www/skins/account/account.less
+++ b/www/skins/account/account.less
@@ -4,6 +4,7 @@
// Core variables and mixins
@import "../../assets/bootstrap/less/variables.less";
@import "variables.less";
+@import "../../../plugins/account.less";
@import "../../assets/bootstrap/less/mixins.less";
// Grid system and page structure
@@ -55,6 +56,7 @@
// Responsive
@import "../../assets/bootstrap/less/responsive.less";
-@import "responsive.less";
+@import "variables.less";
+@import "../../../plugins/account.less";
@import "skin.less";
diff --git a/www/skins/account/responsive.less b/www/skins/account/responsive.less
deleted file mode 100644
index c4f2ac873b..0000000000
--- a/www/skins/account/responsive.less
+++ /dev/null
@@ -1,2 +0,0 @@
-
-@import "variables.less";
\ No newline at end of file
diff --git a/www/skins/login/less/login.less b/www/skins/login/less/login.less
index 204f3017a2..51a0246475 100644
--- a/www/skins/login/less/login.less
+++ b/www/skins/login/less/login.less
@@ -3,7 +3,10 @@
// Core variables and mixins
@import "../../../assets/bootstrap/less/variables.less";
+
@import "variables.less";
+@import "../../../../plugins/login.less";
+
@import "../../../assets/bootstrap/less/mixins.less";
// Grid system and page structure
@@ -55,6 +58,8 @@
// Responsive
@import "../../../assets/bootstrap/less/responsive.less";
-@import "responsive.less";
+
+@import "variables.less";
+@import "../../../../plugins/login.less";
@import "skin.less";
diff --git a/www/skins/login/less/responsive.less b/www/skins/login/less/responsive.less
deleted file mode 100644
index c4f2ac873b..0000000000
--- a/www/skins/login/less/responsive.less
+++ /dev/null
@@ -1,2 +0,0 @@
-
-@import "variables.less";
\ No newline at end of file