TranslationNodeVisitor.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bridge\Twig\NodeVisitor;
  11. use Symfony\Bridge\Twig\Node\TransNode;
  12. use Twig\Environment;
  13. use Twig\Node\Expression\ConstantExpression;
  14. use Twig\Node\Expression\FilterExpression;
  15. use Twig\Node\Expression\FunctionExpression;
  16. use Twig\Node\Node;
  17. use Twig\NodeVisitor\AbstractNodeVisitor;
  18. /**
  19. * TranslationNodeVisitor extracts translation messages.
  20. *
  21. * @author Fabien Potencier <fabien@symfony.com>
  22. */
  23. final class TranslationNodeVisitor extends AbstractNodeVisitor
  24. {
  25. public const UNDEFINED_DOMAIN = '_undefined';
  26. private $enabled = false;
  27. private $messages = [];
  28. public function enable(): void
  29. {
  30. $this->enabled = true;
  31. $this->messages = [];
  32. }
  33. public function disable(): void
  34. {
  35. $this->enabled = false;
  36. $this->messages = [];
  37. }
  38. public function getMessages(): array
  39. {
  40. return $this->messages;
  41. }
  42. /**
  43. * {@inheritdoc}
  44. */
  45. protected function doEnterNode(Node $node, Environment $env): Node
  46. {
  47. if (!$this->enabled) {
  48. return $node;
  49. }
  50. if (
  51. $node instanceof FilterExpression &&
  52. 'trans' === $node->getNode('filter')->getAttribute('value') &&
  53. $node->getNode('node') instanceof ConstantExpression
  54. ) {
  55. // extract constant nodes with a trans filter
  56. $this->messages[] = [
  57. $node->getNode('node')->getAttribute('value'),
  58. $this->getReadDomainFromArguments($node->getNode('arguments'), 1),
  59. ];
  60. } elseif (
  61. $node instanceof FilterExpression &&
  62. 'trans' === $node->getNode('filter')->getAttribute('value') &&
  63. $node->getNode('node') instanceof FunctionExpression &&
  64. 't' === $node->getNode('node')->getAttribute('name')
  65. ) {
  66. $nodeArguments = $node->getNode('node')->getNode('arguments');
  67. if ($nodeArguments->getIterator()->current() instanceof ConstantExpression) {
  68. $this->messages[] = [
  69. $this->getReadMessageFromArguments($nodeArguments, 0),
  70. $this->getReadDomainFromArguments($nodeArguments, 2),
  71. ];
  72. }
  73. } elseif ($node instanceof TransNode) {
  74. // extract trans nodes
  75. $this->messages[] = [
  76. $node->getNode('body')->getAttribute('data'),
  77. $node->hasNode('domain') ? $this->getReadDomainFromNode($node->getNode('domain')) : null,
  78. ];
  79. }
  80. return $node;
  81. }
  82. /**
  83. * {@inheritdoc}
  84. */
  85. protected function doLeaveNode(Node $node, Environment $env): ?Node
  86. {
  87. return $node;
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function getPriority(): int
  93. {
  94. return 0;
  95. }
  96. private function getReadMessageFromArguments(Node $arguments, int $index): ?string
  97. {
  98. if ($arguments->hasNode('message')) {
  99. $argument = $arguments->getNode('message');
  100. } elseif ($arguments->hasNode($index)) {
  101. $argument = $arguments->getNode($index);
  102. } else {
  103. return null;
  104. }
  105. return $this->getReadMessageFromNode($argument);
  106. }
  107. private function getReadMessageFromNode(Node $node): ?string
  108. {
  109. if ($node instanceof ConstantExpression) {
  110. return $node->getAttribute('value');
  111. }
  112. return null;
  113. }
  114. private function getReadDomainFromArguments(Node $arguments, int $index): ?string
  115. {
  116. if ($arguments->hasNode('domain')) {
  117. $argument = $arguments->getNode('domain');
  118. } elseif ($arguments->hasNode($index)) {
  119. $argument = $arguments->getNode($index);
  120. } else {
  121. return null;
  122. }
  123. return $this->getReadDomainFromNode($argument);
  124. }
  125. private function getReadDomainFromNode(Node $node): ?string
  126. {
  127. if ($node instanceof ConstantExpression) {
  128. return $node->getAttribute('value');
  129. }
  130. return self::UNDEFINED_DOMAIN;
  131. }
  132. }