vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php line 28

Open in your IDE?
  1. <?php
  2. namespace Doctrine\Bundle\DoctrineBundle\Twig;
  3. use Doctrine\SqlFormatter\HtmlHighlighter;
  4. use Doctrine\SqlFormatter\NullHighlighter;
  5. use Doctrine\SqlFormatter\SqlFormatter;
  6. use Symfony\Component\VarDumper\Cloner\Data;
  7. use Twig\Extension\AbstractExtension;
  8. use Twig\TwigFilter;
  9. /**
  10. * This class contains the needed functions in order to do the query highlighting
  11. */
  12. class DoctrineExtension extends AbstractExtension
  13. {
  14. /** @var SqlFormatter */
  15. private $sqlFormatter;
  16. /**
  17. * Define our functions
  18. *
  19. * @return TwigFilter[]
  20. */
  21. public function getFilters()
  22. {
  23. return [
  24. new TwigFilter('doctrine_pretty_query', [$this, 'formatQuery'], ['is_safe' => ['html'], 'deprecated' => true]),
  25. new TwigFilter('doctrine_prettify_sql', [$this, 'prettifySql'], ['is_safe' => ['html']]),
  26. new TwigFilter('doctrine_format_sql', [$this, 'formatSql'], ['is_safe' => ['html']]),
  27. new TwigFilter('doctrine_replace_query_parameters', [$this, 'replaceQueryParameters']),
  28. ];
  29. }
  30. /**
  31. * Escape parameters of a SQL query
  32. * DON'T USE THIS FUNCTION OUTSIDE ITS INTENDED SCOPE
  33. *
  34. * @internal
  35. *
  36. * @param mixed $parameter
  37. *
  38. * @return string
  39. */
  40. public static function escapeFunction($parameter)
  41. {
  42. $result = $parameter;
  43. switch (true) {
  44. // Check if result is non-unicode string using PCRE_UTF8 modifier
  45. case is_string($result) && ! preg_match('//u', $result):
  46. $result = '0x' . strtoupper(bin2hex($result));
  47. break;
  48. case is_string($result):
  49. $result = "'" . addslashes($result) . "'";
  50. break;
  51. case is_array($result):
  52. foreach ($result as &$value) {
  53. $value = static::escapeFunction($value);
  54. }
  55. $result = implode(', ', $result) ?: 'NULL';
  56. break;
  57. case is_object($result):
  58. $result = addslashes((string) $result);
  59. break;
  60. case $result === null:
  61. $result = 'NULL';
  62. break;
  63. case is_bool($result):
  64. $result = $result ? '1' : '0';
  65. break;
  66. }
  67. return $result;
  68. }
  69. /**
  70. * Return a query with the parameters replaced
  71. *
  72. * @param string $query
  73. * @param array|Data $parameters
  74. *
  75. * @return string
  76. */
  77. public function replaceQueryParameters($query, $parameters)
  78. {
  79. if ($parameters instanceof Data) {
  80. $parameters = $parameters->getValue(true);
  81. }
  82. $i = 0;
  83. if (! array_key_exists(0, $parameters) && array_key_exists(1, $parameters)) {
  84. $i = 1;
  85. }
  86. return preg_replace_callback(
  87. '/\?|((?<!:):[a-z0-9_]+)/i',
  88. static function ($matches) use ($parameters, &$i) {
  89. $key = substr($matches[0], 1);
  90. if (! array_key_exists($i, $parameters) && ($key === false || ! array_key_exists($key, $parameters))) {
  91. return $matches[0];
  92. }
  93. $value = array_key_exists($i, $parameters) ? $parameters[$i] : $parameters[$key];
  94. $result = DoctrineExtension::escapeFunction($value);
  95. $i++;
  96. return $result;
  97. },
  98. $query
  99. );
  100. }
  101. /**
  102. * Formats and/or highlights the given SQL statement.
  103. *
  104. * @param string $sql
  105. * @param bool $highlightOnly If true the query is not formatted, just highlighted
  106. *
  107. * @return string
  108. */
  109. public function formatQuery($sql, $highlightOnly = false)
  110. {
  111. @trigger_error(sprintf('The "%s()" method is deprecated and will be removed in DoctrineBundle 3.0.', __METHOD__), E_USER_DEPRECATED);
  112. $this->setUpSqlFormatter(true, true);
  113. if ($highlightOnly) {
  114. return $this->sqlFormatter->highlight($sql);
  115. }
  116. return sprintf(
  117. '<div class="highlight highlight-sql"><pre>%s</pre></div>',
  118. $this->sqlFormatter->format($sql)
  119. );
  120. }
  121. public function prettifySql(string $sql): string
  122. {
  123. $this->setUpSqlFormatter();
  124. return $this->sqlFormatter->highlight($sql);
  125. }
  126. public function formatSql(string $sql, bool $highlight): string
  127. {
  128. $this->setUpSqlFormatter($highlight);
  129. return $this->sqlFormatter->format($sql);
  130. }
  131. private function setUpSqlFormatter(bool $highlight = true, bool $legacy = false): void
  132. {
  133. $this->sqlFormatter = new SqlFormatter($highlight ? new HtmlHighlighter([
  134. HtmlHighlighter::HIGHLIGHT_PRE => 'class="highlight highlight-sql"',
  135. HtmlHighlighter::HIGHLIGHT_QUOTE => 'class="string"',
  136. HtmlHighlighter::HIGHLIGHT_BACKTICK_QUOTE => 'class="string"',
  137. HtmlHighlighter::HIGHLIGHT_RESERVED => 'class="keyword"',
  138. HtmlHighlighter::HIGHLIGHT_BOUNDARY => 'class="symbol"',
  139. HtmlHighlighter::HIGHLIGHT_NUMBER => 'class="number"',
  140. HtmlHighlighter::HIGHLIGHT_WORD => 'class="word"',
  141. HtmlHighlighter::HIGHLIGHT_ERROR => 'class="error"',
  142. HtmlHighlighter::HIGHLIGHT_COMMENT => 'class="comment"',
  143. HtmlHighlighter::HIGHLIGHT_VARIABLE => 'class="variable"',
  144. ], ! $legacy) : new NullHighlighter());
  145. }
  146. /**
  147. * Get the name of the extension
  148. *
  149. * @return string
  150. */
  151. public function getName()
  152. {
  153. return 'doctrine_extension';
  154. }
  155. }