vendor/pimcore/pimcore/lib/Twig/Extension/Templating/HeadMeta.php line 356

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. /**
  15.  * ----------------------------------------------------------------------------------
  16.  * based on @author ZF1 Zend_View_Helper_HeadMeta
  17.  * ----------------------------------------------------------------------------------
  18.  */
  19. /**
  20.  * Zend Framework
  21.  *
  22.  * LICENSE
  23.  *
  24.  * This source file is subject to the new BSD license that is bundled
  25.  * with this package in the file LICENSE.txt.
  26.  * It is also available through the world-wide-web at this URL:
  27.  * http://framework.zend.com/license/new-bsd
  28.  * If you did not receive a copy of the license and are unable to
  29.  * obtain it through the world-wide-web, please send an email
  30.  * to [email protected] so we can send you a copy immediately.
  31.  *
  32.  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  33.  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  34.  */
  35. namespace Pimcore\Twig\Extension\Templating;
  36. use Pimcore\Twig\Extension\Templating\Placeholder\AbstractExtension;
  37. use Pimcore\Twig\Extension\Templating\Placeholder\Container;
  38. use Pimcore\Twig\Extension\Templating\Placeholder\ContainerService;
  39. use Pimcore\Twig\Extension\Templating\Placeholder\Exception;
  40. use Pimcore\Twig\Extension\Templating\Traits\TextUtilsTrait;
  41. use Twig\Extension\RuntimeExtensionInterface;
  42. /**
  43.  * @method $this appendHttpEquiv($keyValue, $content, $conditionalHttpEquiv=[])
  44.  * @method $this appendName($keyValue, $content, $conditionalName=[])
  45.  * @method $this appendProperty($property, $content, $modifiers=[])
  46.  * @method $this offsetSetHttpEquiv($index, $keyValue, $content, $conditionalHttpEquiv=[])
  47.  * @method $this offsetSetName($index, $keyValue, $content, $conditionalName=[])
  48.  * @method $this offsetSetProperty($index, $property, $content, $modifiers=[])
  49.  * @method $this prependHttpEquiv($keyValue, $content, $conditionalHttpEquiv=[])
  50.  * @method $this prependName($keyValue, $content, $conditionalName=[])
  51.  * @method $this prependProperty($property, $content, $modifiers=[])
  52.  * @method $this setHttpEquiv($keyValue, $content, $modifiers=[])
  53.  * @method $this setName($keyValue, $content, $modifiers=[])
  54.  * @method $this setProperty($property, $content, $modifiers=[])
  55.  *
  56.  */
  57. class HeadMeta extends AbstractExtension implements RuntimeExtensionInterface
  58. {
  59.     use TextUtilsTrait;
  60.     /**
  61.      * Types of attributes
  62.      *
  63.      * @var array
  64.      */
  65.     protected $_typeKeys = ['name''http-equiv''charset''property'];
  66.     protected $_requiredKeys = ['content'];
  67.     protected $_modifierKeys = ['lang''scheme'];
  68.     protected $rawItems = [];
  69.     /**
  70.      * @var string registry key
  71.      */
  72.     protected $_regKey 'HeadMeta';
  73.     /**
  74.      * HeadMeta constructor.
  75.      *
  76.      * Set separator to PHP_EOL.
  77.      *
  78.      * @param ContainerService $containerService
  79.      */
  80.     public function __construct(ContainerService $containerService)
  81.     {
  82.         parent::__construct($containerService);
  83.         $this->setSeparator(PHP_EOL);
  84.     }
  85.     /**
  86.      * Retrieve object instance; optionally add meta tag
  87.      *
  88.      * @param  string $content
  89.      * @param  string $keyValue
  90.      * @param  string $keyType
  91.      * @param  array $modifiers
  92.      * @param  string $placement
  93.      *
  94.      * @return HeadMeta
  95.      */
  96.     public function __invoke($content null$keyValue null$keyType 'name'$modifiers = [], $placement Container::APPEND)
  97.     {
  98.         if ((null !== $content) && (null !== $keyValue)) {
  99.             $item $this->createData($keyType$keyValue$content$modifiers);
  100.             $action strtolower($placement);
  101.             switch ($action) {
  102.                 case 'append':
  103.                 case 'prepend':
  104.                 case 'set':
  105.                     $this->$action($item);
  106.                     break;
  107.                 default:
  108.                     $this->append($item);
  109.                     break;
  110.             }
  111.         }
  112.         return $this;
  113.     }
  114.     protected function _normalizeType($type)
  115.     {
  116.         switch ($type) {
  117.             case 'Name':
  118.                 return 'name';
  119.             case 'HttpEquiv':
  120.                 return 'http-equiv';
  121.             case 'Property':
  122.                 return 'property';
  123.             default:
  124.                 throw new Exception(sprintf('Invalid type "%s" passed to _normalizeType'$type));
  125.         }
  126.     }
  127.     /**
  128.      * @param string $type
  129.      * @param string $keyValue
  130.      *
  131.      * @return mixed
  132.      */
  133.     public function getItem($type$keyValue)
  134.     {
  135.         foreach ($this->getContainer() as $item) {
  136.             if (isset($item->$type) && $item->$type == $keyValue) {
  137.                 return $item->content;
  138.             }
  139.         }
  140.     }
  141.     /**
  142.      * Overload method access
  143.      *
  144.      * Allows the following 'virtual' methods:
  145.      * - appendName($keyValue, $content, $modifiers = array())
  146.      * - prependName($keyValue, $content, $modifiers = array())
  147.      * - setName($keyValue, $content, $modifiers = array())
  148.      * - appendHttpEquiv($keyValue, $content, $modifiers = array())
  149.      * - prependHttpEquiv($keyValue, $content, $modifiers = array())
  150.      * - setHttpEquiv($keyValue, $content, $modifiers = array())
  151.      * - appendProperty($keyValue, $content, $modifiers = array())
  152.      * - prependProperty($keyValue, $content, $modifiers = array())
  153.      * - setProperty($keyValue, $content, $modifiers = array())
  154.      *
  155.      * @param  string $method
  156.      * @param  array $args
  157.      *
  158.      * @return HeadMeta
  159.      */
  160.     public function __call($method$args)
  161.     {
  162.         if (preg_match('/^(?P<action>set|(pre|ap)pend|offsetSet)(?P<type>Name|HttpEquiv|Property)$/'$method$matches)) {
  163.             $action $matches['action'];
  164.             $type $this->_normalizeType($matches['type']);
  165.             $argc count($args);
  166.             $index null;
  167.             if ('offsetSet' == $action) {
  168.                 if ($argc) {
  169.                     $index array_shift($args);
  170.                     --$argc;
  171.                 }
  172.             }
  173.             if ($argc) {
  174.                 throw new Exception('Too few arguments provided; requires key value, and content');
  175.             }
  176.             if ($argc) {
  177.                 $args[] = [];
  178.             }
  179.             $item $this->createData($type$args[0], $args[1], $args[2]);
  180.             if ('offsetSet' == $action) {
  181.                 $this->offsetSet($index$item);
  182.                 return $this;
  183.             }
  184.             $this->$action($item);
  185.             return $this;
  186.         }
  187.         return parent::__call($method$args);
  188.     }
  189.     /**
  190.      * Determine if item is valid
  191.      *
  192.      * @param  mixed $item
  193.      *
  194.      * @return bool
  195.      */
  196.     protected function _isValid($item)
  197.     {
  198.         return true;
  199.     }
  200.     /**
  201.      * Append
  202.      *
  203.      * @param  string $value
  204.      *
  205.      * @return void
  206.      *
  207.      * @throws Exception
  208.      */
  209.     public function append($value)
  210.     {
  211.         if (!$this->_isValid($value)) {
  212.             throw new Exception('Invalid value passed to append; please use appendMeta()');
  213.         }
  214.         $this->getContainer()->append($value);
  215.     }
  216.     /**
  217.      * OffsetSet
  218.      *
  219.      * @param  string|int $index
  220.      * @param  string $value
  221.      *
  222.      * @return void
  223.      *
  224.      * @throws Exception
  225.      */
  226.     public function offsetSet($index$value)
  227.     {
  228.         if (!$this->_isValid($value)) {
  229.             throw new Exception('Invalid value passed to offsetSet; please use offsetSetName() or offsetSetHttpEquiv()');
  230.         }
  231.         $this->getContainer()->offsetSet($index$value);
  232.     }
  233.     /**
  234.      * OffsetUnset
  235.      *
  236.      * @param  string|int $index
  237.      *
  238.      * @return void
  239.      *
  240.      * @throws Exception
  241.      */
  242.     public function offsetUnset($index)
  243.     {
  244.         if (!in_array($index$this->getContainer()->getKeys())) {
  245.             throw new Exception('Invalid index passed to offsetUnset()');
  246.         }
  247.         $this->getContainer()->offsetUnset($index);
  248.     }
  249.     /**
  250.      * Prepend
  251.      *
  252.      * @param  string $value
  253.      *
  254.      * @return void
  255.      *
  256.      * @throws Exception
  257.      */
  258.     public function prepend($value)
  259.     {
  260.         if (!$this->_isValid($value)) {
  261.             throw new Exception('Invalid value passed to prepend; please use prependMeta()');
  262.         }
  263.         $this->getContainer()->prepend($value);
  264.     }
  265.     /**
  266.      * Set
  267.      *
  268.      * @param mixed $value
  269.      *
  270.      * @return void
  271.      *
  272.      * @throws Exception
  273.      */
  274.     public function set($value)
  275.     {
  276.         if (!$this->_isValid($value)) {
  277.             throw new Exception('Invalid value passed to set; please use setMeta()');
  278.         }
  279.         $container $this->getContainer();
  280.         foreach ($container->getArrayCopy() as $index => $item) {
  281.             if ($item->type == $value->type && $item->{$item->type} == $value->{$value->type}) {
  282.                 $this->offsetUnset($index);
  283.             }
  284.         }
  285.         $this->append($value);
  286.     }
  287.     /**
  288.      * Build meta HTML string
  289.      *
  290.      * @param \stdClass $item
  291.      *
  292.      * @return string
  293.      */
  294.     public function itemToString(\stdClass $item)
  295.     {
  296.         if (!in_array($item->type$this->_typeKeys)) {
  297.             throw new Exception(sprintf('Invalid type "%s" provided for meta'$item->type));
  298.         }
  299.         $type $item->type;
  300.         $modifiersString '';
  301.         foreach ($item->modifiers as $key => $value) {
  302.             if (!in_array($key$this->_modifierKeys)) {
  303.                 continue;
  304.             }
  305.             $modifiersString .= $key '="' $this->_escape($value) . '" ';
  306.         }
  307.         $tpl '<meta %s="%s" content="%s" %s/>';
  308.         $meta sprintf(
  309.             $tpl,
  310.             $type,
  311.             $this->_escape($item->$type),
  312.             $this->_escape($item->content),
  313.             $modifiersString
  314.         );
  315.         if (isset($item->modifiers['conditional'])
  316.             && !empty($item->modifiers['conditional'])
  317.             && is_string($item->modifiers['conditional'])) {
  318.             if (str_replace(' '''$item->modifiers['conditional']) === '!IE') {
  319.                 $meta '<!-->' $meta '<!--';
  320.             }
  321.             $meta '<!--[if ' $this->_escape($item->modifiers['conditional']) . ']>' $meta '<![endif]-->';
  322.         }
  323.         return $meta;
  324.     }
  325.     /**
  326.      * Render placeholder as string
  327.      *
  328.      * @param  string|int $indent
  329.      *
  330.      * @return string
  331.      */
  332.     public function toString($indent null)
  333.     {
  334.         $indent = (null !== $indent)
  335.             ? $this->getWhitespace($indent)
  336.             : $this->getIndent();
  337.         $items = [];
  338.         $this->getContainer()->ksort();
  339.         try {
  340.             foreach ($this as $item) {
  341.                 $items[] = $this->itemToString($item);
  342.             }
  343.         } catch (Exception $e) {
  344.             trigger_error($e->getMessage(), E_USER_WARNING);
  345.             return '';
  346.         }
  347.         $metaString $indent implode($this->_escape($this->getSeparator()) . $indent$items);
  348.         // add raw items
  349.         $separator $this->_escape($this->getSeparator()) . $indent;
  350.         $metaString .= ($separator implode($separator$this->rawItems));
  351.         return $metaString;
  352.     }
  353.     /**
  354.      * Create data item for inserting into stack
  355.      *
  356.      * @param  string $type
  357.      * @param  string $typeValue
  358.      * @param  string $content
  359.      * @param  array $modifiers
  360.      *
  361.      * @return \stdClass
  362.      */
  363.     public function createData($type$typeValue$content, array $modifiers)
  364.     {
  365.         $data = new \stdClass;
  366.         $data->type $type;
  367.         $data->$type $typeValue;
  368.         $data->content $content;
  369.         $data->modifiers $modifiers;
  370.         return $data;
  371.     }
  372.     /**
  373.      * @param string $html
  374.      *
  375.      * @return $this
  376.      */
  377.     public function addRaw($html)
  378.     {
  379.         $this->rawItems[] = $html;
  380.         return $this;
  381.     }
  382.     /**
  383.      * @return array
  384.      */
  385.     public function getRaw()
  386.     {
  387.         return $this->rawItems;
  388.     }
  389.     /**
  390.      * @param string $string
  391.      * @param int $length
  392.      * @param string $suffix
  393.      *
  394.      * @return $this
  395.      */
  396.     public function setDescription($string$length null$suffix '')
  397.     {
  398.         $string $this->normalizeString($string$length$suffix);
  399.         return $this->setName('description'$string);
  400.     }
  401. }