web/enmi/Zend/Dojo/BuildLayer.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/enmi/Zend/Dojo/BuildLayer.php	Thu Jan 20 19:30:54 2011 +0100
@@ -0,0 +1,536 @@
+<?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-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: BuildLayer.php 22280 2010-05-24 20:39:45Z matthew $
+ */
+
+/**
+ * Dojo module layer and custom build profile generation support
+ *
+ * @package    Zend_Dojo
+ * @copyright  Copyright (c) 2005-2010 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 = trim($profile, '"');
+        $profile = preg_replace('/' . preg_quote('\\') . '/', '', $profile);
+        return $profile;
+    }
+}