File indexing completed on 2024-12-22 05:37:13
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_View 0017 * @subpackage Helper 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @version $Id$ 0020 * @license http://framework.zend.com/license/new-bsd New BSD License 0021 */ 0022 0023 /** Zend_View_Helper_Placeholder_Container_Standalone */ 0024 // require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php'; 0025 0026 /** 0027 * Zend_Layout_View_Helper_HeadLink 0028 * 0029 * @see http://www.w3.org/TR/xhtml1/dtds.html 0030 * @uses Zend_View_Helper_Placeholder_Container_Standalone 0031 * @package Zend_View 0032 * @subpackage Helper 0033 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0034 * @license http://framework.zend.com/license/new-bsd New BSD License 0035 * @method $this appendAlternate($href, $type, $title, $extras) 0036 * @method $this appendStylesheet($href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) 0037 * @method $this offsetSetAlternate($index, $href, $type, $title, $extras) 0038 * @method $this offsetSetStylesheet($index, $href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) 0039 * @method $this prependAlternate($href, $type, $title, $extras) 0040 * @method $this prependStylesheet($href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) 0041 * @method $this setAlternate($href, $type, $title, $extras) 0042 * @method $this setStylesheet($href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) 0043 */ 0044 class Zend_View_Helper_HeadLink extends Zend_View_Helper_Placeholder_Container_Standalone 0045 { 0046 /** 0047 * $_validAttributes 0048 * 0049 * @var array 0050 */ 0051 protected $_itemKeys = array( 0052 'charset', 0053 'href', 0054 'hreflang', 0055 'id', 0056 'media', 0057 'rel', 0058 'rev', 0059 'type', 0060 'title', 0061 'extras', 0062 'sizes', 0063 ); 0064 0065 /** 0066 * @var string registry key 0067 */ 0068 protected $_regKey = 'Zend_View_Helper_HeadLink'; 0069 0070 /** 0071 * Constructor 0072 * 0073 * Use PHP_EOL as separator 0074 * 0075 * @return void 0076 */ 0077 public function __construct() 0078 { 0079 parent::__construct(); 0080 $this->setSeparator(PHP_EOL); 0081 } 0082 0083 /** 0084 * headLink() - View Helper Method 0085 * 0086 * Returns current object instance. Optionally, allows passing array of 0087 * values to build link. 0088 * 0089 * @return Zend_View_Helper_HeadLink 0090 */ 0091 public function headLink(array $attributes = null, $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND) 0092 { 0093 if (null !== $attributes) { 0094 $item = $this->createData($attributes); 0095 switch ($placement) { 0096 case Zend_View_Helper_Placeholder_Container_Abstract::SET: 0097 $this->set($item); 0098 break; 0099 case Zend_View_Helper_Placeholder_Container_Abstract::PREPEND: 0100 $this->prepend($item); 0101 break; 0102 case Zend_View_Helper_Placeholder_Container_Abstract::APPEND: 0103 default: 0104 $this->append($item); 0105 break; 0106 } 0107 } 0108 return $this; 0109 } 0110 0111 /** 0112 * Overload method access 0113 * 0114 * Creates the following virtual methods: 0115 * - appendStylesheet($href, $media, $conditionalStylesheet, $extras) 0116 * - offsetSetStylesheet($index, $href, $media, $conditionalStylesheet, $extras) 0117 * - prependStylesheet($href, $media, $conditionalStylesheet, $extras) 0118 * - setStylesheet($href, $media, $conditionalStylesheet, $extras) 0119 * - appendAlternate($href, $type, $title, $extras) 0120 * - offsetSetAlternate($index, $href, $type, $title, $extras) 0121 * - prependAlternate($href, $type, $title, $extras) 0122 * - setAlternate($href, $type, $title, $extras) 0123 * 0124 * Items that may be added in the future: 0125 * - Navigation? need to find docs on this 0126 * - public function appendStart() 0127 * - public function appendContents() 0128 * - public function appendPrev() 0129 * - public function appendNext() 0130 * - public function appendIndex() 0131 * - public function appendEnd() 0132 * - public function appendGlossary() 0133 * - public function appendAppendix() 0134 * - public function appendHelp() 0135 * - public function appendBookmark() 0136 * - Other? 0137 * - public function appendCopyright() 0138 * - public function appendChapter() 0139 * - public function appendSection() 0140 * - public function appendSubsection() 0141 * 0142 * @param mixed $method 0143 * @param mixed $args 0144 * @return void 0145 */ 0146 public function __call($method, $args) 0147 { 0148 if (preg_match('/^(?P<action>set|(ap|pre)pend|offsetSet)(?P<type>Stylesheet|Alternate)$/', $method, $matches)) { 0149 $argc = count($args); 0150 $action = $matches['action']; 0151 $type = $matches['type']; 0152 $index = null; 0153 0154 if ('offsetSet' == $action) { 0155 if (0 < $argc) { 0156 $index = array_shift($args); 0157 --$argc; 0158 } 0159 } 0160 0161 if (1 > $argc) { 0162 // require_once 'Zend/View/Exception.php'; 0163 $e = new Zend_View_Exception(sprintf('%s requires at least one argument', $method)); 0164 $e->setView($this->view); 0165 throw $e; 0166 } 0167 0168 if (is_array($args[0])) { 0169 $item = $this->createData($args[0]); 0170 } else { 0171 $dataMethod = 'createData' . $type; 0172 $item = $this->$dataMethod($args); 0173 } 0174 0175 if ($item) { 0176 if ('offsetSet' == $action) { 0177 $this->offsetSet($index, $item); 0178 } else { 0179 $this->$action($item); 0180 } 0181 } 0182 0183 return $this; 0184 } 0185 0186 return parent::__call($method, $args); 0187 } 0188 0189 /** 0190 * Check if value is valid 0191 * 0192 * @param mixed $value 0193 * @return boolean 0194 */ 0195 protected function _isValid($value) 0196 { 0197 if (!$value instanceof stdClass) { 0198 return false; 0199 } 0200 0201 $vars = get_object_vars($value); 0202 $keys = array_keys($vars); 0203 $intersection = array_intersect($this->_itemKeys, $keys); 0204 if (empty($intersection)) { 0205 return false; 0206 } 0207 0208 return true; 0209 } 0210 0211 /** 0212 * append() 0213 * 0214 * @param array $value 0215 * @return void 0216 */ 0217 public function append($value) 0218 { 0219 if (!$this->_isValid($value)) { 0220 // require_once 'Zend/View/Exception.php'; 0221 $e = new Zend_View_Exception('append() expects a data token; please use one of the custom append*() methods'); 0222 $e->setView($this->view); 0223 throw $e; 0224 } 0225 0226 return $this->getContainer()->append($value); 0227 } 0228 0229 /** 0230 * offsetSet() 0231 * 0232 * @param string|int $index 0233 * @param array $value 0234 * @return void 0235 */ 0236 public function offsetSet($index, $value) 0237 { 0238 if (!$this->_isValid($value)) { 0239 // require_once 'Zend/View/Exception.php'; 0240 $e = new Zend_View_Exception('offsetSet() expects a data token; please use one of the custom offsetSet*() methods'); 0241 $e->setView($this->view); 0242 throw $e; 0243 } 0244 0245 return $this->getContainer()->offsetSet($index, $value); 0246 } 0247 0248 /** 0249 * prepend() 0250 * 0251 * @param array $value 0252 * @return Zend_Layout_ViewHelper_HeadLink 0253 */ 0254 public function prepend($value) 0255 { 0256 if (!$this->_isValid($value)) { 0257 // require_once 'Zend/View/Exception.php'; 0258 $e = new Zend_View_Exception('prepend() expects a data token; please use one of the custom prepend*() methods'); 0259 $e->setView($this->view); 0260 throw $e; 0261 } 0262 0263 return $this->getContainer()->prepend($value); 0264 } 0265 0266 /** 0267 * set() 0268 * 0269 * @param array $value 0270 * @return Zend_Layout_ViewHelper_HeadLink 0271 */ 0272 public function set($value) 0273 { 0274 if (!$this->_isValid($value)) { 0275 // require_once 'Zend/View/Exception.php'; 0276 $e = new Zend_View_Exception('set() expects a data token; please use one of the custom set*() methods'); 0277 $e->setView($this->view); 0278 throw $e; 0279 } 0280 0281 return $this->getContainer()->set($value); 0282 } 0283 0284 0285 /** 0286 * Create HTML link element from data item 0287 * 0288 * @param stdClass $item 0289 * @return string 0290 */ 0291 public function itemToString(stdClass $item) 0292 { 0293 $attributes = (array) $item; 0294 $link = '<link '; 0295 0296 foreach ($this->_itemKeys as $itemKey) { 0297 if (isset($attributes[$itemKey])) { 0298 if(is_array($attributes[$itemKey])) { 0299 foreach($attributes[$itemKey] as $key => $value) { 0300 $link .= sprintf('%s="%s" ', $key, ($this->_autoEscape) ? $this->_escape($value) : $value); 0301 } 0302 } else { 0303 $link .= sprintf('%s="%s" ', $itemKey, ($this->_autoEscape) ? $this->_escape($attributes[$itemKey]) : $attributes[$itemKey]); 0304 } 0305 } 0306 } 0307 0308 if ($this->view instanceof Zend_View_Abstract) { 0309 $link .= ($this->view->doctype()->isXhtml()) ? '/>' : '>'; 0310 } else { 0311 $link .= '/>'; 0312 } 0313 0314 if (($link == '<link />') || ($link == '<link >')) { 0315 return ''; 0316 } 0317 0318 if (isset($attributes['conditionalStylesheet']) 0319 && !empty($attributes['conditionalStylesheet']) 0320 && is_string($attributes['conditionalStylesheet'])) 0321 { 0322 if (str_replace(' ', '', $attributes['conditionalStylesheet']) === '!IE') { 0323 $link = '<!-->' . $link . '<!--'; 0324 } 0325 $link = '<!--[if ' . $attributes['conditionalStylesheet'] . ']>' . $link . '<![endif]-->'; 0326 } 0327 0328 return $link; 0329 } 0330 0331 /** 0332 * Render link elements as string 0333 * 0334 * @param string|int $indent 0335 * @return string 0336 */ 0337 public function toString($indent = null) 0338 { 0339 $indent = (null !== $indent) 0340 ? $this->getWhitespace($indent) 0341 : $this->getIndent(); 0342 0343 $items = array(); 0344 $this->getContainer()->ksort(); 0345 foreach ($this as $item) { 0346 $items[] = $this->itemToString($item); 0347 } 0348 0349 return $indent . implode($this->_escape($this->getSeparator()) . $indent, $items); 0350 } 0351 0352 /** 0353 * Create data item for stack 0354 * 0355 * @param array $attributes 0356 * @return stdClass 0357 */ 0358 public function createData(array $attributes) 0359 { 0360 $data = (object) $attributes; 0361 return $data; 0362 } 0363 0364 /** 0365 * Create item for stylesheet link item 0366 * 0367 * @param array $args 0368 * @return stdClass|false Returns fals if stylesheet is a duplicate 0369 */ 0370 public function createDataStylesheet(array $args) 0371 { 0372 $rel = 'stylesheet'; 0373 $type = 'text/css'; 0374 $media = 'screen'; 0375 $conditionalStylesheet = false; 0376 $href = array_shift($args); 0377 0378 if ($this->_isDuplicateStylesheet($href)) { 0379 return false; 0380 } 0381 0382 if (0 < count($args)) { 0383 $media = array_shift($args); 0384 if(is_array($media)) { 0385 $media = implode(',', $media); 0386 } else { 0387 $media = (string) $media; 0388 } 0389 } 0390 if (0 < count($args)) { 0391 $conditionalStylesheet = array_shift($args); 0392 if(!empty($conditionalStylesheet) && is_string($conditionalStylesheet)) { 0393 $conditionalStylesheet = (string) $conditionalStylesheet; 0394 } else { 0395 $conditionalStylesheet = null; 0396 } 0397 } 0398 0399 if(0 < count($args) && is_array($args[0])) { 0400 $extras = array_shift($args); 0401 $extras = (array) $extras; 0402 } 0403 0404 $attributes = compact('rel', 'type', 'href', 'media', 'conditionalStylesheet', 'extras'); 0405 return $this->createData($this->_applyExtras($attributes)); 0406 } 0407 0408 /** 0409 * Is the linked stylesheet a duplicate? 0410 * 0411 * @param string $uri 0412 * @return bool 0413 */ 0414 protected function _isDuplicateStylesheet($uri) 0415 { 0416 foreach ($this->getContainer() as $item) { 0417 if (($item->rel == 'stylesheet') && ($item->href == $uri)) { 0418 return true; 0419 } 0420 } 0421 return false; 0422 } 0423 0424 /** 0425 * Create item for alternate link item 0426 * 0427 * @param array $args 0428 * @return stdClass 0429 */ 0430 public function createDataAlternate(array $args) 0431 { 0432 if (3 > count($args)) { 0433 // require_once 'Zend/View/Exception.php'; 0434 $e = new Zend_View_Exception(sprintf('Alternate tags require 3 arguments; %s provided', count($args))); 0435 $e->setView($this->view); 0436 throw $e; 0437 } 0438 0439 $rel = 'alternate'; 0440 $href = array_shift($args); 0441 $type = array_shift($args); 0442 $title = array_shift($args); 0443 0444 if(0 < count($args) && is_array($args[0])) { 0445 $extras = array_shift($args); 0446 $extras = (array) $extras; 0447 0448 if(isset($extras['media']) && is_array($extras['media'])) { 0449 $extras['media'] = implode(',', $extras['media']); 0450 } 0451 } 0452 0453 $href = (string) $href; 0454 $type = (string) $type; 0455 $title = (string) $title; 0456 0457 $attributes = compact('rel', 'href', 'type', 'title', 'extras'); 0458 return $this->createData($this->_applyExtras($attributes)); 0459 } 0460 0461 /** 0462 * Apply any overrides specified in the 'extras' array 0463 * @param array $attributes 0464 * @return array 0465 */ 0466 protected function _applyExtras($attributes) 0467 { 0468 if (isset($attributes['extras'])) { 0469 foreach ($attributes['extras'] as $eKey=>$eVal) { 0470 if (isset($attributes[$eKey])) { 0471 $attributes[$eKey] = $eVal; 0472 unset($attributes['extras'][$eKey]); 0473 } 0474 } 0475 } 0476 return $attributes; 0477 } 0478 }