Head.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View\Page\Config\Reader;
  7. use Magento\Framework\View\Layout;
  8. use Magento\Framework\View\Page\Config as PageConfig;
  9. use Magento\Framework\View\Page\Config\Structure;
  10. /**
  11. * Head structure reader is intended for collecting assets, title and metadata
  12. */
  13. class Head implements Layout\ReaderInterface
  14. {
  15. /**#@+
  16. * Supported types
  17. */
  18. const TYPE_HEAD = 'head';
  19. /**#@-*/
  20. /**#@+
  21. * Supported head elements
  22. */
  23. const HEAD_CSS = 'css';
  24. const HEAD_SCRIPT = 'script';
  25. const HEAD_LINK = 'link';
  26. const HEAD_REMOVE = 'remove';
  27. const HEAD_TITLE = 'title';
  28. const HEAD_META = 'meta';
  29. const HEAD_ATTRIBUTE = 'attribute';
  30. /**#@-*/
  31. /**
  32. * {@inheritdoc}
  33. *
  34. * @return string[]
  35. */
  36. public function getSupportedNodes()
  37. {
  38. return [self::TYPE_HEAD];
  39. }
  40. /**
  41. * Add asset content type to node by name
  42. *
  43. * @param Layout\Element $node
  44. * @return void
  45. */
  46. protected function addContentTypeByNodeName(Layout\Element $node)
  47. {
  48. switch ($node->getName()) {
  49. case self::HEAD_CSS:
  50. $node->addAttribute('content_type', 'css');
  51. break;
  52. case self::HEAD_SCRIPT:
  53. $node->addAttribute('content_type', 'js');
  54. break;
  55. }
  56. }
  57. /**
  58. * {@inheritdoc}
  59. *
  60. * @param Layout\Reader\Context $readerContext
  61. * @param Layout\Element $headElement
  62. * @return $this
  63. */
  64. public function interpret(
  65. Layout\Reader\Context $readerContext,
  66. Layout\Element $headElement
  67. ) {
  68. $pageConfigStructure = $readerContext->getPageConfigStructure();
  69. $orderedNodes = [];
  70. foreach ($headElement as $node) {
  71. $nodeOrder = $node->getAttribute('order') ?: 0;
  72. $orderedNodes[$nodeOrder][] = $node;
  73. }
  74. ksort($orderedNodes);
  75. foreach ($orderedNodes as $nodes) {
  76. /** @var \Magento\Framework\View\Layout\Element $node */
  77. foreach ($nodes as $node) {
  78. $this->processNode($node, $pageConfigStructure);
  79. }
  80. }
  81. return $this;
  82. }
  83. /**
  84. * Get all attributes for current dom element
  85. *
  86. * @param \Magento\Framework\View\Layout\Element $element
  87. * @return array
  88. */
  89. protected function getAttributes($element)
  90. {
  91. $attributes = [];
  92. foreach ($element->attributes() as $attrName => $attrValue) {
  93. $attributes[$attrName] = (string)$attrValue;
  94. }
  95. return $attributes;
  96. }
  97. /**
  98. * Set metadata
  99. *
  100. * @param \Magento\Framework\View\Page\Config\Structure $pageConfigStructure
  101. * @param \Magento\Framework\View\Layout\Element $node
  102. * @return void
  103. */
  104. private function setMetadata($pageConfigStructure, $node)
  105. {
  106. if (!$node->getAttribute('name') && $node->getAttribute('property')) {
  107. $metadataName = $node->getAttribute('property');
  108. } else {
  109. $metadataName = $node->getAttribute('name');
  110. }
  111. $pageConfigStructure->setMetadata($metadataName, $node->getAttribute('content'));
  112. }
  113. /**
  114. * Process given node based on it's name.
  115. *
  116. * @param Layout\Element $node
  117. * @param Structure $pageConfigStructure
  118. * @return void
  119. */
  120. private function processNode(Layout\Element $node, Structure $pageConfigStructure)
  121. {
  122. switch ($node->getName()) {
  123. case self::HEAD_CSS:
  124. case self::HEAD_SCRIPT:
  125. case self::HEAD_LINK:
  126. $this->addContentTypeByNodeName($node);
  127. $pageConfigStructure->addAssets($node->getAttribute('src'), $this->getAttributes($node));
  128. break;
  129. case self::HEAD_REMOVE:
  130. $pageConfigStructure->removeAssets($node->getAttribute('src'));
  131. break;
  132. case self::HEAD_TITLE:
  133. $pageConfigStructure->setTitle(new \Magento\Framework\Phrase($node));
  134. break;
  135. case self::HEAD_META:
  136. $this->setMetadata($pageConfigStructure, $node);
  137. break;
  138. case self::HEAD_ATTRIBUTE:
  139. $pageConfigStructure->setElementAttribute(
  140. PageConfig::ELEMENT_TYPE_HEAD,
  141. $node->getAttribute('name'),
  142. $node->getAttribute('value')
  143. );
  144. break;
  145. default:
  146. break;
  147. }
  148. }
  149. }