Container.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View\Layout\Generator;
  7. use Magento\Framework\View\Layout;
  8. class Container implements Layout\GeneratorInterface
  9. {
  10. /**#@+
  11. * Names of container options in layout
  12. */
  13. const CONTAINER_OPT_HTML_TAG = 'htmlTag';
  14. const CONTAINER_OPT_HTML_CLASS = 'htmlClass';
  15. const CONTAINER_OPT_HTML_ID = 'htmlId';
  16. const CONTAINER_OPT_LABEL = 'label';
  17. /**#@-*/
  18. const TYPE = 'container';
  19. /**
  20. * @var array
  21. */
  22. protected $allowedTags = [
  23. 'aside',
  24. 'dd',
  25. 'div',
  26. 'dl',
  27. 'fieldset',
  28. 'main',
  29. 'nav',
  30. 'header',
  31. 'footer',
  32. 'ol',
  33. 'p',
  34. 'section',
  35. 'table',
  36. 'tfoot',
  37. 'ul',
  38. ];
  39. /**
  40. * {@inheritdoc}
  41. *
  42. * @return string
  43. */
  44. public function getType()
  45. {
  46. return self::TYPE;
  47. }
  48. /**
  49. * Process container elements
  50. *
  51. * @param \Magento\Framework\View\Layout\Reader\Context $readerContext
  52. * @param Context $generatorContext
  53. * @return $this
  54. */
  55. public function process(Layout\Reader\Context $readerContext, Layout\Generator\Context $generatorContext)
  56. {
  57. $structure = $generatorContext->getStructure();
  58. $scheduledStructure = $readerContext->getScheduledStructure();
  59. foreach ($scheduledStructure->getElements() as $elementName => $element) {
  60. list($type, $data) = $element;
  61. if ($type === self::TYPE) {
  62. $this->generateContainer($structure, $elementName, $data['attributes']);
  63. $scheduledStructure->unsetElement($elementName);
  64. }
  65. }
  66. return $this;
  67. }
  68. /**
  69. * Set container-specific data to structure element
  70. *
  71. * @param \Magento\Framework\View\Layout\Data\Structure $structure
  72. * @param string $elementName
  73. * @param array $options
  74. * @return void
  75. */
  76. public function generateContainer(
  77. Layout\Data\Structure $structure,
  78. $elementName,
  79. $options
  80. ) {
  81. unset($options['type']);
  82. $this->validateOptions($options);
  83. foreach ($options as $key => $value) {
  84. $structure->setAttribute($elementName, $key, $value);
  85. }
  86. }
  87. /**
  88. * @param array $options
  89. * @return void
  90. * @throws \Magento\Framework\Exception\LocalizedException
  91. */
  92. protected function validateOptions($options)
  93. {
  94. if (!empty($options[Layout\Element::CONTAINER_OPT_HTML_TAG])
  95. && !in_array(
  96. $options[Layout\Element::CONTAINER_OPT_HTML_TAG],
  97. $this->allowedTags
  98. )
  99. ) {
  100. throw new \Magento\Framework\Exception\LocalizedException(
  101. new \Magento\Framework\Phrase(
  102. 'Html tag "%1" is forbidden for usage in containers. Consider to use one of the allowed: %2.',
  103. [$options[Layout\Element::CONTAINER_OPT_HTML_TAG], implode(', ', $this->allowedTags)]
  104. )
  105. );
  106. }
  107. if (empty($options[Layout\Element::CONTAINER_OPT_HTML_TAG])
  108. && (
  109. !empty($options[Layout\Element::CONTAINER_OPT_HTML_ID])
  110. || !empty($options[Layout\Element::CONTAINER_OPT_HTML_CLASS])
  111. )
  112. ) {
  113. throw new \Magento\Framework\Exception\LocalizedException(
  114. new \Magento\Framework\Phrase('HTML ID or class will not have effect, if HTML tag is not specified.')
  115. );
  116. }
  117. }
  118. }