00001 <?php 00024 require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php'; 00025 00035 class Zend_View_Helper_HeadScript extends Zend_View_Helper_Placeholder_Container_Standalone 00036 { 00041 const FILE = 'FILE'; 00042 const SCRIPT = 'SCRIPT'; 00049 protected $_regKey = 'Zend_View_Helper_HeadScript'; 00050 00055 protected $_arbitraryAttributes = false; 00056 00061 protected $_captureLock; 00062 protected $_captureScriptType = null; 00063 protected $_captureScriptAttrs = null; 00064 protected $_captureType; 00071 protected $_optionalAttributes = array( 00072 'charset', 'defer', 'language', 'src' 00073 ); 00074 00079 protected $_requiredAttributes = array('type'); 00080 00086 public $useCdata = false; 00087 00095 public function __construct() 00096 { 00097 parent::__construct(); 00098 $this->setSeparator(PHP_EOL); 00099 } 00100 00114 public function headScript($mode = Zend_View_Helper_HeadScript::FILE, $spec = null, $placement = 'APPEND', array $attrs = array(), $type = 'text/javascript') 00115 { 00116 if ((null !== $spec) && is_string($spec)) { 00117 $action = ucfirst(strtolower($mode)); 00118 $placement = strtolower($placement); 00119 switch ($placement) { 00120 case 'set': 00121 case 'prepend': 00122 case 'append': 00123 $action = $placement . $action; 00124 break; 00125 default: 00126 $action = 'append' . $action; 00127 break; 00128 } 00129 $this->$action($spec, $type, $attrs); 00130 } 00131 00132 return $this; 00133 } 00134 00142 public function captureStart($captureType = Zend_View_Helper_Placeholder_Container_Abstract::APPEND, $type = 'text/javascript', $attrs = array()) 00143 { 00144 if ($this->_captureLock) { 00145 require_once 'Zend/View/Helper/Placeholder/Container/Exception.php'; 00146 throw new Zend_View_Helper_Placeholder_Container_Exception('Cannot nest headScript captures'); 00147 } 00148 00149 $this->_captureLock = true; 00150 $this->_captureType = $captureType; 00151 $this->_captureScriptType = $type; 00152 $this->_captureScriptAttrs = $attrs; 00153 ob_start(); 00154 } 00155 00161 public function captureEnd() 00162 { 00163 $content = ob_get_clean(); 00164 $type = $this->_captureScriptType; 00165 $attrs = $this->_captureScriptAttrs; 00166 $this->_captureScriptType = null; 00167 $this->_captureScriptAttrs = null; 00168 $this->_captureLock = false; 00169 00170 switch ($this->_captureType) { 00171 case Zend_View_Helper_Placeholder_Container_Abstract::SET: 00172 case Zend_View_Helper_Placeholder_Container_Abstract::PREPEND: 00173 case Zend_View_Helper_Placeholder_Container_Abstract::APPEND: 00174 $action = strtolower($this->_captureType) . 'Script'; 00175 break; 00176 default: 00177 $action = 'appendScript'; 00178 break; 00179 } 00180 $this->$action($content, $type, $attrs); 00181 } 00182 00201 public function __call($method, $args) 00202 { 00203 if (preg_match('/^(?P<action>set|(ap|pre)pend|offsetSet)(?P<mode>File|Script)$/', $method, $matches)) { 00204 if (1 > count($args)) { 00205 require_once 'Zend/View/Exception.php'; 00206 throw new Zend_View_Exception(sprintf('Method "%s" requires at least one argument', $method)); 00207 } 00208 00209 $action = $matches['action']; 00210 $mode = strtolower($matches['mode']); 00211 $type = 'text/javascript'; 00212 $attrs = array(); 00213 00214 if ('offsetSet' == $action) { 00215 $index = array_shift($args); 00216 if (1 > count($args)) { 00217 require_once 'Zend/View/Exception.php'; 00218 throw new Zend_View_Exception(sprintf('Method "%s" requires at least two arguments, an index and source', $method)); 00219 } 00220 } 00221 00222 $content = $args[0]; 00223 00224 if (isset($args[1])) { 00225 $type = (string) $args[1]; 00226 } 00227 if (isset($args[2])) { 00228 $attrs = (array) $args[2]; 00229 } 00230 00231 switch ($mode) { 00232 case 'script': 00233 $item = $this->createData($type, $attrs, $content); 00234 if ('offsetSet' == $action) { 00235 $this->offsetSet($index, $item); 00236 } else { 00237 $this->$action($item); 00238 } 00239 break; 00240 case 'file': 00241 default: 00242 if (!$this->_isDuplicate($content)) { 00243 $attrs['src'] = $content; 00244 $item = $this->createData($type, $attrs); 00245 if ('offsetSet' == $action) { 00246 $this->offsetSet($index, $item); 00247 } else { 00248 $this->$action($item); 00249 } 00250 } 00251 break; 00252 } 00253 00254 return $this; 00255 } 00256 00257 return parent::__call($method, $args); 00258 } 00259 00266 protected function _isDuplicate($file) 00267 { 00268 foreach ($this->getContainer() as $item) { 00269 if (($item->source === null) 00270 && array_key_exists('src', $item->attributes) 00271 && ($file == $item->attributes['src'])) 00272 { 00273 return true; 00274 } 00275 } 00276 return false; 00277 } 00278 00286 protected function _isValid($value) 00287 { 00288 if ((!$value instanceof stdClass) 00289 || !isset($value->type) 00290 || (!isset($value->source) && !isset($value->attributes))) 00291 { 00292 return false; 00293 } 00294 00295 return true; 00296 } 00297 00304 public function append($value) 00305 { 00306 if (!$this->_isValid($value)) { 00307 require_once 'Zend/View/Exception.php'; 00308 throw new Zend_View_Exception('Invalid argument passed to append(); please use one of the helper methods, appendScript() or appendFile()'); 00309 } 00310 00311 return $this->getContainer()->append($value); 00312 } 00313 00320 public function prepend($value) 00321 { 00322 if (!$this->_isValid($value)) { 00323 require_once 'Zend/View/Exception.php'; 00324 throw new Zend_View_Exception('Invalid argument passed to prepend(); please use one of the helper methods, prependScript() or prependFile()'); 00325 } 00326 00327 return $this->getContainer()->prepend($value); 00328 } 00329 00336 public function set($value) 00337 { 00338 if (!$this->_isValid($value)) { 00339 require_once 'Zend/View/Exception.php'; 00340 throw new Zend_View_Exception('Invalid argument passed to set(); please use one of the helper methods, setScript() or setFile()'); 00341 } 00342 00343 return $this->getContainer()->set($value); 00344 } 00345 00353 public function offsetSet($index, $value) 00354 { 00355 if (!$this->_isValid($value)) { 00356 require_once 'Zend/View/Exception.php'; 00357 throw new Zend_View_Exception('Invalid argument passed to offsetSet(); please use one of the helper methods, offsetSetScript() or offsetSetFile()'); 00358 } 00359 00360 $this->_isValid($value); 00361 return $this->getContainer()->offsetSet($index, $value); 00362 } 00363 00370 public function setAllowArbitraryAttributes($flag) 00371 { 00372 $this->_arbitraryAttributes = (bool) $flag; 00373 return $this; 00374 } 00375 00381 public function arbitraryAttributesAllowed() 00382 { 00383 return $this->_arbitraryAttributes; 00384 } 00385 00395 public function itemToString($item, $indent, $escapeStart, $escapeEnd) 00396 { 00397 $attrString = ''; 00398 if (!empty($item->attributes)) { 00399 foreach ($item->attributes as $key => $value) { 00400 if (!$this->arbitraryAttributesAllowed() 00401 && !in_array($key, $this->_optionalAttributes)) 00402 { 00403 continue; 00404 } 00405 if ('defer' == $key) { 00406 $value = 'defer'; 00407 } 00408 $attrString .= sprintf(' %s="%s"', $key, ($this->_autoEscape) ? $this->_escape($value) : $value); 00409 } 00410 } 00411 00412 $type = ($this->_autoEscape) ? $this->_escape($item->type) : $item->type; 00413 $html = $indent . '<script type="' . $type . '"' . $attrString . '>'; 00414 if (!empty($item->source)) { 00415 $html .= PHP_EOL . $indent . ' ' . $escapeStart . PHP_EOL . $item->source . $indent . ' ' . $escapeEnd . PHP_EOL . $indent; 00416 } 00417 $html .= '</script>'; 00418 00419 if (isset($item->attributes['conditional']) 00420 && !empty($item->attributes['conditional']) 00421 && is_string($item->attributes['conditional'])) 00422 { 00423 $html = '<!--[if ' . $item->attributes['conditional'] . ']> ' . $html . '<![endif]-->'; 00424 } 00425 00426 return $html; 00427 } 00428 00435 public function toString($indent = null) 00436 { 00437 $indent = (null !== $indent) 00438 ? $this->getWhitespace($indent) 00439 : $this->getIndent(); 00440 00441 if ($this->view) { 00442 $useCdata = $this->view->doctype()->isXhtml() ? true : false; 00443 } else { 00444 $useCdata = $this->useCdata ? true : false; 00445 } 00446 $escapeStart = ($useCdata) ? '//<![CDATA[' : '//<!--'; 00447 $escapeEnd = ($useCdata) ? '//]]>' : '//-->'; 00448 00449 $items = array(); 00450 $this->getContainer()->ksort(); 00451 foreach ($this as $item) { 00452 if (!$this->_isValid($item)) { 00453 continue; 00454 } 00455 00456 $items[] = $this->itemToString($item, $indent, $escapeStart, $escapeEnd); 00457 } 00458 00459 $return = implode($this->getSeparator(), $items); 00460 return $return; 00461 } 00462 00471 public function createData($type, array $attributes, $content = null) 00472 { 00473 $data = new stdClass(); 00474 $data->type = $type; 00475 $data->attributes = $attributes; 00476 $data->source = $content; 00477 return $data; 00478 } 00479 }