Condition.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View\Layout\Reader\Visibility;
  7. use Magento\Framework\Data\Argument\InterpreterInterface;
  8. use Magento\Framework\Simplexml\Element;
  9. use Magento\Framework\View\Layout\AclCondition;
  10. use Magento\Framework\View\Layout\Argument\Parser;
  11. use Magento\Framework\View\Layout\ConfigCondition;
  12. /**
  13. * Parse conditions from element.
  14. */
  15. class Condition
  16. {
  17. /**
  18. * Supported subtypes for visibility conditions.
  19. */
  20. const TYPE_ARGUMENTS = 'arguments';
  21. /**
  22. * @var Parser
  23. */
  24. private $argumentParser;
  25. /**
  26. * @var InterpreterInterface
  27. */
  28. private $argumentInterpreter;
  29. /**
  30. * @param Parser $argumentParser
  31. * @param InterpreterInterface $argumentInterpreter
  32. */
  33. public function __construct(
  34. Parser $argumentParser,
  35. InterpreterInterface $argumentInterpreter
  36. ) {
  37. $this->argumentParser = $argumentParser;
  38. $this->argumentInterpreter = $argumentInterpreter;
  39. }
  40. /**
  41. * @param Element $element
  42. *
  43. * @return array
  44. */
  45. public function parseConditions(Element $element)
  46. {
  47. $visibilityConditions = [];
  48. $configPath = (string)$element->getAttribute('ifconfig');
  49. if (!empty($configPath)) {
  50. $visibilityConditions['ifconfig'] = [
  51. 'name' => ConfigCondition::class,
  52. 'arguments' => [
  53. 'configPath' => $configPath
  54. ],
  55. ];
  56. }
  57. $aclResource = (string)$element->getAttribute('aclResource');
  58. if (!empty($aclResource)) {
  59. $visibilityConditions['acl'] = [
  60. 'name' => AclCondition::class,
  61. 'arguments' => [
  62. 'acl' => $aclResource
  63. ],
  64. ];
  65. }
  66. /** @var $childElement Element */
  67. foreach ($element as $childElement) {
  68. if ($childElement->getName() === 'visibilityCondition') {
  69. $visibilityConditions[$childElement->getAttribute('name')] = [
  70. 'name' => $childElement->getAttribute('className'),
  71. 'arguments' => $this->evaluateArguments($childElement),
  72. ];
  73. }
  74. }
  75. return $visibilityConditions;
  76. }
  77. /**
  78. * Compute argument values
  79. *
  80. * @param Element $blockElement
  81. * @return array
  82. */
  83. private function evaluateArguments(Element $blockElement)
  84. {
  85. $argumentsData = [];
  86. $arguments = $this->getArguments($blockElement);
  87. foreach ($arguments as $argumentName => $argumentData) {
  88. if (isset($argumentData['updater'])) {
  89. continue;
  90. }
  91. $result = $this->argumentInterpreter->evaluate($argumentData);
  92. if (is_array($result)) {
  93. $argumentsData[$argumentName] = isset($argumentsData[$argumentName])
  94. ? array_replace_recursive($argumentsData[$argumentName], $result)
  95. : $result;
  96. } else {
  97. $argumentsData[$argumentName] = $result;
  98. }
  99. }
  100. return $argumentsData;
  101. }
  102. /**
  103. * @param Element $element
  104. *
  105. * @return array
  106. */
  107. private function getArguments(Element $element)
  108. {
  109. $arguments = $this->getElementsByType($element, self::TYPE_ARGUMENTS);
  110. // We have only one declaration of <arguments> node in block or its reference
  111. $argumentElement = reset($arguments);
  112. return $argumentElement ? $this->parseArguments($argumentElement) : [];
  113. }
  114. /**
  115. * Get elements by type
  116. *
  117. * @param Element $element
  118. * @param string $type
  119. * @return array
  120. */
  121. private function getElementsByType(Element $element, $type)
  122. {
  123. $elements = [];
  124. /** @var $childElement Element */
  125. foreach ($element as $childElement) {
  126. if ($childElement->getName() === $type) {
  127. $elements[] = $childElement;
  128. }
  129. }
  130. return $elements;
  131. }
  132. /**
  133. * Parse argument nodes and return their array representation
  134. *
  135. * @param Element $node
  136. * @return array
  137. */
  138. private function parseArguments(Element $node)
  139. {
  140. $nodeDom = dom_import_simplexml($node);
  141. $result = [];
  142. foreach ($nodeDom->childNodes as $argumentNode) {
  143. if ($argumentNode instanceof \DOMElement && $argumentNode->nodeName == 'argument') {
  144. $argumentName = $argumentNode->getAttribute('name');
  145. $result[$argumentName] = $this->argumentParser->parse($argumentNode);
  146. }
  147. }
  148. return $result;
  149. }
  150. }