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_HeadMeta
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 appendHttpEquiv($keyValue, $content, $conditionalHttpEquiv)
0036  * @method $this appendName($keyValue, $content, $conditionalName)
0037  * @method $this appendProperty($property, $content, $modifiers)
0038  * @method $this offsetSetHttpEquiv($index, $keyValue, $content, $conditionalHttpEquiv)
0039  * @method $this offsetSetName($index, $keyValue, $content, $conditionalName)
0040  * @method $this offsetSetProperty($index, $property, $content, $modifiers)
0041  * @method $this prependHttpEquiv($keyValue, $content, $conditionalHttpEquiv)
0042  * @method $this prependName($keyValue, $content, $conditionalName)
0043  * @method $this prependProperty($property, $content, $modifiers)
0044  * @method $this setCharset($charset)
0045  * @method $this setHttpEquiv($keyValue, $content, $modifiers)
0046  * @method $this setName($keyValue, $content, $modifiers)
0047  * @method $this setProperty($property, $content, $modifiers)
0048  */
0049 class Zend_View_Helper_HeadMeta extends Zend_View_Helper_Placeholder_Container_Standalone
0050 {
0051     /**
0052      * Types of attributes
0053      * @var array
0054      */
0055     protected $_typeKeys     = array('name', 'http-equiv', 'charset', 'property');
0056     protected $_requiredKeys = array('content');
0057     protected $_modifierKeys = array('lang', 'scheme');
0058 
0059     /**
0060      * @var string registry key
0061      */
0062     protected $_regKey = 'Zend_View_Helper_HeadMeta';
0063 
0064     /**
0065      * Constructor
0066      *
0067      * Set separator to PHP_EOL
0068      *
0069      * @return void
0070      */
0071     public function __construct()
0072     {
0073         parent::__construct();
0074         $this->setSeparator(PHP_EOL);
0075     }
0076 
0077     /**
0078      * Retrieve object instance; optionally add meta tag
0079      *
0080      * @param  string $content
0081      * @param  string $keyValue
0082      * @param  string $keyType
0083      * @param  array $modifiers
0084      * @param  string $placement
0085      * @return Zend_View_Helper_HeadMeta
0086      */
0087     public function headMeta($content = null, $keyValue = null, $keyType = 'name', $modifiers = array(), $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND)
0088     {
0089         if ((null !== $content) && (null !== $keyValue)) {
0090             $item   = $this->createData($keyType, $keyValue, $content, $modifiers);
0091             $action = strtolower($placement);
0092             switch ($action) {
0093                 case 'append':
0094                 case 'prepend':
0095                 case 'set':
0096                     $this->$action($item);
0097                     break;
0098                 default:
0099                     $this->append($item);
0100                     break;
0101             }
0102         }
0103 
0104         return $this;
0105     }
0106 
0107     protected function _normalizeType($type)
0108     {
0109         switch ($type) {
0110             case 'Name':
0111                 return 'name';
0112             case 'HttpEquiv':
0113                 return 'http-equiv';
0114             case 'Property':
0115                 return 'property';
0116             default:
0117                 // require_once 'Zend/View/Exception.php';
0118                 $e = new Zend_View_Exception(sprintf('Invalid type "%s" passed to _normalizeType', $type));
0119                 $e->setView($this->view);
0120                 throw $e;
0121         }
0122     }
0123 
0124     /**
0125      * Overload method access
0126      *
0127      * Allows the following 'virtual' methods:
0128      * - appendName($keyValue, $content, $modifiers = array())
0129      * - offsetGetName($index, $keyValue, $content, $modifers = array())
0130      * - prependName($keyValue, $content, $modifiers = array())
0131      * - setName($keyValue, $content, $modifiers = array())
0132      * - appendHttpEquiv($keyValue, $content, $modifiers = array())
0133      * - offsetGetHttpEquiv($index, $keyValue, $content, $modifers = array())
0134      * - prependHttpEquiv($keyValue, $content, $modifiers = array())
0135      * - setHttpEquiv($keyValue, $content, $modifiers = array())
0136      * - appendProperty($keyValue, $content, $modifiers = array())
0137      * - offsetGetProperty($index, $keyValue, $content, $modifiers = array())
0138      * - prependProperty($keyValue, $content, $modifiers = array())
0139      * - setProperty($keyValue, $content, $modifiers = array())
0140      *
0141      * @param  string $method
0142      * @param  array $args
0143      * @return Zend_View_Helper_HeadMeta
0144      */
0145     public function __call($method, $args)
0146     {
0147         if (preg_match('/^(?P<action>set|(pre|ap)pend|offsetSet)(?P<type>Name|HttpEquiv|Property)$/', $method, $matches)) {
0148             $action = $matches['action'];
0149             $type   = $this->_normalizeType($matches['type']);
0150             $argc   = count($args);
0151             $index  = null;
0152 
0153             if ('offsetSet' == $action) {
0154                 if (0 < $argc) {
0155                     $index = array_shift($args);
0156                     --$argc;
0157                 }
0158             }
0159 
0160             if (2 > $argc) {
0161                 // require_once 'Zend/View/Exception.php';
0162                 $e = new Zend_View_Exception('Too few arguments provided; requires key value, and content');
0163                 $e->setView($this->view);
0164                 throw $e;
0165             }
0166 
0167             if (3 > $argc) {
0168                 $args[] = array();
0169             }
0170 
0171             $item  = $this->createData($type, $args[0], $args[1], $args[2]);
0172 
0173             if ('offsetSet' == $action) {
0174                 return $this->offsetSet($index, $item);
0175             }
0176 
0177             $this->$action($item);
0178             return $this;
0179         }
0180 
0181         return parent::__call($method, $args);
0182     }
0183 
0184     /**
0185      * Create an HTML5-style meta charset tag. Something like <meta charset="utf-8">
0186      *
0187      * Not valid in a non-HTML5 doctype
0188      *
0189      * @param string $charset
0190      * @return Zend_View_Helper_HeadMeta Provides a fluent interface
0191      */
0192     public function setCharset($charset)
0193     {
0194         $item = new stdClass;
0195         $item->type = 'charset';
0196         $item->charset = $charset;
0197         $item->content = null;
0198         $item->modifiers = array();
0199         $this->set($item);
0200         return $this;
0201     }
0202 
0203     /**
0204      * Determine if item is valid
0205      *
0206      * @param  mixed $item
0207      * @return boolean
0208      */
0209     protected function _isValid($item)
0210     {
0211         if ((!$item instanceof stdClass)
0212             || !isset($item->type)
0213             || !isset($item->modifiers))
0214         {
0215             return false;
0216         }
0217 
0218         $isHtml5 = is_null($this->view) ? false : $this->view->doctype()->isHtml5();
0219 
0220         if (!isset($item->content)
0221         && (! $isHtml5 || (! $isHtml5 && $item->type !== 'charset'))) {
0222             return false;
0223         }
0224 
0225         // <meta property= ... /> is only supported with doctype RDFa
0226         if ( !is_null($this->view) && !$this->view->doctype()->isRdfa()
0227             && $item->type === 'property') {
0228             return false;
0229         }
0230 
0231         return true;
0232     }
0233 
0234     /**
0235      * Append
0236      *
0237      * @param  string $value
0238      * @return void
0239      * @throws Zend_View_Exception
0240      */
0241     public function append($value)
0242     {
0243         if (!$this->_isValid($value)) {
0244             // require_once 'Zend/View/Exception.php';
0245             $e = new Zend_View_Exception('Invalid value passed to append; please use appendMeta()');
0246             $e->setView($this->view);
0247             throw $e;
0248         }
0249 
0250         return $this->getContainer()->append($value);
0251     }
0252 
0253     /**
0254      * OffsetSet
0255      *
0256      * @param  string|int $index
0257      * @param  string $value
0258      * @return void
0259      * @throws Zend_View_Exception
0260      */
0261     public function offsetSet($index, $value)
0262     {
0263         if (!$this->_isValid($value)) {
0264             // require_once 'Zend/View/Exception.php';
0265             $e =  new Zend_View_Exception('Invalid value passed to offsetSet; please use offsetSetName() or offsetSetHttpEquiv()');
0266             $e->setView($this->view);
0267             throw $e;
0268         }
0269 
0270         return $this->getContainer()->offsetSet($index, $value);
0271     }
0272 
0273     /**
0274      * OffsetUnset
0275      *
0276      * @param  string|int $index
0277      * @return void
0278      * @throws Zend_View_Exception
0279      */
0280     public function offsetUnset($index)
0281     {
0282         if (!in_array($index, $this->getContainer()->getKeys())) {
0283             // require_once 'Zend/View/Exception.php';
0284             $e = new Zend_View_Exception('Invalid index passed to offsetUnset()');
0285             $e->setView($this->view);
0286             throw $e;
0287         }
0288 
0289         return $this->getContainer()->offsetUnset($index);
0290     }
0291 
0292     /**
0293      * Prepend
0294      *
0295      * @param  string $value
0296      * @return void
0297      * @throws Zend_View_Exception
0298      */
0299     public function prepend($value)
0300     {
0301         if (!$this->_isValid($value)) {
0302             // require_once 'Zend/View/Exception.php';
0303             $e = new Zend_View_Exception('Invalid value passed to prepend; please use prependMeta()');
0304             $e->setView($this->view);
0305             throw $e;
0306         }
0307 
0308         return $this->getContainer()->prepend($value);
0309     }
0310 
0311     /**
0312      * Set
0313      *
0314      * @param  string $value
0315      * @return void
0316      * @throws Zend_View_Exception
0317      */
0318     public function set($value)
0319     {
0320         if (!$this->_isValid($value)) {
0321             // require_once 'Zend/View/Exception.php';
0322             $e = new Zend_View_Exception('Invalid value passed to set; please use setMeta()');
0323             $e->setView($this->view);
0324             throw $e;
0325         }
0326 
0327         $container = $this->getContainer();
0328         foreach ($container->getArrayCopy() as $index => $item) {
0329             if ($item->type == $value->type && $item->{$item->type} == $value->{$value->type}) {
0330                 $this->offsetUnset($index);
0331             }
0332         }
0333 
0334         return $this->append($value);
0335     }
0336 
0337     /**
0338      * Build meta HTML string
0339      *
0340      * @param  string $type
0341      * @param  string $typeValue
0342      * @param  string $content
0343      * @param  array $modifiers
0344      * @return string
0345      */
0346     public function itemToString(stdClass $item)
0347     {
0348         if (!in_array($item->type, $this->_typeKeys)) {
0349             // require_once 'Zend/View/Exception.php';
0350             $e = new Zend_View_Exception(sprintf('Invalid type "%s" provided for meta', $item->type));
0351             $e->setView($this->view);
0352             throw $e;
0353         }
0354         $type = $item->type;
0355 
0356         $modifiersString = '';
0357         foreach ($item->modifiers as $key => $value) {
0358             if (!is_null($this->view) && $this->view->doctype()->isHtml5()
0359             && $key == 'scheme') {
0360                 // require_once 'Zend/View/Exception.php';
0361                 throw new Zend_View_Exception('Invalid modifier '
0362                 . '"scheme" provided; not supported by HTML5');
0363             }
0364             if (!in_array($key, $this->_modifierKeys)) {
0365                 continue;
0366             }
0367             $modifiersString .= $key . '="' . $this->_escape($value) . '" ';
0368         }
0369 
0370         if ($this->view instanceof Zend_View_Abstract) {
0371             if ($this->view->doctype()->isHtml5()
0372             && $type == 'charset') {
0373                 $tpl = ($this->view->doctype()->isXhtml())
0374                     ? '<meta %s="%s"/>'
0375                     : '<meta %s="%s">';
0376             } elseif ($this->view->doctype()->isXhtml()) {
0377                 $tpl = '<meta %s="%s" content="%s" %s/>';
0378             } else {
0379                 $tpl = '<meta %s="%s" content="%s" %s>';
0380             }
0381         } else {
0382             $tpl = '<meta %s="%s" content="%s" %s/>';
0383         }
0384 
0385         $meta = sprintf(
0386             $tpl,
0387             $type,
0388             $this->_escape($item->$type),
0389             $this->_escape($item->content),
0390             $modifiersString
0391         );
0392         
0393         if (isset($item->modifiers['conditional'])
0394             && !empty($item->modifiers['conditional'])
0395             && is_string($item->modifiers['conditional']))
0396         {
0397             if (str_replace(' ', '', $item->modifiers['conditional']) === '!IE') {
0398                 $meta = '<!-->' . $meta . '<!--';
0399             }
0400             $meta = '<!--[if ' . $this->_escape($item->modifiers['conditional']) . ']>' . $meta . '<![endif]-->';
0401         }
0402         
0403         return $meta;
0404     }
0405 
0406     /**
0407      * Render placeholder as string
0408      *
0409      * @param  string|int $indent
0410      * @return string
0411      */
0412     public function toString($indent = null)
0413     {
0414         $indent = (null !== $indent)
0415                 ? $this->getWhitespace($indent)
0416                 : $this->getIndent();
0417 
0418         $items = array();
0419         $this->getContainer()->ksort();
0420         try {
0421             foreach ($this as $item) {
0422                 $items[] = $this->itemToString($item);
0423             }
0424         } catch (Zend_View_Exception $e) {
0425             trigger_error($e->getMessage(), E_USER_WARNING);
0426             return '';
0427         }
0428         return $indent . implode($this->_escape($this->getSeparator()) . $indent, $items);
0429     }
0430 
0431     /**
0432      * Create data item for inserting into stack
0433      *
0434      * @param  string $type
0435      * @param  string $typeValue
0436      * @param  string $content
0437      * @param  array $modifiers
0438      * @return stdClass
0439      */
0440     public function createData($type, $typeValue, $content, array $modifiers)
0441     {
0442         $data            = new stdClass;
0443         $data->type      = $type;
0444         $data->$type     = $typeValue;
0445         $data->content   = $content;
0446         $data->modifiers = $modifiers;
0447         return $data;
0448     }
0449 }