PageRenderTime 25ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/Zend/View/Helper/HeadScript.php

https://github.com/grandison/budo16
PHP | 478 lines | 241 code | 46 blank | 191 comment | 44 complexity | dc8b6c8ef5da24bc9ad6e274af67dc40 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  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.
  14. *
  15. * @category Zend
  16. * @package Zend_View
  17. * @subpackage Helper
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @version $Id: HeadScript.php 16971 2009-07-22 18:05:45Z mikaelkael $
  20. * @license http://framework.zend.com/license/new-bsd New BSD License
  21. */
  22. /** Zend_View_Helper_Placeholder_Container_Standalone */
  23. // require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php';
  24. /**
  25. * Helper for setting and retrieving script elements for HTML head section
  26. *
  27. * @uses Zend_View_Helper_Placeholder_Container_Standalone
  28. * @package Zend_View
  29. * @subpackage Helper
  30. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  31. * @license http://framework.zend.com/license/new-bsd New BSD License
  32. */
  33. class Zend_View_Helper_HeadScript extends Zend_View_Helper_Placeholder_Container_Standalone
  34. {
  35. /**#@+
  36. * Script type contants
  37. * @const string
  38. */
  39. const FILE = 'FILE';
  40. const SCRIPT = 'SCRIPT';
  41. /**#@-*/
  42. /**
  43. * Registry key for placeholder
  44. * @var string
  45. */
  46. protected $_regKey = 'Zend_View_Helper_HeadScript';
  47. /**
  48. * Are arbitrary attributes allowed?
  49. * @var bool
  50. */
  51. protected $_arbitraryAttributes = false;
  52. /**#@+
  53. * Capture type and/or attributes (used for hinting during capture)
  54. * @var string
  55. */
  56. protected $_captureLock;
  57. protected $_captureScriptType = null;
  58. protected $_captureScriptAttrs = null;
  59. protected $_captureType;
  60. /**#@-*/
  61. /**
  62. * Optional allowed attributes for script tag
  63. * @var array
  64. */
  65. protected $_optionalAttributes = array(
  66. 'charset', 'defer', 'language', 'src'
  67. );
  68. /**
  69. * Required attributes for script tag
  70. * @var string
  71. */
  72. protected $_requiredAttributes = array('type');
  73. /**
  74. * Whether or not to format scripts using CDATA; used only if doctype
  75. * helper is not accessible
  76. * @var bool
  77. */
  78. public $useCdata = false;
  79. /**
  80. * Constructor
  81. *
  82. * Set separator to PHP_EOL.
  83. *
  84. * @return void
  85. */
  86. public function __construct()
  87. {
  88. parent::__construct();
  89. $this->setSeparator(PHP_EOL);
  90. }
  91. /**
  92. * Return headScript object
  93. *
  94. * Returns headScript helper object; optionally, allows specifying a script
  95. * or script file to include.
  96. *
  97. * @param string $mode Script or file
  98. * @param string $spec Script/url
  99. * @param string $placement Append, prepend, or set
  100. * @param array $attrs Array of script attributes
  101. * @param string $type Script type and/or array of script attributes
  102. * @return Zend_View_Helper_HeadScript
  103. */
  104. public function headScript($mode = Zend_View_Helper_HeadScript::FILE, $spec = null, $placement = 'APPEND', array $attrs = array(), $type = 'text/javascript')
  105. {
  106. if ((null !== $spec) && is_string($spec)) {
  107. $action = ucfirst(strtolower($mode));
  108. $placement = strtolower($placement);
  109. switch ($placement) {
  110. case 'set':
  111. case 'prepend':
  112. case 'append':
  113. $action = $placement . $action;
  114. break;
  115. default:
  116. $action = 'append' . $action;
  117. break;
  118. }
  119. $this->$action($spec, $type, $attrs);
  120. }
  121. return $this;
  122. }
  123. /**
  124. * Start capture action
  125. *
  126. * @param mixed $captureType
  127. * @param string $typeOrAttrs
  128. * @return void
  129. */
  130. public function captureStart($captureType = Zend_View_Helper_Placeholder_Container_Abstract::APPEND, $type = 'text/javascript', $attrs = array())
  131. {
  132. if ($this->_captureLock) {
  133. // require_once 'Zend/View/Helper/Placeholder/Container/Exception.php';
  134. throw new Zend_View_Helper_Placeholder_Container_Exception('Cannot nest headScript captures');
  135. }
  136. $this->_captureLock = true;
  137. $this->_captureType = $captureType;
  138. $this->_captureScriptType = $type;
  139. $this->_captureScriptAttrs = $attrs;
  140. ob_start();
  141. }
  142. /**
  143. * End capture action and store
  144. *
  145. * @return void
  146. */
  147. public function captureEnd()
  148. {
  149. $content = ob_get_clean();
  150. $type = $this->_captureScriptType;
  151. $attrs = $this->_captureScriptAttrs;
  152. $this->_captureScriptType = null;
  153. $this->_captureScriptAttrs = null;
  154. $this->_captureLock = false;
  155. switch ($this->_captureType) {
  156. case Zend_View_Helper_Placeholder_Container_Abstract::SET:
  157. case Zend_View_Helper_Placeholder_Container_Abstract::PREPEND:
  158. case Zend_View_Helper_Placeholder_Container_Abstract::APPEND:
  159. $action = strtolower($this->_captureType) . 'Script';
  160. break;
  161. default:
  162. $action = 'appendScript';
  163. break;
  164. }
  165. $this->$action($content, $type, $attrs);
  166. }
  167. /**
  168. * Overload method access
  169. *
  170. * Allows the following method calls:
  171. * - appendFile($src, $type = 'text/javascript', $attrs = array())
  172. * - offsetSetFile($index, $src, $type = 'text/javascript', $attrs = array())
  173. * - prependFile($src, $type = 'text/javascript', $attrs = array())
  174. * - setFile($src, $type = 'text/javascript', $attrs = array())
  175. * - appendScript($script, $type = 'text/javascript', $attrs = array())
  176. * - offsetSetScript($index, $src, $type = 'text/javascript', $attrs = array())
  177. * - prependScript($script, $type = 'text/javascript', $attrs = array())
  178. * - setScript($script, $type = 'text/javascript', $attrs = array())
  179. *
  180. * @param string $method
  181. * @param array $args
  182. * @return Zend_View_Helper_HeadScript
  183. * @throws Zend_View_Exception if too few arguments or invalid method
  184. */
  185. public function __call($method, $args)
  186. {
  187. if (preg_match('/^(?P<action>set|(ap|pre)pend|offsetSet)(?P<mode>File|Script)$/', $method, $matches)) {
  188. if (1 > count($args)) {
  189. // require_once 'Zend/View/Exception.php';
  190. throw new Zend_View_Exception(sprintf('Method "%s" requires at least one argument', $method));
  191. }
  192. $action = $matches['action'];
  193. $mode = strtolower($matches['mode']);
  194. $type = 'text/javascript';
  195. $attrs = array();
  196. if ('offsetSet' == $action) {
  197. $index = array_shift($args);
  198. if (1 > count($args)) {
  199. // require_once 'Zend/View/Exception.php';
  200. throw new Zend_View_Exception(sprintf('Method "%s" requires at least two arguments, an index and source', $method));
  201. }
  202. }
  203. $content = $args[0];
  204. if (isset($args[1])) {
  205. $type = (string) $args[1];
  206. }
  207. if (isset($args[2])) {
  208. $attrs = (array) $args[2];
  209. }
  210. switch ($mode) {
  211. case 'script':
  212. $item = $this->createData($type, $attrs, $content);
  213. if ('offsetSet' == $action) {
  214. $this->offsetSet($index, $item);
  215. } else {
  216. $this->$action($item);
  217. }
  218. break;
  219. case 'file':
  220. default:
  221. if (!$this->_isDuplicate($content)) {
  222. $attrs['src'] = $content;
  223. $item = $this->createData($type, $attrs);
  224. if ('offsetSet' == $action) {
  225. $this->offsetSet($index, $item);
  226. } else {
  227. $this->$action($item);
  228. }
  229. }
  230. break;
  231. }
  232. return $this;
  233. }
  234. return parent::__call($method, $args);
  235. }
  236. /**
  237. * Is the file specified a duplicate?
  238. *
  239. * @param string $file
  240. * @return bool
  241. */
  242. protected function _isDuplicate($file)
  243. {
  244. foreach ($this->getContainer() as $item) {
  245. if (($item->source === null)
  246. && array_key_exists('src', $item->attributes)
  247. && ($file == $item->attributes['src']))
  248. {
  249. return true;
  250. }
  251. }
  252. return false;
  253. }
  254. /**
  255. * Is the script provided valid?
  256. *
  257. * @param mixed $value
  258. * @param string $method
  259. * @return bool
  260. */
  261. protected function _isValid($value)
  262. {
  263. if ((!$value instanceof stdClass)
  264. || !isset($value->type)
  265. || (!isset($value->source) && !isset($value->attributes)))
  266. {
  267. return false;
  268. }
  269. return true;
  270. }
  271. /**
  272. * Override append
  273. *
  274. * @param string $value
  275. * @return void
  276. */
  277. public function append($value)
  278. {
  279. if (!$this->_isValid($value)) {
  280. // require_once 'Zend/View/Exception.php';
  281. throw new Zend_View_Exception('Invalid argument passed to append(); please use one of the helper methods, appendScript() or appendFile()');
  282. }
  283. return $this->getContainer()->append($value);
  284. }
  285. /**
  286. * Override prepend
  287. *
  288. * @param string $value
  289. * @return void
  290. */
  291. public function prepend($value)
  292. {
  293. if (!$this->_isValid($value)) {
  294. // require_once 'Zend/View/Exception.php';
  295. throw new Zend_View_Exception('Invalid argument passed to prepend(); please use one of the helper methods, prependScript() or prependFile()');
  296. }
  297. return $this->getContainer()->prepend($value);
  298. }
  299. /**
  300. * Override set
  301. *
  302. * @param string $value
  303. * @return void
  304. */
  305. public function set($value)
  306. {
  307. if (!$this->_isValid($value)) {
  308. // require_once 'Zend/View/Exception.php';
  309. throw new Zend_View_Exception('Invalid argument passed to set(); please use one of the helper methods, setScript() or setFile()');
  310. }
  311. return $this->getContainer()->set($value);
  312. }
  313. /**
  314. * Override offsetSet
  315. *
  316. * @param string|int $index
  317. * @param mixed $value
  318. * @return void
  319. */
  320. public function offsetSet($index, $value)
  321. {
  322. if (!$this->_isValid($value)) {
  323. // require_once 'Zend/View/Exception.php';
  324. throw new Zend_View_Exception('Invalid argument passed to offsetSet(); please use one of the helper methods, offsetSetScript() or offsetSetFile()');
  325. }
  326. return $this->getContainer()->offsetSet($index, $value);
  327. }
  328. /**
  329. * Set flag indicating if arbitrary attributes are allowed
  330. *
  331. * @param bool $flag
  332. * @return Zend_View_Helper_HeadScript
  333. */
  334. public function setAllowArbitraryAttributes($flag)
  335. {
  336. $this->_arbitraryAttributes = (bool) $flag;
  337. return $this;
  338. }
  339. /**
  340. * Are arbitrary attributes allowed?
  341. *
  342. * @return bool
  343. */
  344. public function arbitraryAttributesAllowed()
  345. {
  346. return $this->_arbitraryAttributes;
  347. }
  348. /**
  349. * Create script HTML
  350. *
  351. * @param string $type
  352. * @param array $attributes
  353. * @param string $content
  354. * @param string|int $indent
  355. * @return string
  356. */
  357. public function itemToString($item, $indent, $escapeStart, $escapeEnd)
  358. {
  359. $attrString = '';
  360. if (!empty($item->attributes)) {
  361. foreach ($item->attributes as $key => $value) {
  362. if (!$this->arbitraryAttributesAllowed()
  363. && !in_array($key, $this->_optionalAttributes))
  364. {
  365. continue;
  366. }
  367. if ('defer' == $key) {
  368. $value = 'defer';
  369. }
  370. $attrString .= sprintf(' %s="%s"', $key, ($this->_autoEscape) ? $this->_escape($value) : $value);
  371. }
  372. }
  373. $type = ($this->_autoEscape) ? $this->_escape($item->type) : $item->type;
  374. $html = $indent . '<script type="' . $type . '"' . $attrString . '>';
  375. if (!empty($item->source)) {
  376. $html .= PHP_EOL . $indent . ' ' . $escapeStart . PHP_EOL . $item->source . $indent . ' ' . $escapeEnd . PHP_EOL . $indent;
  377. }
  378. $html .= '</script>';
  379. if (isset($item->attributes['conditional'])
  380. && !empty($item->attributes['conditional'])
  381. && is_string($item->attributes['conditional']))
  382. {
  383. $html = '<!--[if ' . $item->attributes['conditional'] . ']> ' . $html . '<![endif]-->';
  384. }
  385. return $html;
  386. }
  387. /**
  388. * Retrieve string representation
  389. *
  390. * @param string|int $indent
  391. * @return string
  392. */
  393. public function toString($indent = null)
  394. {
  395. $indent = (null !== $indent)
  396. ? $this->getWhitespace($indent)
  397. : $this->getIndent();
  398. if ($this->view) {
  399. $useCdata = $this->view->doctype()->isXhtml() ? true : false;
  400. } else {
  401. $useCdata = $this->useCdata ? true : false;
  402. }
  403. $escapeStart = ($useCdata) ? '//<![CDATA[' : '//<!--';
  404. $escapeEnd = ($useCdata) ? '//]]>' : '//-->';
  405. $items = array();
  406. $this->getContainer()->ksort();
  407. foreach ($this as $item) {
  408. if (!$this->_isValid($item)) {
  409. continue;
  410. }
  411. $items[] = $this->itemToString($item, $indent, $escapeStart, $escapeEnd);
  412. }
  413. $return = implode($this->getSeparator(), $items);
  414. return $return;
  415. }
  416. /**
  417. * Create data item containing all necessary components of script
  418. *
  419. * @param string $type
  420. * @param array $attributes
  421. * @param string $content
  422. * @return stdClass
  423. */
  424. public function createData($type, array $attributes, $content = null)
  425. {
  426. $data = new stdClass();
  427. $data->type = $type;
  428. $data->attributes = $attributes;
  429. $data->source = $content;
  430. return $data;
  431. }
  432. }