diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php index 16c45c0228..16b9af4431 100644 --- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\AsseticBundle\DependencyInjection; +use Symfony\Component\Process\ExecutableFinder; +use Symfony\Component\Process\Exception\ExecutableNotFoundException; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; @@ -48,6 +50,7 @@ class Configuration implements ConfigurationInterface public function getConfigTreeBuilder() { $builder = new TreeBuilder(); + $finder = new ExecutableFinder(); $builder->root('assetic') ->children() @@ -55,9 +58,9 @@ class Configuration implements ConfigurationInterface ->booleanNode('use_controller')->defaultValue($this->debug)->end() ->scalarNode('read_from')->defaultValue('%kernel.root_dir%/../web')->end() ->scalarNode('write_to')->defaultValue('%assetic.read_from%')->end() - ->scalarNode('java')->defaultValue('/usr/bin/java')->end() - ->scalarNode('node')->defaultValue('/usr/bin/node')->end() - ->scalarNode('sass')->defaultValue('/usr/bin/sass')->end() + ->scalarNode('java')->defaultValue(function() use ($finder) { try { return $finder->find('java'); } catch(ExecutableNotFoundException $ex) { return null; } })->end() + ->scalarNode('node')->defaultValue(function() use ($finder) { try { return $finder->find('node'); } catch(ExecutableNotFoundException $ex) { return null; } })->end() + ->scalarNode('sass')->defaultValue(function() use ($finder) { try { return $finder->find('sass'); } catch(ExecutableNotFoundException $ex) { return null; } })->end() ->end() // bundles diff --git a/src/Symfony/Component/Process/Exception/Exception.php b/src/Symfony/Component/Process/Exception/Exception.php new file mode 100644 index 0000000000..0f4e490d02 --- /dev/null +++ b/src/Symfony/Component/Process/Exception/Exception.php @@ -0,0 +1,12 @@ + + */ +interface Exception +{ +} \ No newline at end of file diff --git a/src/Symfony/Component/Process/Exception/ExecutableNotFoundException.php b/src/Symfony/Component/Process/Exception/ExecutableNotFoundException.php new file mode 100644 index 0000000000..7fc87c22ed --- /dev/null +++ b/src/Symfony/Component/Process/Exception/ExecutableNotFoundException.php @@ -0,0 +1,25 @@ + + */ +class ExecutableNotFoundException extends RuntimeException +{ + private $name; + + public function __construct($name) + { + parent::__construct(sprintf('Could not find executable "%s".', $name)); + + $this->name = $name; + } + + public function getName() + { + return $this->name; + } +} \ No newline at end of file diff --git a/src/Symfony/Component/Process/Exception/RuntimeException.php b/src/Symfony/Component/Process/Exception/RuntimeException.php new file mode 100644 index 0000000000..4dd0f5f203 --- /dev/null +++ b/src/Symfony/Component/Process/Exception/RuntimeException.php @@ -0,0 +1,12 @@ + + */ +class RuntimeException extends \RuntimeException implements Exception +{ +} \ No newline at end of file diff --git a/src/Symfony/Component/Process/ExecutableFinder.php b/src/Symfony/Component/Process/ExecutableFinder.php new file mode 100644 index 0000000000..6c774d6900 --- /dev/null +++ b/src/Symfony/Component/Process/ExecutableFinder.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +use Symfony\Component\Process\Exception\ExecutableNotFoundException; + +/** + * Generic executable finder. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class ExecutableFinder +{ + private $suffixes = array('.exe', '.bat', '.cmd', '.com'); + + public function setSuffixes(array $suffixes) + { + $this->suffixes = $suffixes; + } + + public function addSuffix($suffix) + { + $this->suffixes[] = $suffix; + } + + public function find($name) + { + $dirs = explode(PATH_SEPARATOR, getenv('PATH') ? getenv('PATH') : getenv('Path')); + $suffixes = DIRECTORY_SEPARATOR == '\\' ? (getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : $this->suffixes) : array(''); + foreach ($suffixes as $suffix) { + foreach ($dirs as $dir) { + if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && is_executable($file)) { + return $file; + } + } + } + + throw new ExecutableNotFoundException($name); + } +} \ No newline at end of file diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php new file mode 100644 index 0000000000..a53a922f66 --- /dev/null +++ b/src/Symfony/Component/Process/PhpExecutableFinder.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process; + +use Symfony\Component\Process\Exception\RuntimeException; + +/** + * An executable finder specifically designed for the PHP executable. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class PhpExecutableFinder +{ + private $executableFinder; + + public function __construct() + { + $this->executableFinder = new ExecutableFinder(); + } + + public function find() + { + if ($php = getenv('PHP_PATH')) { + if (!is_executable($php)) { + throw new RuntimeException('The defined PHP_PATH environment variable is not a valid PHP executable.'); + } + + return $php; + } + + $suffixes = DIRECTORY_SEPARATOR == '\\' ? (getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe', '.bat', '.cmd', '.com')) : array(''); + foreach ($suffixes as $suffix) { + if (is_executable($php = PHP_BINDIR.DIRECTORY_SEPARATOR.'php'.$suffix)) { + return $php; + } + } + + if ($php = getenv('PHP_PEAR_PHP_BIN')) { + if (is_executable($php)) { + return $php; + } + } + + return $this->executableFinder->find('php'); + } +} \ No newline at end of file diff --git a/src/Symfony/Component/Process/PhpProcess.php b/src/Symfony/Component/Process/PhpProcess.php index 628b3f3f40..1dd15886c2 100644 --- a/src/Symfony/Component/Process/PhpProcess.php +++ b/src/Symfony/Component/Process/PhpProcess.php @@ -24,6 +24,8 @@ namespace Symfony\Component\Process; */ class PhpProcess extends Process { + private $executableFinder; + /** * Constructor. * @@ -38,6 +40,8 @@ class PhpProcess extends Process public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array()) { parent::__construct(null, $cwd, $env, $script, $timeout, $options); + + $this->executableFinder = new PhpExecutableFinder(); } /** @@ -63,42 +67,9 @@ class PhpProcess extends Process public function run($callback = null) { if (null === $this->getCommandLine()) { - $this->setCommandLine($this->getPhpBinary()); + $this->setCommandLine($this->executableFinder->find()); } return parent::run($callback); } - - /** - * Returns the PHP binary path. - * - * @return string The PHP binary path - * - * @throws \RuntimeException When defined PHP_PATH is not executable or not found - */ - private function getPhpBinary() - { - if ($php = getenv('PHP_PATH')) { - if (!is_executable($php)) { - throw new \RuntimeException('The defined PHP_PATH environment variable is not a valid PHP executable.'); - } - - return $php; - } - - $suffixes = DIRECTORY_SEPARATOR == '\\' ? (getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe', '.bat', '.cmd', '.com')) : array(''); - foreach ($suffixes as $suffix) { - if (is_executable($php = PHP_BINDIR.DIRECTORY_SEPARATOR.'php'.$suffix)) { - return $php; - } - } - - if ($php = getenv('PHP_PEAR_PHP_BIN')) { - if (is_executable($php)) { - return $php; - } - } - - throw new \RuntimeException('Unable to find the PHP executable.'); - } }