vendor/doctrine/doctrine-bundle/src/Twig/DoctrineExtension.php line 42

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