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

/app/classes/Zend/View/Helper/HeadMeta.php

https://gitlab.com/jalon/doadoronline
PHP | 456 lines | 253 code | 52 blank | 151 comment | 48 complexity | 616c7d13b4ca2cd275baf03ec1dbd6ed MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\View\Helper;
  10. use stdClass;
  11. use Zend\View;
  12. use Zend\View\Exception;
  13. /**
  14. * Zend\View\Helper\HeadMeta
  15. *
  16. * @see http://www.w3.org/TR/xhtml1/dtds.html
  17. *
  18. * Allows the following 'virtual' methods:
  19. * @method HeadMeta appendName($keyValue, $content, $modifiers = array())
  20. * @method HeadMeta offsetGetName($index, $keyValue, $content, $modifiers = array())
  21. * @method HeadMeta prependName($keyValue, $content, $modifiers = array())
  22. * @method HeadMeta setName($keyValue, $content, $modifiers = array())
  23. * @method HeadMeta appendHttpEquiv($keyValue, $content, $modifiers = array())
  24. * @method HeadMeta offsetGetHttpEquiv($index, $keyValue, $content, $modifiers = array())
  25. * @method HeadMeta prependHttpEquiv($keyValue, $content, $modifiers = array())
  26. * @method HeadMeta setHttpEquiv($keyValue, $content, $modifiers = array())
  27. * @method HeadMeta appendProperty($keyValue, $content, $modifiers = array())
  28. * @method HeadMeta offsetGetProperty($index, $keyValue, $content, $modifiers = array())
  29. * @method HeadMeta prependProperty($keyValue, $content, $modifiers = array())
  30. * @method HeadMeta setProperty($keyValue, $content, $modifiers = array())
  31. */
  32. class HeadMeta extends Placeholder\Container\AbstractStandalone
  33. {
  34. /**
  35. * Allowed key types
  36. *
  37. * @var array
  38. */
  39. protected $typeKeys = array('name', 'http-equiv', 'charset', 'property', 'itemprop');
  40. /**
  41. * Required attributes for meta tag
  42. *
  43. * @var array
  44. */
  45. protected $requiredKeys = array('content');
  46. /**
  47. * Allowed modifier keys
  48. *
  49. * @var array
  50. */
  51. protected $modifierKeys = array('lang', 'scheme');
  52. /**
  53. * Registry key for placeholder
  54. *
  55. * @var string
  56. */
  57. protected $regKey = 'Zend_View_Helper_HeadMeta';
  58. /**
  59. * Constructor
  60. *
  61. * Set separator to PHP_EOL
  62. *
  63. */
  64. public function __construct()
  65. {
  66. parent::__construct();
  67. $this->setSeparator(PHP_EOL);
  68. }
  69. /**
  70. * Retrieve object instance; optionally add meta tag
  71. *
  72. * @param string $content
  73. * @param string $keyValue
  74. * @param string $keyType
  75. * @param array $modifiers
  76. * @param string $placement
  77. * @return HeadMeta
  78. */
  79. public function __invoke($content = null, $keyValue = null, $keyType = 'name', $modifiers = array(), $placement = Placeholder\Container\AbstractContainer::APPEND)
  80. {
  81. if ((null !== $content) && (null !== $keyValue)) {
  82. $item = $this->createData($keyType, $keyValue, $content, $modifiers);
  83. $action = strtolower($placement);
  84. switch ($action) {
  85. case 'append':
  86. case 'prepend':
  87. case 'set':
  88. $this->$action($item);
  89. break;
  90. default:
  91. $this->append($item);
  92. break;
  93. }
  94. }
  95. return $this;
  96. }
  97. /**
  98. * Overload method access
  99. *
  100. * @param string $method
  101. * @param array $args
  102. * @throws Exception\BadMethodCallException
  103. * @return HeadMeta
  104. */
  105. public function __call($method, $args)
  106. {
  107. if (preg_match(
  108. '/^(?P<action>set|(pre|ap)pend|offsetSet)(?P<type>Name|HttpEquiv|Property|Itemprop)$/',
  109. $method,
  110. $matches)
  111. ) {
  112. $action = $matches['action'];
  113. $type = $this->normalizeType($matches['type']);
  114. $argc = count($args);
  115. $index = null;
  116. if ('offsetSet' == $action) {
  117. if (0 < $argc) {
  118. $index = array_shift($args);
  119. --$argc;
  120. }
  121. }
  122. if (2 > $argc) {
  123. throw new Exception\BadMethodCallException(
  124. 'Too few arguments provided; requires key value, and content'
  125. );
  126. }
  127. if (3 > $argc) {
  128. $args[] = array();
  129. }
  130. $item = $this->createData($type, $args[0], $args[1], $args[2]);
  131. if ('offsetSet' == $action) {
  132. return $this->offsetSet($index, $item);
  133. }
  134. $this->$action($item);
  135. return $this;
  136. }
  137. return parent::__call($method, $args);
  138. }
  139. /**
  140. * Render placeholder as string
  141. *
  142. * @param string|int $indent
  143. * @return string
  144. */
  145. public function toString($indent = null)
  146. {
  147. $indent = (null !== $indent)
  148. ? $this->getWhitespace($indent)
  149. : $this->getIndent();
  150. $items = array();
  151. $this->getContainer()->ksort();
  152. try {
  153. foreach ($this as $item) {
  154. $items[] = $this->itemToString($item);
  155. }
  156. } catch (Exception\InvalidArgumentException $e) {
  157. trigger_error($e->getMessage(), E_USER_WARNING);
  158. return '';
  159. }
  160. return $indent . implode($this->escape($this->getSeparator()) . $indent, $items);
  161. }
  162. /**
  163. * Create data item for inserting into stack
  164. *
  165. * @param string $type
  166. * @param string $typeValue
  167. * @param string $content
  168. * @param array $modifiers
  169. * @return stdClass
  170. */
  171. public function createData($type, $typeValue, $content, array $modifiers)
  172. {
  173. $data = new stdClass;
  174. $data->type = $type;
  175. $data->$type = $typeValue;
  176. $data->content = $content;
  177. $data->modifiers = $modifiers;
  178. return $data;
  179. }
  180. /**
  181. * Build meta HTML string
  182. *
  183. * @param stdClass $item
  184. * @throws Exception\InvalidArgumentException
  185. * @return string
  186. */
  187. public function itemToString(stdClass $item)
  188. {
  189. if (!in_array($item->type, $this->typeKeys)) {
  190. throw new Exception\InvalidArgumentException(sprintf(
  191. 'Invalid type "%s" provided for meta',
  192. $item->type
  193. ));
  194. }
  195. $type = $item->type;
  196. $modifiersString = '';
  197. foreach ($item->modifiers as $key => $value) {
  198. if ($this->view->plugin('doctype')->isHtml5()
  199. && $key == 'scheme'
  200. ) {
  201. throw new Exception\InvalidArgumentException(
  202. 'Invalid modifier "scheme" provided; not supported by HTML5'
  203. );
  204. }
  205. if (!in_array($key, $this->modifierKeys)) {
  206. continue;
  207. }
  208. $modifiersString .= $key . '="' . $this->escape($value) . '" ';
  209. }
  210. $modifiersString = rtrim($modifiersString);
  211. if ('' != $modifiersString) {
  212. $modifiersString = ' ' . $modifiersString;
  213. }
  214. if (method_exists($this->view, 'plugin')) {
  215. if ($this->view->plugin('doctype')->isHtml5()
  216. && $type == 'charset'
  217. ) {
  218. $tpl = ($this->view->plugin('doctype')->isXhtml())
  219. ? '<meta %s="%s"/>'
  220. : '<meta %s="%s">';
  221. } elseif ($this->view->plugin('doctype')->isXhtml()) {
  222. $tpl = '<meta %s="%s" content="%s"%s />';
  223. } else {
  224. $tpl = '<meta %s="%s" content="%s"%s>';
  225. }
  226. } else {
  227. $tpl = '<meta %s="%s" content="%s"%s />';
  228. }
  229. $meta = sprintf(
  230. $tpl,
  231. $type,
  232. $this->escape($item->$type),
  233. $this->escape($item->content),
  234. $modifiersString
  235. );
  236. if (isset($item->modifiers['conditional'])
  237. && !empty($item->modifiers['conditional'])
  238. && is_string($item->modifiers['conditional']))
  239. {
  240. $meta = '<!--[if ' . $this->escape($item->modifiers['conditional']) . ']>' . $meta . '<![endif]-->';
  241. }
  242. return $meta;
  243. }
  244. /**
  245. * Normalize type attribute of meta
  246. *
  247. * @param string $type type in CamelCase
  248. * @throws Exception\DomainException
  249. * @return string
  250. */
  251. protected function normalizeType($type)
  252. {
  253. switch ($type) {
  254. case 'Name':
  255. return 'name';
  256. case 'HttpEquiv':
  257. return 'http-equiv';
  258. case 'Property':
  259. return 'property';
  260. case 'Itemprop':
  261. return 'itemprop';
  262. default:
  263. throw new Exception\DomainException(sprintf(
  264. 'Invalid type "%s" passed to normalizeType',
  265. $type
  266. ));
  267. }
  268. }
  269. /**
  270. * Determine if item is valid
  271. *
  272. * @param mixed $item
  273. * @return bool
  274. */
  275. protected function isValid($item)
  276. {
  277. if ((!$item instanceof stdClass)
  278. || !isset($item->type)
  279. || !isset($item->modifiers)
  280. ) {
  281. return false;
  282. }
  283. if (!isset($item->content)
  284. && (! $this->view->plugin('doctype')->isHtml5()
  285. || (! $this->view->plugin('doctype')->isHtml5() && $item->type !== 'charset'))
  286. ) {
  287. return false;
  288. }
  289. // <meta itemprop= ... /> is only supported with doctype html
  290. if (! $this->view->plugin('doctype')->isHtml5()
  291. && $item->type === 'itemprop'
  292. ) {
  293. return false;
  294. }
  295. // <meta property= ... /> is only supported with doctype RDFa
  296. if (!$this->view->plugin('doctype')->isRdfa()
  297. && $item->type === 'property'
  298. ) {
  299. return false;
  300. }
  301. return true;
  302. }
  303. /**
  304. * Append
  305. *
  306. * @param string $value
  307. * @return void
  308. * @throws Exception\InvalidArgumentException
  309. */
  310. public function append($value)
  311. {
  312. if (!$this->isValid($value)) {
  313. throw new Exception\InvalidArgumentException(
  314. 'Invalid value passed to append; please use appendMeta()'
  315. );
  316. }
  317. return $this->getContainer()->append($value);
  318. }
  319. /**
  320. * OffsetSet
  321. *
  322. * @param string|int $index
  323. * @param string $value
  324. * @throws Exception\InvalidArgumentException
  325. * @return void
  326. */
  327. public function offsetSet($index, $value)
  328. {
  329. if (!$this->isValid($value)) {
  330. throw new Exception\InvalidArgumentException(
  331. 'Invalid value passed to offsetSet; please use offsetSetName() or offsetSetHttpEquiv()'
  332. );
  333. }
  334. return $this->getContainer()->offsetSet($index, $value);
  335. }
  336. /**
  337. * OffsetUnset
  338. *
  339. * @param string|int $index
  340. * @throws Exception\InvalidArgumentException
  341. * @return void
  342. */
  343. public function offsetUnset($index)
  344. {
  345. if (!in_array($index, $this->getContainer()->getKeys())) {
  346. throw new Exception\InvalidArgumentException('Invalid index passed to offsetUnset()');
  347. }
  348. return $this->getContainer()->offsetUnset($index);
  349. }
  350. /**
  351. * Prepend
  352. *
  353. * @param string $value
  354. * @throws Exception\InvalidArgumentException
  355. * @return void
  356. */
  357. public function prepend($value)
  358. {
  359. if (!$this->isValid($value)) {
  360. throw new Exception\InvalidArgumentException(
  361. 'Invalid value passed to prepend; please use prependMeta()'
  362. );
  363. }
  364. return $this->getContainer()->prepend($value);
  365. }
  366. /**
  367. * Set
  368. *
  369. * @param string $value
  370. * @throws Exception\InvalidArgumentException
  371. * @return void
  372. */
  373. public function set($value)
  374. {
  375. if (!$this->isValid($value)) {
  376. throw new Exception\InvalidArgumentException('Invalid value passed to set; please use setMeta()');
  377. }
  378. $container = $this->getContainer();
  379. foreach ($container->getArrayCopy() as $index => $item) {
  380. if ($item->type == $value->type && $item->{$item->type} == $value->{$value->type}) {
  381. $this->offsetUnset($index);
  382. }
  383. }
  384. return $this->append($value);
  385. }
  386. /**
  387. * Create an HTML5-style meta charset tag. Something like <meta charset="utf-8">
  388. *
  389. * Not valid in a non-HTML5 doctype
  390. *
  391. * @param string $charset
  392. * @return HeadMeta Provides a fluent interface
  393. */
  394. public function setCharset($charset)
  395. {
  396. $item = new stdClass;
  397. $item->type = 'charset';
  398. $item->charset = $charset;
  399. $item->content = null;
  400. $item->modifiers = array();
  401. $this->set($item);
  402. return $this;
  403. }
  404. }