PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Symfony/Bundle/FrameworkBundle/Debug/ExceptionFormatter.php

https://github.com/come/symfony
PHP | 179 lines | 95 code | 22 blank | 62 comment | 28 complexity | d467ddc5b4a2ee34238455e391d2c554 MD5 | raw file
Possible License(s): ISC
  1. <?php
  2. namespace Symfony\Bundle\FrameworkBundle\Debug;
  3. use Symfony\Components\DependencyInjection\ContainerInterface;
  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. * ExceptionFormatter.
  14. *
  15. * @package Symfony
  16. * @subpackage Bundle_FrameworkBundle
  17. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  18. */
  19. class ExceptionFormatter
  20. {
  21. protected $container;
  22. /**
  23. * Constructor.
  24. *
  25. * @param ContainerInterface $container A Container instance
  26. */
  27. public function __construct(ContainerInterface $container)
  28. {
  29. $this->container = $container;
  30. }
  31. /**
  32. * Returns an array of exception traces.
  33. *
  34. * @param Exception $exception An Exception implementation instance
  35. * @param string $format The trace format (txt or html)
  36. *
  37. * @return array An array of traces
  38. */
  39. public function getTraces(\Exception $exception, $format = 'txt')
  40. {
  41. $traceData = $exception->getTrace();
  42. array_unshift($traceData, array(
  43. 'function' => '',
  44. 'file' => $exception->getFile() != null ? $exception->getFile() : null,
  45. 'line' => $exception->getLine() != null ? $exception->getLine() : null,
  46. 'args' => array(),
  47. ));
  48. $traces = array();
  49. if ($format == 'html') {
  50. $lineFormat = 'at <strong>%s%s%s</strong>(%s)<br />in <em>%s</em> line %s <a href="#" onclick="toggle(\'%s\'); return false;">...</a><br /><ul class="code" id="%s" style="display: %s">%s</ul>';
  51. } else {
  52. $lineFormat = 'at %s%s%s(%s) in %s line %s';
  53. }
  54. for ($i = 0, $count = count($traceData); $i < $count; $i++) {
  55. $line = isset($traceData[$i]['line']) ? $traceData[$i]['line'] : null;
  56. $file = isset($traceData[$i]['file']) ? $traceData[$i]['file'] : null;
  57. $args = isset($traceData[$i]['args']) ? $traceData[$i]['args'] : array();
  58. $traces[] = sprintf($lineFormat,
  59. (isset($traceData[$i]['class']) ? $traceData[$i]['class'] : ''),
  60. (isset($traceData[$i]['type']) ? $traceData[$i]['type'] : ''),
  61. $traceData[$i]['function'],
  62. $this->formatArgs($args, false, $format),
  63. $this->formatFile($file, $line, $format, null === $file ? 'n/a' : $file),
  64. null === $line ? 'n/a' : $line,
  65. 'trace_'.$i,
  66. 'trace_'.$i,
  67. $i == 0 ? 'block' : 'none',
  68. $this->fileExcerpt($file, $line)
  69. );
  70. }
  71. return $traces;
  72. }
  73. /**
  74. * Returns an excerpt of a code file around the given line number.
  75. *
  76. * @param string $file A file path
  77. * @param int $line The selected line number
  78. *
  79. * @return string An HTML string
  80. */
  81. protected function fileExcerpt($file, $line)
  82. {
  83. if (is_readable($file)) {
  84. $content = preg_split('#<br />#', highlight_file($file, true));
  85. $lines = array();
  86. for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; $i++) {
  87. $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'>'.$content[$i - 1].'</li>';
  88. }
  89. return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
  90. }
  91. }
  92. /**
  93. * Formats an array as a string.
  94. *
  95. * @param array $args The argument array
  96. * @param boolean $single
  97. * @param string $format The format string (html or txt)
  98. *
  99. * @return string
  100. */
  101. protected function formatArgs($args, $single = false, $format = 'html')
  102. {
  103. $result = array();
  104. $single and $args = array($args);
  105. foreach ($args as $key => $value) {
  106. if (is_object($value)) {
  107. $formattedValue = ($format == 'html' ? '<em>object</em>' : 'object').sprintf("('%s')", get_class($value));
  108. } else if (is_array($value)) {
  109. $formattedValue = ($format == 'html' ? '<em>array</em>' : 'array').sprintf("(%s)", $this->formatArgs($value));
  110. } else if (is_string($value)) {
  111. $formattedValue = ($format == 'html' ? sprintf("'%s'", $this->escape($value)) : "'$value'");
  112. } else if (null === $value) {
  113. $formattedValue = ($format == 'html' ? '<em>null</em>' : 'null');
  114. } else {
  115. $formattedValue = $value;
  116. }
  117. $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escape($key), $formattedValue);
  118. }
  119. return implode(', ', $result);
  120. }
  121. /**
  122. * Formats a file path.
  123. *
  124. * @param string $file An absolute file path
  125. * @param integer $line The line number
  126. * @param string $format The output format (txt or html)
  127. * @param string $text Use this text for the link rather than the file path
  128. *
  129. * @return string
  130. */
  131. protected function formatFile($file, $line, $format = 'html', $text = null)
  132. {
  133. if (null === $text) {
  134. $text = $file;
  135. }
  136. $linkFormat = $this->container->getParameterBag()->has('debug.file_link_format') ? $this->container->getParameter('debug.file_link_format') : ini_get('xdebug.file_link_format');
  137. if ('html' === $format && $file && $line && $linkFormat) {
  138. $link = strtr($linkFormat, array('%f' => $file, '%l' => $line));
  139. $text = sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', $link, $text);
  140. }
  141. return $text;
  142. }
  143. /**
  144. * Escapes a string value with html entities
  145. *
  146. * @param string $value
  147. *
  148. * @return string
  149. */
  150. protected function escape($value)
  151. {
  152. if (!is_string($value)) {
  153. return $value;
  154. }
  155. return htmlspecialchars($value, ENT_QUOTES, $this->container->getParameter('kernel.charset'));
  156. }
  157. }