537 lines
14 KiB
PHP
537 lines
14 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Zend Framework
|
||
|
*
|
||
|
* LICENSE
|
||
|
*
|
||
|
* This source file is subject to the new BSD license that is bundled
|
||
|
* with this package in the file LICENSE.txt.
|
||
|
* It is also available through the world-wide-web at this URL:
|
||
|
* http://framework.zend.com/license/new-bsd
|
||
|
* If you did not receive a copy of the license and are unable to
|
||
|
* obtain it through the world-wide-web, please send an email
|
||
|
* to license@zend.com so we can send you a copy immediately.
|
||
|
*
|
||
|
* @category Zend
|
||
|
* @package Zend_Dojo
|
||
|
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
|
||
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||
|
* @version $Id: BuildLayer.php 16971 2009-07-22 18:05:45Z mikaelkael $
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Dojo module layer and custom build profile generation support
|
||
|
*
|
||
|
* @package Zend_Dojo
|
||
|
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
|
||
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||
|
*/
|
||
|
class Zend_Dojo_BuildLayer
|
||
|
{
|
||
|
/**
|
||
|
* Flag: whether or not to consume JS aggregated in the dojo() view
|
||
|
* helper when generate the module layer contents
|
||
|
* @var bool
|
||
|
*/
|
||
|
protected $_consumeJavascript = false;
|
||
|
|
||
|
/**
|
||
|
* Flag: whether or not to consume dojo.addOnLoad events registered
|
||
|
* with the dojo() view helper when generating the module layer file
|
||
|
* contents
|
||
|
* @var bool
|
||
|
*/
|
||
|
protected $_consumeOnLoad = false;
|
||
|
|
||
|
/**
|
||
|
* Dojo view helper reference
|
||
|
* @var Zend_Dojo_View_Helper_Dojo_Container
|
||
|
*/
|
||
|
protected $_dojo;
|
||
|
|
||
|
/**
|
||
|
* Name of the custom layer to generate
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $_layerName;
|
||
|
|
||
|
/**
|
||
|
* Path to the custom layer script relative to dojo.js (used when
|
||
|
* creating the build profile)
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $_layerScriptPath;
|
||
|
|
||
|
/**
|
||
|
* Build profile options
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $_profileOptions = array(
|
||
|
'action' => 'release',
|
||
|
'optimize' => 'shrinksafe',
|
||
|
'layerOptimize' => 'shrinksafe',
|
||
|
'copyTests' => false,
|
||
|
'loader' => 'default',
|
||
|
'cssOptimize' => 'comments',
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* Associative array of module/path pairs for the build profile
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $_profilePrefixes = array();
|
||
|
|
||
|
/**
|
||
|
* Zend_View reference
|
||
|
* @var Zend_View_Interface
|
||
|
*/
|
||
|
protected $_view;
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
* @param array|Zend_Config $options
|
||
|
* @return void
|
||
|
* @throws Zend_Dojo_Exception for invalid option argument
|
||
|
*/
|
||
|
public function __construct($options = null)
|
||
|
{
|
||
|
if (null !== $options) {
|
||
|
if ($options instanceof Zend_Config) {
|
||
|
$options = $options->toArray();
|
||
|
} elseif (!is_array($options)) {
|
||
|
require_once 'Zend/Dojo/Exception.php';
|
||
|
throw new Zend_Dojo_Exception('Invalid options provided to constructor');
|
||
|
}
|
||
|
$this->setOptions($options);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set options
|
||
|
*
|
||
|
* Proxies to any setter that matches an option key.
|
||
|
*
|
||
|
* @param array $options
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setOptions(array $options)
|
||
|
{
|
||
|
$methods = get_class_methods($this);
|
||
|
foreach ($options as $key => $value) {
|
||
|
$method = 'set' . ucfirst($key);
|
||
|
if (in_array($method, $methods)) {
|
||
|
$this->$method($value);
|
||
|
}
|
||
|
}
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set View object
|
||
|
*
|
||
|
* @param Zend_View_Interface $view
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setView(Zend_View_Interface $view)
|
||
|
{
|
||
|
$this->_view = $view;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve view object
|
||
|
*
|
||
|
* @return Zend_View_Interface|null
|
||
|
*/
|
||
|
public function getView()
|
||
|
{
|
||
|
return $this->_view;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set dojo() view helper instance
|
||
|
*
|
||
|
* @param Zend_Dojo_View_Helper_Dojo_Container $helper
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setDojoHelper(Zend_Dojo_View_Helper_Dojo_Container $helper)
|
||
|
{
|
||
|
$this->_dojo = $helper;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve dojo() view helper instance
|
||
|
*
|
||
|
* Will retrieve it from the view object if not registered.
|
||
|
*
|
||
|
* @return Zend_Dojo_View_Helper_Dojo_Container
|
||
|
* @throws Zend_Dojo_Exception if not registered and no view object found
|
||
|
*/
|
||
|
public function getDojoHelper()
|
||
|
{
|
||
|
if (null === $this->_dojo) {
|
||
|
if (null === ($view = $this->getView())) {
|
||
|
require_once 'Zend/Dojo/Exception.php';
|
||
|
throw new Zend_Dojo_Exception('View object not registered; cannot retrieve dojo helper');
|
||
|
}
|
||
|
$helper = $view->getHelper('dojo');
|
||
|
$this->setDojoHelper($view->dojo());
|
||
|
}
|
||
|
return $this->_dojo;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set custom layer name; e.g. "custom.main"
|
||
|
*
|
||
|
* @param string $name
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setLayerName($name)
|
||
|
{
|
||
|
if (!preg_match('/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/i', $name)) {
|
||
|
require_once 'Zend/Dojo/Exception.php';
|
||
|
throw new Zend_Dojo_Exception('Invalid layer name provided; must be of form[a-z][a-z0-9_](\.[a-z][a-z0-9_])+');
|
||
|
}
|
||
|
$this->_layerName = $name;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve custom layer name
|
||
|
*
|
||
|
* @return string|null
|
||
|
*/
|
||
|
public function getLayerName()
|
||
|
{
|
||
|
return $this->_layerName;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the path to the custom layer script
|
||
|
*
|
||
|
* Should be a path relative to dojo.js
|
||
|
*
|
||
|
* @param string $path
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setLayerScriptPath($path)
|
||
|
{
|
||
|
$this->_layerScriptPath = (string) $path;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get custom layer script path
|
||
|
*
|
||
|
* @return string|null
|
||
|
*/
|
||
|
public function getLayerScriptPath()
|
||
|
{
|
||
|
return $this->_layerScriptPath;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set flag indicating whether or not to consume JS aggregated in dojo()
|
||
|
* view helper
|
||
|
*
|
||
|
* @param bool $flag
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setConsumeJavascript($flag)
|
||
|
{
|
||
|
$this->_consumeJavascript = (bool) $flag;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get flag indicating whether or not to consume JS aggregated in dojo()
|
||
|
* view helper
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function consumeJavascript()
|
||
|
{
|
||
|
return $this->_consumeJavascript;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set flag indicating whether or not to consume dojo.addOnLoad events
|
||
|
* aggregated in dojo() view helper
|
||
|
*
|
||
|
* @param bool $flag
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setConsumeOnLoad($flag)
|
||
|
{
|
||
|
$this->_consumeOnLoad = (bool) $flag;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get flag indicating whether or not to consume dojo.addOnLoad events aggregated in dojo() view helper
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function consumeOnLoad()
|
||
|
{
|
||
|
return $this->_consumeOnLoad;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set many build profile options at once
|
||
|
*
|
||
|
* @param array $options
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setProfileOptions(array $options)
|
||
|
{
|
||
|
$this->_profileOptions += $options;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add many build profile options at once
|
||
|
*
|
||
|
* @param array $options
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function addProfileOptions(array $options)
|
||
|
{
|
||
|
$this->_profileOptions = $this->_profileOptions + $options;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add a single build profile option
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @param value $value
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function addProfileOption($key, $value)
|
||
|
{
|
||
|
$this->_profileOptions[(string) $key] = $value;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Is a given build profile option set?
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function hasProfileOption($key)
|
||
|
{
|
||
|
return array_key_exists((string) $key, $this->_profileOptions);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve a single build profile option
|
||
|
*
|
||
|
* Returns null if profile option does not exist.
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function getProfileOption($key)
|
||
|
{
|
||
|
if ($this->hasProfileOption($key)) {
|
||
|
return $this->_profileOptions[(string) $key];
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all build profile options
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getProfileOptions()
|
||
|
{
|
||
|
return $this->_profileOptions;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove a build profile option
|
||
|
*
|
||
|
* @param string $name
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function removeProfileOption($name)
|
||
|
{
|
||
|
if ($this->hasProfileOption($name)) {
|
||
|
unset($this->_profileOptions[(string) $name]);
|
||
|
}
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove all build profile options
|
||
|
*
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function clearProfileOptions()
|
||
|
{
|
||
|
$this->_profileOptions = array();
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add a build profile dependency prefix
|
||
|
*
|
||
|
* If just the prefix is passed, sets path to "../$prefix".
|
||
|
*
|
||
|
* @param string $prefix
|
||
|
* @param null|string $path
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function addProfilePrefix($prefix, $path = null)
|
||
|
{
|
||
|
if (null === $path) {
|
||
|
$path = '../' . $prefix;
|
||
|
}
|
||
|
$this->_profilePrefixes[$prefix] = array($prefix, $path);
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set multiple dependency prefixes for bulid profile
|
||
|
*
|
||
|
* @param array $prefixes
|
||
|
* @return Zend_Dojo_BuildLayer
|
||
|
*/
|
||
|
public function setProfilePrefixes(array $prefixes)
|
||
|
{
|
||
|
foreach ($prefixes as $prefix => $path) {
|
||
|
$this->addProfilePrefix($prefix, $path);
|
||
|
}
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get build profile dependency prefixes
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getProfilePrefixes()
|
||
|
{
|
||
|
$layerName = $this->getLayerName();
|
||
|
if (null !== $layerName) {
|
||
|
$prefix = $this->_getPrefix($layerName);
|
||
|
if (!array_key_exists($prefix, $this->_profilePrefixes)) {
|
||
|
$this->addProfilePrefix($prefix);
|
||
|
}
|
||
|
}
|
||
|
$view = $this->getView();
|
||
|
if (!empty($view)) {
|
||
|
$helper = $this->getDojoHelper();
|
||
|
if ($helper) {
|
||
|
$modules = $helper->getModules();
|
||
|
foreach ($modules as $module) {
|
||
|
$prefix = $this->_getPrefix($module);
|
||
|
if (!array_key_exists($prefix, $this->_profilePrefixes)) {
|
||
|
$this->addProfilePrefix($prefix);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return $this->_profilePrefixes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate module layer script
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function generateLayerScript()
|
||
|
{
|
||
|
$helper = $this->getDojoHelper();
|
||
|
$layerName = $this->getLayerName();
|
||
|
$modulePaths = $helper->getModulePaths();
|
||
|
$modules = $helper->getModules();
|
||
|
$onLoadActions = $helper->getOnLoadActions();
|
||
|
$javascript = $helper->getJavascript();
|
||
|
|
||
|
$content = 'dojo.provide("' . $layerName . '");' . "\n\n(function(){\n";
|
||
|
|
||
|
foreach ($modulePaths as $module => $path) {
|
||
|
$content .= sprintf("dojo.registerModulePath(\"%s\", \"%s\");\n", $module, $path);
|
||
|
}
|
||
|
foreach ($modules as $module) {
|
||
|
$content .= sprintf("dojo.require(\"%s\");\n", $module);
|
||
|
}
|
||
|
|
||
|
if ($this->consumeOnLoad()) {
|
||
|
foreach ($helper->getOnLoadActions() as $callback) {
|
||
|
$content .= sprintf("dojo.addOnLoad(%s);\n", $callback);
|
||
|
}
|
||
|
}
|
||
|
if ($this->consumeJavascript()) {
|
||
|
$javascript = implode("\n", $helper->getJavascript());
|
||
|
if (!empty($javascript)) {
|
||
|
$content .= "\n" . $javascript . "\n";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$content .= "})();";
|
||
|
|
||
|
return $content;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate build profile
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function generateBuildProfile()
|
||
|
{
|
||
|
$profileOptions = $this->getProfileOptions();
|
||
|
$layerName = $this->getLayerName();
|
||
|
$layerScriptPath = $this->getLayerScriptPath();
|
||
|
$profilePrefixes = $this->getProfilePrefixes();
|
||
|
|
||
|
if (!array_key_exists('releaseName', $profileOptions)) {
|
||
|
$profileOptions['releaseName'] = substr($layerName, 0, strpos($layerName, '.'));
|
||
|
}
|
||
|
|
||
|
$profile = $profileOptions;
|
||
|
$profile['layers'] = array(array(
|
||
|
'name' => $layerScriptPath,
|
||
|
'layerDependencies' => array(),
|
||
|
'dependencies' => array($layerName),
|
||
|
));
|
||
|
$profile['prefixes'] = array_values($profilePrefixes);
|
||
|
|
||
|
return 'dependencies = ' . $this->_filterJsonProfileToJavascript($profile) . ';';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve module prefix
|
||
|
*
|
||
|
* @param string $module
|
||
|
* @return void
|
||
|
*/
|
||
|
protected function _getPrefix($module)
|
||
|
{
|
||
|
$segments = explode('.', $module, 2);
|
||
|
return $segments[0];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Filter a JSON build profile to JavaScript
|
||
|
*
|
||
|
* @param string $profile
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function _filterJsonProfileToJavascript($profile)
|
||
|
{
|
||
|
require_once 'Zend/Json.php';
|
||
|
$profile = Zend_Json::encode($profile);
|
||
|
$profile = preg_replace('/"([^"]*)":/', '$1:', $profile);
|
||
|
$profile = preg_replace('/' . preg_quote('\\') . '/', '', $profile);
|
||
|
return $profile;
|
||
|
}
|
||
|
}
|