Hoa central
Exception.php
Go to the documentation of this file.
1 <?php
2 
38 
39 use Hoa\Core;
40 
51 class Idle extends \Exception
52 {
58  protected $_tmpArguments = null;
59 
65  protected $_arguments = null;
66 
72  protected $_trace = null;
73 
79  protected $_previous = null;
80 
86  protected $_rawMessage = null;
87 
88 
89 
102  public function __construct(
103  $message,
104  $code = 0,
105  $arguments = [],
106  \Exception $previous = null
107  ) {
108  $this->_tmpArguments = $arguments;
109  parent::__construct($message, $code, $previous);
110  $this->_rawMessage = $message;
111  $this->message = @vsprintf($message, $this->getArguments());
112 
113  return;
114  }
115 
122  public function getBacktrace()
123  {
124  if (null === $this->_trace) {
125  $this->_trace = $this->getTrace();
126  }
127 
128  return $this->_trace;
129  }
130 
137  public function getPreviousThrow()
138  {
139  if (null === $this->_previous) {
140  $this->_previous = $this->getPrevious();
141  }
142 
143  return $this->_previous;
144  }
145 
151  public function getArguments()
152  {
153  if (null === $this->_arguments) {
154  $arguments = $this->_tmpArguments;
155 
156  if (!is_array($arguments)) {
157  $arguments = [$arguments];
158  }
159 
160  foreach ($arguments as $key => &$value) {
161  if (null === $value) {
162  $value = '(null)';
163  }
164  }
165 
166  $this->_arguments = $arguments;
167  unset($this->_tmpArguments);
168  }
169 
170  return $this->_arguments;
171  }
172 
178  public function getRawMessage()
179  {
180  return $this->_rawMessage;
181  }
182 
188  public function getFormattedMessage()
189  {
190  return $this->getMessage();
191  }
192 
198  public function getFrom()
199  {
200  $trace = $this->getBacktrace();
201  $from = '{main}';
202 
203  if (!empty($trace)) {
204  $t = $trace[0];
205  $from = '';
206 
207  if (isset($t['class'])) {
208  $from .= $t['class'] . '::';
209  }
210 
211  if (isset($t['function'])) {
212  $from .= $t['function'] . '()';
213  }
214  }
215 
216  return $from;
217  }
218 
225  public function raise($previous = false)
226  {
227  $message = $this->getFormattedMessage();
228  $trace = $this->getBacktrace();
229  $file = '/dev/null';
230  $line = -1;
231  $pre = $this->getFrom();
232 
233  if (!empty($trace)) {
234  $file = isset($trace['file']) ? $trace['file'] : null;
235  $line = isset($trace['line']) ? $trace['line'] : null;
236  }
237 
238  $pre .= ': ';
239 
240  try {
241  $out =
242  $pre . '(' . $this->getCode() . ') ' . $message . "\n" .
243  'in ' . $this->getFile() . ' at line ' .
244  $this->getLine() . '.';
245  } catch (\Exception $e) {
246  $out =
247  $pre . '(' . $this->getCode() . ') ' . $message . "\n" .
248  'in ' . $file . ' around line ' . $line . '.';
249  }
250 
251  if (true === $previous &&
252  null !== $previous = $this->getPreviousThrow()) {
253  $out .=
254  "\n\n" . ' ⬇ ' . "\n\n" .
255  'Nested exception (' . get_class($previous) . '):' . "\n" .
256  ($previous instanceof self
257  ? $previous->raise(true)
258  : $previous->getMessage());
259  }
260 
261  return $out;
262  }
263 
271  public static function uncaught($exception)
272  {
273  if (!($exception instanceof self)) {
274  throw $exception;
275  }
276 
277  while (0 < ob_get_level()) {
278  ob_end_flush();
279  }
280 
281  echo
282  'Uncaught exception (' . get_class($exception) . '):' . "\n" .
283  $exception->raise(true);
284 
285  return;
286  }
287 
301  public static function error($errno, $errstr, $errfile, $errline)
302  {
303  if (0 === ($errno & error_reporting())) {
304  return;
305  }
306 
307  $trace = debug_backtrace();
308  array_shift($trace);
309  array_shift($trace);
310 
311  throw new Error($errstr, $errno, $errfile, $errline, $trace);
312  }
313 
319  public function __toString()
320  {
321  return $this->raise();
322  }
323 }
324 
333 class Exception extends Idle implements Core\Event\Source
334 {
347  public function __construct(
348  $message,
349  $code = 0,
350  $arguments = [],
351  $previous = null
352  ) {
353  parent::__construct($message, $code, $arguments, $previous);
354 
355  if (false === Core\Event::eventExists('hoa://Event/Exception')) {
356  Core\Event::register('hoa://Event/Exception', __CLASS__);
357  }
358 
359  $this->send();
360 
361  return;
362  }
363 
369  public function send()
370  {
371  Core\Event::notify(
372  'hoa://Event/Exception',
373  $this,
374  new Core\Event\Bucket($this)
375  );
376 
377  return;
378  }
379 }
380 
389 class Error extends Exception
390 {
400  public function __construct(
401  $message,
402  $code,
403  $file,
404  $line,
405  Array $trace = []
406  ) {
407  $this->file = $file;
408  $this->line = $line;
409  $this->_trace = $trace;
410 
411  parent::__construct($message, $code);
412 
413  return;
414  }
415 }
416 
425 class Group
426  extends Exception
427  implements \ArrayAccess, \IteratorAggregate, \Countable
428 {
434  protected $_group = null;
435 
436 
437 
447  public function __construct(
448  $message,
449  $code = 0,
450  $arguments = [],
451  \Exception $previous = null
452  ) {
453  parent::__construct($message, $code, $arguments, $previous);
454  $this->_group = new \SplStack();
455  $this->beginTransaction();
456 
457  return;
458  }
459 
466  public function raise($previous = false)
467  {
468  $out = parent::raise($previous);
469 
470  if (0 >= count($this)) {
471  return $out;
472  }
473 
474  $out .= "\n\n" . 'Contains the following exceptions:';
475 
476  foreach ($this as $exception) {
477  $out .= "\n\n" . ' • ' . str_replace(
478  "\n",
479  "\n" . ' ',
480  $exception->raise($previous)
481  );
482  }
483 
484  return $out;
485  }
486 
492  public function beginTransaction()
493  {
494  $this->_group->push(new \ArrayObject());
495 
496  return $this;
497  }
498 
504  public function rollbackTransaction()
505  {
506  if (1 >= count($this->_group)) {
507  return $this;
508  }
509 
510  $this->_group->pop();
511 
512  return $this;
513  }
514 
520  public function commitTransaction()
521  {
522  if (false === $this->hasUncommittedExceptions()) {
523  return $this;
524  }
525 
526  foreach ($this->_group->pop() as $index => $exception) {
527  $this->offsetSet($index, $exception);
528  }
529 
530  return $this;
531  }
532 
538  public function hasUncommittedExceptions()
539  {
540  return
541  1 < count($this->_group) &&
542  0 < count($this->_group->top());
543  }
544 
551  public function offsetExists($index)
552  {
553  foreach ($this->_group as $group) {
554  if (isset($group[$index])) {
555  return true;
556  }
557  }
558 
559  return false;
560  }
561 
568  public function offsetGet($index)
569  {
570  foreach ($this->_group as $group) {
571  if (isset($group[$index])) {
572  return $group[$index];
573  }
574  }
575 
576  return null;
577  }
578 
586  public function offsetSet($index, $exception)
587  {
588  if (!($exception instanceof \Exception)) {
589  return null;
590  }
591 
592  $group = $this->_group->top();
593 
594  if (null === $index ||
595  true === is_int($index)) {
596  $group[] = $exception;
597  } else {
598  $group[$index] = $exception;
599  }
600 
601  return;
602  }
603 
610  public function offsetUnset($index)
611  {
612  foreach ($this->_group as $group) {
613  if (isset($group[$index])) {
614  unset($group[$index]);
615  }
616  }
617 
618  return;
619  }
620 
626  public function getExceptions()
627  {
628  return $this->_group->bottom();
629  }
630 
636  public function getIterator()
637  {
638  return $this->getExceptions()->getIterator();
639  }
640 
646  public function count()
647  {
648  return count($this->_group->bottom());
649  }
650 }
651 
655 class_alias('Hoa\Core\Exception\Exception', 'Hoa\Core\Exception');
static error($errno, $errstr, $errfile, $errline)
Definition: Exception.php:301
__construct($message, $code, $file, $line, Array $trace=[])
Definition: Exception.php:400
offsetSet($index, $exception)
Definition: Exception.php:586
static uncaught($exception)
Definition: Exception.php:271
__construct($message, $code=0, $arguments=[], $previous=null)
Definition: Exception.php:347
__construct($message, $code=0, $arguments=[],\Exception $previous=null)
Definition: Exception.php:102
__construct($message, $code=0, $arguments=[],\Exception $previous=null)
Definition: Exception.php:447