vendor/netgen/ibexa-site-api/bundle/Templating/Twig/Node/GetAttrExpressionDecorator.php line 200

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Netgen\Bundle\IbexaSiteApiBundle\Templating\Twig\Node;
  4. use Netgen\IbexaSiteApi\Core\Site\Values\Fields;
  5. use Traversable;
  6. use Twig\Compiler;
  7. use Twig\Environment;
  8. use Twig\Extension\CoreExtension;
  9. use Twig\Extension\SandboxExtension;
  10. use Twig\Node\Expression\GetAttrExpression;
  11. use Twig\Node\Node;
  12. use Twig\Source;
  13. use Twig\Template;
  14. final class GetAttrExpressionDecorator extends GetAttrExpression
  15. {
  16. /** @noinspection MagicMethodsValidityInspection */
  17. /** @noinspection PhpMissingParentConstructorInspection */
  18. public function __construct(
  19. private readonly GetAttrExpression $decoratedExpression,
  20. ) {}
  21. public function __toString(): string
  22. {
  23. return $this->decoratedExpression->__toString();
  24. }
  25. public function enableDefinedTest(): void
  26. {
  27. $this->decoratedExpression->enableDefinedTest();
  28. }
  29. public function isDefinedTestEnabled(): bool
  30. {
  31. return $this->decoratedExpression->isDefinedTestEnabled();
  32. }
  33. public function compile(Compiler $compiler): void
  34. {
  35. $env = $compiler->getEnvironment();
  36. $arrayAccessSandbox = false;
  37. // optimize array calls
  38. if (
  39. $this->getAttribute('optimizable')
  40. && !$this->isDefinedTestEnabled()
  41. && $this->getAttribute('type') === Template::ARRAY_CALL
  42. && (!$env->isStrictVariables() || $this->getAttribute('ignore_strict_check'))
  43. ) {
  44. $var = '$' . $compiler->getVarName();
  45. $compiler
  46. ->raw('((' . $var . ' = ')
  47. ->subcompile($this->getNode('node'))
  48. ->raw(') && is_array(')
  49. ->raw($var);
  50. if (!$env->hasExtension(SandboxExtension::class)) {
  51. $compiler
  52. ->raw(') || ')
  53. ->raw($var)
  54. ->raw(' instanceof ArrayAccess ? (')
  55. ->raw($var)
  56. ->raw('[')
  57. ->subcompile($this->getNode('attribute'))
  58. ->raw('] ?? null) : null)');
  59. return;
  60. }
  61. $arrayAccessSandbox = true;
  62. $compiler
  63. ->raw(') || ')
  64. ->raw($var)
  65. ->raw(' instanceof ArrayAccess && in_array(')
  66. ->raw($var.'::class')
  67. ->raw(', CoreExtension::ARRAY_LIKE_CLASSES, true) ? (')
  68. ->raw($var)
  69. ->raw('[')
  70. ->subcompile($this->getNode('attribute'))
  71. ->raw('] ?? null) : ');
  72. }
  73. $compiler->raw(self::class . '::twigGetAttribute($this->env, $this->source, ');
  74. if ($this->getAttribute('ignore_strict_check')) {
  75. $this->getNode('node')->setAttribute('ignore_strict_check', true);
  76. }
  77. $compiler
  78. ->subcompile($this->getNode('node'))
  79. ->raw(', ')
  80. ->subcompile($this->getNode('attribute'));
  81. if ($this->hasNode('arguments')) {
  82. $compiler->raw(', ')->subcompile($this->getNode('arguments'));
  83. } else {
  84. $compiler->raw(', []');
  85. }
  86. $compiler->raw(', ')
  87. ->repr($this->getAttribute('type'))
  88. ->raw(', ')->repr($this->isDefinedTestEnabled())
  89. ->raw(', ')->repr($this->getAttribute('ignore_strict_check'))
  90. ->raw(', ')->repr($env->hasExtension(SandboxExtension::class))
  91. ->raw(', ')->repr($this->getNode('node')->getTemplateLine())
  92. ->raw(')');
  93. if ($arrayAccessSandbox) {
  94. $compiler->raw(')');
  95. }
  96. }
  97. public function getTemplateLine(): int
  98. {
  99. return $this->decoratedExpression->getTemplateLine();
  100. }
  101. public function getNodeTag(): ?string
  102. {
  103. return $this->decoratedExpression->getNodeTag();
  104. }
  105. public function hasAttribute(string $name): bool
  106. {
  107. return $this->decoratedExpression->hasAttribute($name);
  108. }
  109. public function getAttribute($name, $default = null)
  110. {
  111. return $this->decoratedExpression->getAttribute($name, $default);
  112. }
  113. public function setAttribute(string $name, $value): void
  114. {
  115. $this->decoratedExpression->setAttribute($name, $value);
  116. }
  117. public function removeAttribute(string $name): void
  118. {
  119. $this->decoratedExpression->removeAttribute($name);
  120. }
  121. public function hasNode(string $name): bool
  122. {
  123. return $this->decoratedExpression->hasNode($name);
  124. }
  125. public function getNode(string $name): Node
  126. {
  127. return $this->decoratedExpression->getNode($name);
  128. }
  129. public function setNode(string $name, Node $node): void
  130. {
  131. $this->decoratedExpression->setNode($name, $node);
  132. }
  133. public function removeNode(string $name): void
  134. {
  135. $this->decoratedExpression->removeNode($name);
  136. }
  137. public function count()
  138. {
  139. return $this->decoratedExpression->count();
  140. }
  141. public function getIterator(): Traversable
  142. {
  143. return $this->decoratedExpression->getIterator();
  144. }
  145. public function getTemplateName(): ?string
  146. {
  147. return $this->decoratedExpression->getTemplateName();
  148. }
  149. public function setSourceContext(Source $source): void
  150. {
  151. $this->decoratedExpression->setSourceContext($source);
  152. }
  153. public function getSourceContext(): ?Source
  154. {
  155. return $this->decoratedExpression->getSourceContext();
  156. }
  157. /**
  158. * @param string $type
  159. * @param bool $isDefinedTest
  160. * @param bool $ignoreStrictCheck
  161. * @param bool $sandboxed
  162. * @param int $lineno
  163. */
  164. public static function twigGetAttribute(
  165. Environment $env,
  166. Source $source,
  167. mixed $object,
  168. mixed $item,
  169. array $arguments = [],
  170. $type = Template::ANY_CALL,
  171. $isDefinedTest = false,
  172. $ignoreStrictCheck = false,
  173. $sandboxed = false,
  174. $lineno = -1,
  175. ) {
  176. if (!$object instanceof Fields) {
  177. return CoreExtension::getAttribute(
  178. $env,
  179. $source,
  180. $object,
  181. $item,
  182. $arguments,
  183. $type,
  184. $isDefinedTest,
  185. $ignoreStrictCheck,
  186. $sandboxed,
  187. $lineno,
  188. );
  189. }
  190. if ($isDefinedTest) {
  191. return $object->hasField($item);
  192. }
  193. return $object->getField($item);
  194. }
  195. }