7
* This source file is subject to the new BSD license that is bundled
8
* with this package in the file LICENSE.txt.
9
* It is also available through the world-wide-web at this URL:
10
* http://framework.zend.com/license/new-bsd
11
* If you did not receive a copy of the license and are unable to
12
* obtain it through the world-wide-web, please send an email
13
* to license@zend.com so we can send you a copy immediately.
18
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
* @version $Id: Container.php 11991 2008-10-16 15:12:15Z matthew $
20
* @license http://framework.zend.com/license/new-bsd New BSD License
24
require_once 'Zend/Dojo.php';
27
* Container for Dojo View Helper
32
* @copyright Copyright (C) 2008 - Present, Zend Technologies, Inc.
33
* @license New BSD {@link http://framework.zend.com/license/new-bsd}
35
class Zend_Dojo_View_Helper_Dojo_Container
38
* @var Zend_View_Interface
43
* addOnLoad capture lock
46
protected $_captureLock = false;
49
* addOnLoad object on which to apply lambda
52
protected $_captureObj;
55
* Base CDN url to utilize
58
protected $_cdnBase = Zend_Dojo::CDN_BASE_GOOGLE;
61
* Path segment following version string of CDN path
64
protected $_cdnDojoPath = Zend_Dojo::CDN_DOJO_PATH_GOOGLE;
67
* Dojo version to use from CDN
70
protected $_cdnVersion = '1.2.0';
73
* Has the dijit loader been registered?
76
protected $_dijitLoaderRegistered = false;
79
* Registered programmatic dijits
82
protected $_dijits = array();
88
protected $_djConfig = array();
91
* Whether or not dojo is enabled
94
protected $_enabled = false;
97
* Are we rendering as XHTML?
100
protected $_isXhtml = false;
103
* Arbitrary javascript to include in dojo script
106
protected $_javascriptStatements = array();
109
* Dojo layers (custom builds) to use
112
protected $_layers = array();
115
* Relative path to dojo
118
protected $_localPath = null;
121
* Root of dojo where all dojo files are installed
124
protected $_localRelativePath = null;
130
protected $_modules = array();
133
* Registered module paths
136
protected $_modulePaths = array();
139
* Actions to perform on window load
142
protected $_onLoadActions = array();
145
* Register the Dojo stylesheet?
148
protected $_registerDojoStylesheet = false;
151
* Style sheet modules to load
154
protected $_stylesheetModules = array();
160
protected $_stylesheets = array();
165
* @param Zend_Dojo_View_Interface $view
168
public function setView(Zend_View_Interface $view)
176
* @return Zend_Dojo_View_Helper_Dojo_Container
178
public function enable()
180
$this->_enabled = true;
187
* @return Zend_Dojo_View_Helper_Dojo_Container
189
public function disable()
191
$this->_enabled = false;
200
public function isEnabled()
202
return $this->_enabled;
206
* Specify a module to require
208
* @param string $module
209
* @return Zend_Dojo_View_Helper_Dojo_Container
211
public function requireModule($module)
213
if (!is_string($module) && !is_array($module)) {
214
require_once 'Zend/Dojo/View/Exception.php';
215
throw new Zend_Dojo_View_Exception('Invalid module name specified; must be a string or an array of strings');
218
$module = (array) $module;
220
foreach ($module as $mod) {
221
if (!preg_match('/^[a-z][a-z0-9._-]+$/i', $mod)) {
222
require_once 'Zend/Dojo/View/Exception.php';
223
throw new Zend_Dojo_View_Exception(sprintf('Module name specified, "%s", contains invalid characters', (string) $mod));
226
if (!in_array($mod, $this->_modules)) {
227
$this->_modules[] = $mod;
235
* Retrieve list of modules to require
239
public function getModules()
241
return $this->_modules;
245
* Register a module path
247
* @param string $path
248
* @return Zend_Dojo_View_Helper_Dojo_Container
250
public function registerModulePath($module, $path)
252
$path = (string) $path;
253
if (!in_array($module, $this->_modulePaths)) {
254
$this->_modulePaths[$module] = $path;
261
* List registered module paths
265
public function getModulePaths()
267
return $this->_modulePaths;
271
* Add layer (custom build) path
273
* @param string $path
274
* @return Zend_Dojo_View_Helper_Dojo_Container
276
public function addLayer($path)
278
$path = (string) $path;
279
if (!in_array($path, $this->_layers)) {
280
$this->_layers[] = $path;
286
* Get registered layers
290
public function getLayers()
292
return $this->_layers;
296
* Remove a registered layer
298
* @param string $path
299
* @return Zend_Dojo_View_Helper_Dojo_Container
301
public function removeLayer($path)
303
$path = (string) $path;
304
$layers = array_flip($this->_layers);
305
if (array_key_exists($path, $layers)) {
306
unset($layers[$path]);
307
$this->_layers = array_keys($layers);
313
* Clear all registered layers
315
* @return Zend_Dojo_View_Helper_Dojo_Container
317
public function clearLayers()
319
$this->_layers = array();
327
* @return Zend_Dojo_View_Helper_Dojo_Container
329
public function setCdnBase($url)
331
$this->_cdnBase = (string) $url;
336
* Return CDN base URL
340
public function getCdnBase()
342
return $this->_cdnBase;
346
* Use CDN, using version specified
348
* @param string $version
349
* @return Zend_Dojo_View_Helper_Dojo_Container
351
public function setCdnVersion($version = null)
354
if (preg_match('/^[1-9]\.[0-9](\.[0-9])?$/', $version)) {
355
$this->_cdnVersion = $version;
365
public function getCdnVersion()
367
return $this->_cdnVersion;
371
* Set CDN path to dojo (relative to CDN base + version)
373
* @param string $path
374
* @return Zend_Dojo_View_Helper_Dojo_Container
376
public function setCdnDojoPath($path)
378
$this->_cdnDojoPath = (string) $path;
383
* Get CDN path to dojo (relative to CDN base + version)
387
public function getCdnDojoPath()
389
return $this->_cdnDojoPath;
393
* Are we using the CDN?
397
public function useCdn()
399
return !$this->useLocalPath();
403
* Set path to local dojo
405
* @param string $path
406
* @return Zend_Dojo_View_Helper_Dojo_Container
408
public function setLocalPath($path)
411
$this->_localPath = (string) $path;
416
* Get local path to dojo
420
public function getLocalPath()
422
return $this->_localPath;
426
* Are we using a local path?
430
public function useLocalPath()
432
return (null === $this->_localPath) ? false : true;
436
* Set Dojo configuration
438
* @param string $option
439
* @param mixed $value
440
* @return Zend_Dojo_View_Helper_Dojo_Container
442
public function setDjConfig(array $config)
444
$this->_djConfig = $config;
449
* Set Dojo configuration option
451
* @param string $option
452
* @param mixed $value
453
* @return Zend_Dojo_View_Helper_Dojo_Container
455
public function setDjConfigOption($option, $value)
457
$option = (string) $option;
458
$this->_djConfig[$option] = $value;
463
* Retrieve dojo configuration values
467
public function getDjConfig()
469
return $this->_djConfig;
473
* Get dojo configuration value
475
* @param string $option
476
* @param mixed $default
479
public function getDjConfigOption($option, $default = null)
481
$option = (string) $option;
482
if (array_key_exists($option, $this->_djConfig)) {
483
return $this->_djConfig[$option];
489
* Add a stylesheet by module name
491
* @param string $module
492
* @return Zend_Dojo_View_Helper_Dojo_Container
494
public function addStylesheetModule($module)
496
if (!preg_match('/^[a-z0-9]+\.[a-z0-9_-]+(\.[a-z0-9_-]+)*$/i', $module)) {
497
require_once 'Zend/Dojo/View/Exception.php';
498
throw new Zend_Dojo_View_Exception('Invalid stylesheet module specified');
500
if (in_array($module, $this->_stylesheetModules)) {
503
$this->_stylesheetModules[] = $module;
508
* Get all stylesheet modules currently registered
512
public function getStylesheetModules()
514
return $this->_stylesheetModules;
520
* @param string $path
521
* @return Zend_Dojo_View_Helper_Dojo_Container
523
public function addStylesheet($path)
525
$path = (string) $path;
526
if (!in_array($path, $this->_stylesheets)) {
527
$this->_stylesheets[] = (string) $path;
533
* Register the dojo.css stylesheet?
535
* With no arguments, returns the status of the flag; with arguments, sets
536
* the flag and returns the object.
538
* @param null|bool $flag
539
* @return Zend_Dojo_View_Helper_Dojo_Container|bool
541
public function registerDojoStylesheet($flag = null)
543
if (null === $flag) {
544
return $this->_registerDojoStylesheet;
547
$this->_registerDojoStylesheet = (bool) $flag;
552
* Retrieve registered stylesheets
556
public function getStylesheets()
558
return $this->_stylesheets;
562
* Add a script to execute onLoad
564
* dojo.addOnLoad accepts:
568
* @param string $callback Lambda
569
* @return Zend_Dojo_View_Helper_Dojo_Container
571
public function addOnLoad($callback)
573
if (!in_array($callback, $this->_onLoadActions, true)) {
574
$this->_onLoadActions[] = $callback;
580
* Retrieve all registered onLoad actions
584
public function getOnLoadActions()
586
return $this->_onLoadActions;
590
* Start capturing routines to run onLoad
594
public function onLoadCaptureStart()
596
if ($this->_captureLock) {
597
require_once 'Zend/Dojo/View/Exception.php';
598
throw new Zend_Dojo_View_Exception('Cannot nest onLoad captures');
601
$this->_captureLock = true;
607
* Stop capturing routines to run onLoad
611
public function onLoadCaptureEnd()
613
$data = ob_get_clean();
614
$this->_captureLock = false;
616
$this->addOnLoad($data);
621
* Add a programmatic dijit
624
* @param array $params
625
* @return Zend_Dojo_View_Helper_Dojo_Container
627
public function addDijit($id, array $params)
629
if (array_key_exists($id, $this->_dijits)) {
630
require_once 'Zend/Dojo/View/Exception.php';
631
throw new Zend_Dojo_View_Exception(sprintf('Duplicate dijit with id "%s" already registered', $id));
634
$this->_dijits[$id] = array(
643
* Set a programmatic dijit (overwrites)
646
* @param array $params
647
* @return Zend_Dojo_View_Helper_Dojo_Container
649
public function setDijit($id, array $params)
651
$this->removeDijit($id);
652
return $this->addDijit($id, $params);
656
* Add multiple dijits at once
658
* Expects an array of id => array $params pairs
660
* @param array $dijits
661
* @return Zend_Dojo_View_Helper_Dojo_Container
663
public function addDijits(array $dijits)
665
foreach ($dijits as $id => $params) {
666
$this->addDijit($id, $params);
672
* Set multiple dijits at once (overwrites)
674
* Expects an array of id => array $params pairs
676
* @param array $dijits
677
* @return Zend_Dojo_View_Helper_Dojo_Container
679
public function setDijits(array $dijits)
681
$this->clearDijits();
682
return $this->addDijits($dijits);
686
* Is the given programmatic dijit already registered?
691
public function hasDijit($id)
693
return array_key_exists($id, $this->_dijits);
697
* Retrieve a dijit by id
702
public function getDijit($id)
704
if ($this->hasDijit($id)) {
705
return $this->_dijits[$id]['params'];
711
* Retrieve all dijits
713
* Returns dijits as an array of assoc arrays
717
public function getDijits()
719
return array_values($this->_dijits);
723
* Remove a programmatic dijit if it exists
726
* @return Zend_Dojo_View_Helper_Dojo_Container
728
public function removeDijit($id)
730
if (array_key_exists($id, $this->_dijits)) {
731
unset($this->_dijits[$id]);
740
* @return Zend_Dojo_View_Helper_Dojo_Container
742
public function clearDijits()
744
$this->_dijits = array();
749
* Render dijits as JSON structure
753
public function dijitsToJson()
755
require_once 'Zend/Json.php';
756
return Zend_Json::encode($this->getDijits());
760
* Create dijit loader functionality
764
public function registerDijitLoader()
766
if (!$this->_dijitLoaderRegistered) {
769
dojo.forEach(zendDijits, function(info) {
770
var n = dojo.byId(info.id);
772
dojo.attr(n, dojo.mixin({ id: info.id }, info.params));
778
$this->requireModule('dojo.parser');
779
$this->addOnLoad($js);
780
$this->addJavascript('var zendDijits = ' . $this->dijitsToJson() . ';');
781
$this->_dijitLoaderRegistered = true;
786
* Add arbitrary javascript to execute in dojo JS container
789
* @return Zend_Dojo_View_Helper_Dojo_Container
791
public function addJavascript($js)
793
$js = preg_replace('/^\s*(.*?)\s*$/s', '$1', $js);
794
if (!in_array(substr($js, -1), array(';', '}'))) {
798
if (in_array($js, $this->_javascriptStatements)) {
802
$this->_javascriptStatements[] = $js;
807
* Return all registered javascript statements
811
public function getJavascript()
813
return $this->_javascriptStatements;
817
* Clear arbitrary javascript stack
819
* @return Zend_Dojo_View_Helper_Dojo_Container
821
public function clearJavascript()
823
$this->_javascriptStatements = array();
828
* Capture arbitrary javascript to include in dojo script
832
public function javascriptCaptureStart()
834
if ($this->_captureLock) {
835
require_once 'Zend/Dojo/View/Exception.php';
836
throw new Zend_Dojo_View_Exception('Cannot nest captures');
839
$this->_captureLock = true;
845
* Finish capturing arbitrary javascript to include in dojo script
849
public function javascriptCaptureEnd()
851
$data = ob_get_clean();
852
$this->_captureLock = false;
854
$this->addJavascript($data);
859
* String representation of dojo environment
863
public function __toString()
865
if (!$this->isEnabled()) {
869
$this->_isXhtml = $this->view->doctype()->isXhtml();
871
if (Zend_Dojo_View_Helper_Dojo::useDeclarative()) {
872
if (null === $this->getDjConfigOption('parseOnLoad')) {
873
$this->setDjConfigOption('parseOnLoad', true);
877
if (!empty($this->_dijits)) {
878
$this->registerDijitLoader();
881
$html = $this->_renderStylesheets() . PHP_EOL
882
. $this->_renderDjConfig() . PHP_EOL
883
. $this->_renderDojoScriptTag() . PHP_EOL
884
. $this->_renderLayers() . PHP_EOL
885
. $this->_renderExtras();
890
* Retrieve local path to dojo resources for building relative paths
894
protected function _getLocalRelativePath()
896
if (null === $this->_localRelativePath) {
897
$localPath = $this->getLocalPath();
898
$localPath = preg_replace('|[/\\\\]dojo[/\\\\]dojo.js[^/\\\\]*$|i', '', $localPath);
899
$this->_localRelativePath = $localPath;
901
return $this->_localRelativePath;
905
* Render dojo stylesheets
909
protected function _renderStylesheets()
911
if ($this->useCdn()) {
912
$base = $this->getCdnBase()
913
. $this->getCdnVersion();
915
$base = $this->_getLocalRelativePath();
918
$registeredStylesheets = $this->getStylesheetModules();
919
foreach ($registeredStylesheets as $stylesheet) {
920
$themeName = substr($stylesheet, strrpos($stylesheet, '.') + 1);
921
$stylesheet = str_replace('.', '/', $stylesheet);
922
$stylesheets[] = $base . '/' . $stylesheet . '/' . $themeName . '.css';
925
foreach ($this->getStylesheets() as $stylesheet) {
926
$stylesheets[] = $stylesheet;
929
if ($this->_registerDojoStylesheet) {
930
$stylesheets[] = $base . '/dojo/resources/dojo.css';
933
if (empty($stylesheets)) {
937
array_reverse($stylesheets);
938
$style = '<style type="text/css">' . PHP_EOL
939
. (($this->_isXhtml) ? '<!--' : '<!--') . PHP_EOL;
940
foreach ($stylesheets as $stylesheet) {
941
$style .= ' @import "' . $stylesheet . '";' . PHP_EOL;
943
$style .= (($this->_isXhtml) ? '-->' : '-->') . PHP_EOL
950
* Render DjConfig values
954
protected function _renderDjConfig()
956
$djConfigValues = $this->getDjConfig();
957
if (empty($djConfigValues)) {
961
require_once 'Zend/Json.php';
962
$scriptTag = '<script type="text/javascript">' . PHP_EOL
963
. (($this->_isXhtml) ? '//<![CDATA[' : '//<!--') . PHP_EOL
964
. ' var djConfig = ' . Zend_Json::encode($djConfigValues) . ';' . PHP_EOL
965
. (($this->_isXhtml) ? '//]]>' : '//-->') . PHP_EOL
972
* Render dojo script tag
974
* Renders Dojo script tag by utilizing either local path provided or the
975
* CDN. If any djConfig values were set, they will be serialized and passed
976
* with that attribute.
980
protected function _renderDojoScriptTag()
982
if ($this->useCdn()) {
983
$source = $this->getCdnBase()
984
. $this->getCdnVersion()
985
. $this->getCdnDojoPath();
987
$source = $this->getLocalPath();
990
$scriptTag = '<script type="text/javascript" src="' . $source . '"></script>';
995
* Render layers (custom builds) as script tags
999
protected function _renderLayers()
1001
$layers = $this->getLayers();
1002
if (empty($layers)) {
1007
foreach ($layers as $path) {
1009
'<script type="text/javascript" src="%s"></script>',
1010
htmlentities($path, ENT_QUOTES)
1014
return implode("\n", $html);
1018
* Render dojo module paths and requires
1022
protected function _renderExtras()
1025
$modulePaths = $this->getModulePaths();
1026
if (!empty($modulePaths)) {
1027
foreach ($modulePaths as $module => $path) {
1028
$js[] = 'dojo.registerModulePath("' . $this->view->escape($module) . '", "' . $this->view->escape($path) . '");';
1032
$modules = $this->getModules();
1033
if (!empty($modules)) {
1034
foreach ($modules as $module) {
1035
$js[] = 'dojo.require("' . $this->view->escape($module) . '");';
1039
$onLoadActions = array();
1040
foreach ($this->getOnLoadActions() as $callback) {
1041
$onLoadActions[] = 'dojo.addOnLoad(' . $callback . ');';
1044
$javascript = implode("\n ", $this->getJavascript());
1048
$content .= implode("\n ", $js) . "\n";
1051
if (!empty($onLoadActions)) {
1052
$content .= implode("\n ", $onLoadActions) . "\n";
1055
if (!empty($javascript)) {
1056
$content .= $javascript . "\n";
1059
if (preg_match('/^\s*$/s', $content)) {
1063
$html = '<script type="text/javascript">' . PHP_EOL
1064
. (($this->_isXhtml) ? '//<![CDATA[' : '//<!--') . PHP_EOL
1066
. (($this->_isXhtml) ? '//]]>' : '//-->') . PHP_EOL
1067
. PHP_EOL . '</script>';