[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/symfony/twig-bridge/Extension/ -> CodeExtension.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Bridge\Twig\Extension;
  13  
  14  use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
  15  use Twig\Extension\AbstractExtension;
  16  use Twig\TwigFilter;
  17  
  18  /**
  19   * Twig extension relate to PHP code and used by the profiler and the default exception templates.
  20   *
  21   * @author Fabien Potencier <fabien@symfony.com>
  22   */
  23  class CodeExtension extends AbstractExtension
  24  {
  25      private $fileLinkFormat;
  26      private $rootDir;
  27      private $charset;
  28  
  29      /**
  30       * @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
  31       * @param string                   $rootDir        The project root directory
  32       * @param string                   $charset        The charset
  33       */
  34      public function __construct($fileLinkFormat, $rootDir, $charset)
  35      {
  36          $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
  37          $this->rootDir = str_replace('/', \DIRECTORY_SEPARATOR, \dirname($rootDir)).\DIRECTORY_SEPARATOR;
  38          $this->charset = $charset;
  39      }
  40  
  41      /**
  42       * {@inheritdoc}
  43       */
  44      public function getFilters()
  45      {
  46          return [
  47              new TwigFilter('abbr_class', [$this, 'abbrClass'], ['is_safe' => ['html']]),
  48              new TwigFilter('abbr_method', [$this, 'abbrMethod'], ['is_safe' => ['html']]),
  49              new TwigFilter('format_args', [$this, 'formatArgs'], ['is_safe' => ['html']]),
  50              new TwigFilter('format_args_as_text', [$this, 'formatArgsAsText']),
  51              new TwigFilter('file_excerpt', [$this, 'fileExcerpt'], ['is_safe' => ['html']]),
  52              new TwigFilter('format_file', [$this, 'formatFile'], ['is_safe' => ['html']]),
  53              new TwigFilter('format_file_from_text', [$this, 'formatFileFromText'], ['is_safe' => ['html']]),
  54              new TwigFilter('format_log_message', [$this, 'formatLogMessage'], ['is_safe' => ['html']]),
  55              new TwigFilter('file_link', [$this, 'getFileLink']),
  56          ];
  57      }
  58  
  59      public function abbrClass($class)
  60      {
  61          $parts = explode('\\', $class);
  62          $short = array_pop($parts);
  63  
  64          return sprintf('<abbr title="%s">%s</abbr>', $class, $short);
  65      }
  66  
  67      public function abbrMethod($method)
  68      {
  69          if (false !== strpos($method, '::')) {
  70              list($class, $method) = explode('::', $method, 2);
  71              $result = sprintf('%s::%s()', $this->abbrClass($class), $method);
  72          } elseif ('Closure' === $method) {
  73              $result = sprintf('<abbr title="%s">%1$s</abbr>', $method);
  74          } else {
  75              $result = sprintf('<abbr title="%s">%1$s</abbr>()', $method);
  76          }
  77  
  78          return $result;
  79      }
  80  
  81      /**
  82       * Formats an array as a string.
  83       *
  84       * @param array $args The argument array
  85       *
  86       * @return string
  87       */
  88      public function formatArgs($args)
  89      {
  90          $result = [];
  91          foreach ($args as $key => $item) {
  92              if ('object' === $item[0]) {
  93                  $parts = explode('\\', $item[1]);
  94                  $short = array_pop($parts);
  95                  $formattedValue = sprintf('<em>object</em>(<abbr title="%s">%s</abbr>)', $item[1], $short);
  96              } elseif ('array' === $item[0]) {
  97                  $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
  98              } elseif ('null' === $item[0]) {
  99                  $formattedValue = '<em>null</em>';
 100              } elseif ('boolean' === $item[0]) {
 101                  $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
 102              } elseif ('resource' === $item[0]) {
 103                  $formattedValue = '<em>resource</em>';
 104              } else {
 105                  $formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset));
 106              }
 107  
 108              $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
 109          }
 110  
 111          return implode(', ', $result);
 112      }
 113  
 114      /**
 115       * Formats an array as a string.
 116       *
 117       * @param array $args The argument array
 118       *
 119       * @return string
 120       */
 121      public function formatArgsAsText($args)
 122      {
 123          return strip_tags($this->formatArgs($args));
 124      }
 125  
 126      /**
 127       * Returns an excerpt of a code file around the given line number.
 128       *
 129       * @param string $file       A file path
 130       * @param int    $line       The selected line number
 131       * @param int    $srcContext The number of displayed lines around or -1 for the whole file
 132       *
 133       * @return string An HTML string
 134       */
 135      public function fileExcerpt($file, $line, $srcContext = 3)
 136      {
 137          if (is_file($file) && is_readable($file)) {
 138              // highlight_file could throw warnings
 139              // see https://bugs.php.net/25725
 140              $code = @highlight_file($file, true);
 141              // remove main code/span tags
 142              $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
 143              // split multiline spans
 144              $code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', function ($m) {
 145                  return "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>';
 146              }, $code);
 147              $content = explode('<br />', $code);
 148  
 149              $lines = [];
 150              if (0 > $srcContext) {
 151                  $srcContext = \count($content);
 152              }
 153  
 154              for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) {
 155                  $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><a class="anchor" name="line'.$i.'"></a><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
 156              }
 157  
 158              return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
 159          }
 160  
 161          return null;
 162      }
 163  
 164      /**
 165       * Formats a file path.
 166       *
 167       * @param string $file An absolute file path
 168       * @param int    $line The line number
 169       * @param string $text Use this text for the link rather than the file path
 170       *
 171       * @return string
 172       */
 173      public function formatFile($file, $line, $text = null)
 174      {
 175          $file = trim($file);
 176  
 177          if (null === $text) {
 178              $text = str_replace('/', \DIRECTORY_SEPARATOR, $file);
 179              if (0 === strpos($text, $this->rootDir)) {
 180                  $text = substr($text, \strlen($this->rootDir));
 181                  $text = explode(\DIRECTORY_SEPARATOR, $text, 2);
 182                  $text = sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->rootDir, $text[0], isset($text[1]) ? \DIRECTORY_SEPARATOR.$text[1] : '');
 183              }
 184          }
 185  
 186          if (0 < $line) {
 187              $text .= ' at line '.$line;
 188          }
 189  
 190          if (false !== $link = $this->getFileLink($file, $line)) {
 191              return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', htmlspecialchars($link, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $text);
 192          }
 193  
 194          return $text;
 195      }
 196  
 197      /**
 198       * Returns the link for a given file/line pair.
 199       *
 200       * @param string $file An absolute file path
 201       * @param int    $line The line number
 202       *
 203       * @return string|false A link or false
 204       */
 205      public function getFileLink($file, $line)
 206      {
 207          if ($fmt = $this->fileLinkFormat) {
 208              return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
 209          }
 210  
 211          return false;
 212      }
 213  
 214      public function formatFileFromText($text)
 215      {
 216          return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) {
 217              return 'in '.$this->formatFile($match[2], $match[3]);
 218          }, $text);
 219      }
 220  
 221      /**
 222       * @internal
 223       */
 224      public function formatLogMessage($message, array $context)
 225      {
 226          if ($context && false !== strpos($message, '{')) {
 227              $replacements = [];
 228              foreach ($context as $key => $val) {
 229                  if (is_scalar($val)) {
 230                      $replacements['{'.$key.'}'] = $val;
 231                  }
 232              }
 233  
 234              if ($replacements) {
 235                  $message = strtr($message, $replacements);
 236              }
 237          }
 238  
 239          return htmlspecialchars($message, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset);
 240      }
 241  
 242      /**
 243       * {@inheritdoc}
 244       */
 245      public function getName()
 246      {
 247          return 'code';
 248      }
 249  
 250      protected static function fixCodeMarkup($line)
 251      {
 252          // </span> ending tag from previous line
 253          $opening = strpos($line, '<span');
 254          $closing = strpos($line, '</span>');
 255          if (false !== $closing && (false === $opening || $closing < $opening)) {
 256              $line = substr_replace($line, '', $closing, 7);
 257          }
 258  
 259          // missing </span> tag at the end of line
 260          $opening = strpos($line, '<span');
 261          $closing = strpos($line, '</span>');
 262          if (false !== $opening && (false === $closing || $closing > $opening)) {
 263              $line .= '</span>';
 264          }
 265  
 266          return trim($line);
 267      }
 268  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1