Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
ExceptionHandler
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
9 / 9
16
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setVerbose
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isVerbose
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addException
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 hasExceptions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExceptions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 prepare
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
3
 prepareMessage
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 log
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2/**
3 * Pop PHP Framework (https://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@noladev.com>
7 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
8 * @license    https://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Debug\Handler;
15
16use Pop\Log\Logger;
17
18/**
19 * Debug exception handler class
20 *
21 * @category   Pop
22 * @package    Pop\Debug
23 * @author     Nick Sagona, III <dev@noladev.com>
24 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
25 * @license    https://www.popphp.org/license     New BSD License
26 * @version    3.0.0
27 */
28class ExceptionHandler extends AbstractHandler
29{
30
31    /**
32     * Verbose flag
33     * @var bool
34     */
35    protected bool $verbose = false;
36
37    /**
38     * Constructor
39     *
40     * Instantiate a handler object
41     *
42     * @param bool    $verbose
43     * @param ?string $name
44     * @param ?Logger $logger
45     * @param array   $loggingParams
46     */
47    public function __construct(bool $verbose = false, ?string $name = null, ?Logger $logger = null, array $loggingParams = [])
48    {
49        parent::__construct($name, $logger, $loggingParams);
50        $this->setVerbose($verbose);
51    }
52
53    /**
54     * Set verbose
55     *
56     * @param  bool $verbose
57     * @return ExceptionHandler
58     */
59    public function setVerbose(bool $verbose = true): ExceptionHandler
60    {
61        $this->verbose = $verbose;
62        return $this;
63    }
64
65    /**
66     * Is verbose
67     *
68     * @return bool
69     */
70    public function isVerbose(): bool
71    {
72        return $this->verbose;
73    }
74
75
76    /**
77     * Add exception
78     *
79     * @param  \Exception $exception
80     * @return ExceptionHandler
81     */
82    public function addException(\Exception $exception): ExceptionHandler
83    {
84        $this->data[] = ['exception' => $exception, 'timestamp' => (string)microtime(true)];
85        return $this;
86    }
87
88    /**
89     * Determine if the handler has exceptions
90     *
91     * @return bool
92     */
93    public function hasExceptions(): bool
94    {
95        return (count($this->data) > 0);
96    }
97
98    /**
99     * Get exceptions
100     *
101     * @return array
102     */
103    public function getExceptions(): array
104    {
105        return $this->data;
106    }
107
108    /**
109     * Prepare handler data for storage
110     *
111     * @return array
112     */
113    public function prepare(): array
114    {
115        if ($this->isVerbose()) {
116            $exceptions = [];
117            foreach ($this->data as $exception) {
118                $exceptions[] = [
119                    'exception' => get_class($exception['exception']),
120                    'code'      => $exception['exception']->getCode(),
121                    'line'      => $exception['exception']->getLine(),
122                    'file'      => $exception['exception']->getFile(),
123                    'message'   => $exception['exception']->getMessage(),
124                    'trace'     => $exception['exception']->getTrace(),
125                    'timestamp' => $exception['timestamp'],
126                ];
127            }
128            return $exceptions;
129        } else {
130            return $this->data;
131        }
132    }
133
134    /**
135     * Prepare handler message
136     *
137     * @param  ?array $context
138     * @return string
139     */
140    public function prepareMessage(?array $context = null): string
141    {
142        if ($context === null) {
143            $context = $this->prepare();
144        }
145
146        return (count($context) > 1) ?
147            '(' . count($context) . ') exceptions have been thrown.' :
148            '(1) exception has been thrown.';
149    }
150
151    /**
152     * Trigger handler logging
153     *
154     * @throws Exception
155     * @return void
156     */
157    public function log(): void
158    {
159        if (($this->hasLogger()) && ($this->hasLoggingParams())) {
160            $logLevel = $this->loggingParams['level'] ?? null;
161
162            if ($logLevel !== null) {
163                $context = $this->prepare();
164                $this->logger->log($logLevel, $this->prepareMessage($context), $context);
165            } else {
166                throw new Exception('Error: The log level parameter was not set.');
167            }
168        }
169    }
170
171}