CodeHelper.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
  3. use Symfony\Component\Templating\Helper\Helper;
  4. /*
  5. * This file is part of the Symfony framework.
  6. *
  7. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. /**
  13. * CodeHelper.
  14. *
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. */
  17. class CodeHelper extends Helper
  18. {
  19. protected $fileLinkFormat;
  20. protected $rootDir;
  21. /**
  22. * Constructor.
  23. *
  24. * @param string $fileLinkFormat The format for links to source files
  25. * @param string $rootDir The project root directory
  26. */
  27. public function __construct($fileLinkFormat, $rootDir)
  28. {
  29. $this->fileLinkFormat = null !== $fileLinkFormat ? $fileLinkFormat : ini_get('xdebug.file_link_format');
  30. $this->rootDir = str_replace('\\', '/', $rootDir).'/';
  31. }
  32. /**
  33. * Formats an array as a string.
  34. *
  35. * @param array $args The argument array
  36. *
  37. * @return string
  38. */
  39. public function formatArgsAsText($args)
  40. {
  41. $result = array();
  42. foreach ($args as $key => $value) {
  43. if (is_object($value)) {
  44. $formattedValue = sprintf("object('%s')", get_class($value));
  45. } elseif (is_array($value)) {
  46. $formattedValue = sprintf("array(%s)", $this->formatArgs($value));
  47. } elseif (is_string($value)) {
  48. $formattedValue = sprintf("'%s'", $value);
  49. } elseif (null === $value) {
  50. $formattedValue = 'null';
  51. } elseif (false === $value) {
  52. $formattedValue = 'false';
  53. } elseif (true === $value) {
  54. $formattedValue = 'true';
  55. } else {
  56. $formattedValue = $value;
  57. }
  58. $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
  59. }
  60. return implode(', ', $result);
  61. }
  62. public function abbrClass($class)
  63. {
  64. $parts = explode('\\', $class);
  65. $short = array_pop($parts);
  66. return sprintf("<abbr title=\"%s\">%s</abbr>", $class, $short);
  67. }
  68. public function abbrMethod($method)
  69. {
  70. list($class, $method) = explode('::', $method);
  71. $parts = explode('\\', $class);
  72. $short = array_pop($parts);
  73. return sprintf("<abbr title=\"%s\">%s</abbr>::%s", $class, $short, $method);
  74. }
  75. /**
  76. * Formats an array as a string.
  77. *
  78. * @param array $args The argument array
  79. *
  80. * @return string
  81. */
  82. public function formatArgs($args)
  83. {
  84. $result = array();
  85. foreach ($args as $key => $value) {
  86. if (is_object($value)) {
  87. $class = get_class($value);
  88. $parts = explode('\\', $class);
  89. $short = array_pop($parts);
  90. $formattedValue = sprintf("<em>object</em>(<abbr title=\"%s\">%s</abbr>)", $class, $short);
  91. } elseif (is_array($value)) {
  92. $formattedValue = sprintf("<em>array</em>(%s)", $this->formatArgs($value));
  93. } elseif (is_string($value)) {
  94. $formattedValue = sprintf("'%s'", $value);
  95. } elseif (null === $value) {
  96. $formattedValue = '<em>null</em>';
  97. } elseif (false === $value) {
  98. $formattedValue = '<em>false</em>';
  99. } elseif (true === $value) {
  100. $formattedValue = '<em>true</em>';
  101. } else {
  102. $formattedValue = $value;
  103. }
  104. $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
  105. }
  106. return implode(', ', $result);
  107. }
  108. /**
  109. * Returns an excerpt of a code file around the given line number.
  110. *
  111. * @param string $file A file path
  112. * @param int $line The selected line number
  113. *
  114. * @return string An HTML string
  115. */
  116. public function fileExcerpt($file, $line)
  117. {
  118. if (is_readable($file)) {
  119. $content = preg_split('#<br />#', highlight_file($file, true));
  120. $lines = array();
  121. for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; $i++) {
  122. $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'>'.$content[$i - 1].'</li>';
  123. }
  124. return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
  125. }
  126. }
  127. /**
  128. * Formats a file path.
  129. *
  130. * @param string $file An absolute file path
  131. * @param integer $line The line number
  132. * @param string $format The output format (txt or html)
  133. * @param string $text Use this text for the link rather than the file path
  134. *
  135. * @return string
  136. */
  137. public function formatFile($file, $line)
  138. {
  139. if (0 === strpos($file, $this->rootDir)) {
  140. $file = str_replace($this->rootDir, '', str_replace('\\', '/', $file));
  141. $file = sprintf('<abbr title="%s">kernel.root_dir</abbr>/%s', $this->rootDir, $file);
  142. }
  143. if (!$this->fileLinkFormat) {
  144. return "$file line $line";
  145. }
  146. $link = strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
  147. return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s line %s</a>', $link, $file, $line);
  148. }
  149. public function formatFileFromText($text)
  150. {
  151. $that = $this;
  152. return preg_replace_callback('/(called|defined) in (.*?)(?: on)? line (\d+)/', function ($match) use ($that) {
  153. return $match[1].' in '.$that->formatFile($match[2], $match[3]);
  154. }, $text);
  155. }
  156. /**
  157. * Returns the canonical name of this helper.
  158. *
  159. * @return string The canonical name
  160. */
  161. public function getName()
  162. {
  163. return 'code';
  164. }
  165. }