PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/LimeError.php

http://github.com/bschussek/lime
PHP | 236 lines | 121 code | 24 blank | 91 comment | 19 complexity | f1f6fb2b21656910e598d13064d1b0b3 MD5 | raw file
Possible License(s): ISC
  1. <?php
  2. /*
  3. * This file is part of the Lime test framework.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. * (c) Bernhard Schussek <bernhard.schussek@symfony-project.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. /**
  12. * Stores an error and optionally its trace.
  13. *
  14. * This class is similar to PHP's native Exception class, but is guaranteed
  15. * to be serializable. The native Exception class is not serializable if the
  16. * traces contain circular references between objects.
  17. *
  18. * @package Lime
  19. * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  20. * @version SVN: $Id: LimeError.php 23701 2009-11-08 21:23:40Z bschussek $
  21. */
  22. class LimeError implements Serializable
  23. {
  24. private
  25. $type = null,
  26. $message = null,
  27. $file = null,
  28. $line = null,
  29. $trace = null,
  30. $invocationTrace = null;
  31. /**
  32. * Creates a new instance and copies the data from an exception.
  33. *
  34. * @param Exception $exception
  35. * @return LimeError
  36. */
  37. public static function fromException(Exception $exception, $file = null, $line = null, $trace = null)
  38. {
  39. if (is_null($file))
  40. {
  41. $file = $exception->getFile();
  42. }
  43. if (is_null($line))
  44. {
  45. $line = $exception->getLine();
  46. }
  47. if (is_null($trace))
  48. {
  49. $trace = $exception->getTrace();
  50. }
  51. $invocationTrace = array();
  52. if ($exception instanceof LimeMockException)
  53. {
  54. $invocationTrace = iterator_to_array($exception->getInvocationTrace());
  55. }
  56. return new self($exception->getMessage(), $file, $line, get_class($exception), $trace, $invocationTrace);
  57. }
  58. /**
  59. * Constructor.
  60. *
  61. * @param string $message The error message
  62. * @param string $file The file where the error occurred
  63. * @param integer $line The line where the error occurred
  64. * @param string $type The error type, f.i. "Fatal Error"
  65. * @param array $trace The traces of the error
  66. */
  67. public function __construct($message, $file, $line, $type = 'Error', array $trace = array(), array $invocationTrace = array())
  68. {
  69. // Remove all the parts from the trace that have been generated inside
  70. // a mock object. In the end, only the traces that led to the erroneous
  71. // method call remain there.
  72. // It would be nice if we could do that inside LimeMockException, but we
  73. // can't because getTrace() is final.
  74. while (count($trace) > 0 && isset($trace[0]['class']) && preg_match('/^Mock_\w+_\w{8}$/', $trace[0]['class']))
  75. {
  76. $file = isset($trace[0]['file']) ? $trace[0]['file'] : null;
  77. $line = isset($trace[0]['line']) ? $trace[0]['line'] : null;
  78. array_shift($trace);
  79. }
  80. // Remove all the parts from the trace that have been generated inside
  81. // the LimeTest object. Like above.
  82. while (count($trace) > 0 && isset($trace[0]['class']) && $trace[0]['class'] == 'LimeTest')
  83. {
  84. $file = isset($trace[0]['file']) ? $trace[0]['file'] : null;
  85. $line = isset($trace[0]['line']) ? $trace[0]['line'] : null;
  86. array_shift($trace);
  87. }
  88. // Remove all the parts from the trace that have been generated in the
  89. // annotation support, the CLI etc. They are irrelevant for the testing
  90. // developer.
  91. for ($i = 0, $c = count($trace); $i < $c; ++$i)
  92. {
  93. if (strpos($trace[$i]['function'], '__lime_annotation_') === 0)
  94. {
  95. for (; $i < $c; ++$i)
  96. {
  97. unset($trace[$i]);
  98. }
  99. }
  100. }
  101. // Remove "~annotated" suffixes
  102. foreach ($trace as $t_trace)
  103. {
  104. if (isset($_trace['file']))
  105. {
  106. $_trace['file'] = preg_replace('/~annotated$/', '', $_trace['file']);
  107. }
  108. }
  109. $file = preg_replace('/~annotated$/', '', $file);
  110. $this->message = $message;
  111. $this->file = $file;
  112. $this->line = $line;
  113. $this->type = $type;
  114. $this->trace = $trace;
  115. $this->invocationTrace = $invocationTrace;
  116. }
  117. /**
  118. * Returns the error type.
  119. *
  120. * @return string
  121. */
  122. public function getType()
  123. {
  124. return $this->type;
  125. }
  126. /**
  127. * Returns the error message.
  128. *
  129. * @return string
  130. */
  131. public function getMessage()
  132. {
  133. return $this->message;
  134. }
  135. /**
  136. * Returns the file where the error occurred.
  137. *
  138. * @return string
  139. */
  140. public function getFile()
  141. {
  142. return $this->file;
  143. }
  144. /**
  145. * Returns the line where the error occurred.
  146. *
  147. * @return integer
  148. */
  149. public function getLine()
  150. {
  151. return $this->line;
  152. }
  153. /**
  154. * Returns the trace of the error.
  155. *
  156. * @return array
  157. */
  158. public function getTrace()
  159. {
  160. return $this->trace;
  161. }
  162. /**
  163. * Returns the invocation trace of mock errors.
  164. *
  165. * @return array
  166. */
  167. public function getInvocationTrace()
  168. {
  169. return $this->invocationTrace;
  170. }
  171. /**
  172. * Serializes the error.
  173. *
  174. * @see Serializable#serialize()
  175. * @return string The serialized error content
  176. */
  177. public function serialize()
  178. {
  179. $traces = $this->trace;
  180. foreach ($traces as &$trace)
  181. {
  182. if (array_key_exists('args', $trace))
  183. {
  184. foreach ($trace['args'] as &$value)
  185. {
  186. // TODO: This should be improved. Maybe we can check for recursions
  187. // and only exclude duplicate objects from the trace
  188. if (is_object($value))
  189. {
  190. // replace object by class name
  191. $value = sprintf('object (%s) (...)', get_class($value));
  192. }
  193. else if (is_array($value))
  194. {
  195. $value = 'array(...)';
  196. }
  197. }
  198. }
  199. }
  200. return serialize(array($this->file, $this->line, $this->message, $traces, $this->type, $this->invocationTrace));
  201. }
  202. /**
  203. * Unserializes an error.
  204. *
  205. * @see Serializable#unserialize()
  206. * @param string $data The serialized error content
  207. */
  208. public function unserialize($data)
  209. {
  210. list($this->file, $this->line, $this->message, $this->trace, $this->type, $this->invocationTrace) = unserialize($data);
  211. }
  212. }