Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.59% covered (success)
94.59%
70 / 74
90.00% covered (success)
90.00%
9 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
RequestHandler
94.59% covered (success)
94.59%
70 / 74
90.00% covered (success)
90.00%
9 / 10
30.14
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 prepare
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
3
 setRequest
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getRequest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 request
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasRequest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 prepareHeaderAsString
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 prepareAsString
78.95% covered (success)
78.95%
15 / 19
0.00% covered (danger)
0.00%
0 / 1
9.76
 log
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
9
 getRequestTimestamp
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Debug\Handler;
15
16use Pop\Http\Server\Request;
17use Pop\Http\Uri;
18use Pop\Log\Logger;
19use Pop\Session\Session;
20
21/**
22 * Debug request handler class
23 *
24 * @category   Pop
25 * @package    Pop\Debug
26 * @author     Nick Sagona, III <dev@nolainteractive.com>
27 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
28 * @license    http://www.popphp.org/license     New BSD License
29 * @version    2.2.0
30 */
31class RequestHandler extends AbstractHandler
32{
33
34    /**
35     * Request
36     * @var ?Request
37     */
38    protected ?Request $request = null;
39
40    /**
41     * Request timestamp
42     * @var ?float
43     */
44    protected ?float $requestTimestamp = null;
45
46    /**
47     * Constructor
48     *
49     * Instantiate a request handler object
50     *
51     * @param ?Request $request
52     * @param ?string  $name
53     */
54    public function __construct(?Request $request = null, ?string $name = null, ?Logger $logger = null, array $loggingParams = [])
55    {
56        parent::__construct($name, $logger, $loggingParams);
57        if ($request === null) {
58            $request = new Request(new Uri());
59        }
60        $this->setRequest($request);
61
62        $this->requestTimestamp = microtime(true);
63    }
64
65    /**
66     * Prepare handler data for storage
67     *
68     * @return array
69     */
70    public function prepare(): array
71    {
72        Session::getInstance();
73
74        return [
75            'uri'       => $this->request->getUri()->getUri(),
76            'method'    => $this->request->getMethod(),
77            'headers'   => $this->request->getHeaders(),
78            'server'    => $this->request->getServer(),
79            'env'       => $this->request->getEnv(),
80            'get'       => $this->request->getQuery(),
81            'post'      => $this->request->getPost(),
82            'put'       => $this->request->getPut(),
83            'patch'     => $this->request->getPatch(),
84            'delete'    => $this->request->getDelete(),
85            'files'     => $this->request->getFiles(),
86            'cookie'    => (isset($_COOKIE)) ? $_COOKIE : [],
87            'session'   => (isset($_SESSION)) ? $_SESSION : [],
88            'raw'       => $this->request->getRawData(),
89            'parsed'    => $this->request->getParsedData(),
90            'timestamp' => number_format($this->requestTimestamp, 5, '.', ''),
91            'elapsed'   => number_format((microtime(true) - $this->requestTimestamp), 5, '.', '')
92        ];
93    }
94
95    /**
96     * Set request
97     *
98     * @param  Request $request
99     * @return RequestHandler
100     */
101    public function setRequest(Request $request): RequestHandler
102    {
103        $this->request = $request;
104        return $this;
105    }
106
107    /**
108     * Get request
109     *
110     * @return Request
111     */
112    public function getRequest(): Request
113    {
114        return $this->request;
115    }
116
117    /**
118     * Get request (alias)
119     *
120     * @return Request
121     */
122    public function request(): Request
123    {
124        return $this->request;
125    }
126
127    /**
128     * Has request
129     *
130     * @return bool
131     */
132    public function hasRequest(): bool
133    {
134        return ($this->request !== null);
135    }
136
137    /**
138     * Prepare header string
139     *
140     * @return string
141     */
142    public function prepareHeaderAsString(): string
143    {
144        $string  = ((!empty($this->name)) ? $this->name . ' ' : '') . 'Request Handler';
145        $string .= PHP_EOL . str_repeat('=', strlen($string)) . PHP_EOL;
146
147        return $string;
148    }
149
150    /**
151     * Prepare handler data as string
152     *
153     * @return string
154     */
155    public function prepareAsString(): string
156    {
157        $string = '';
158        if (!empty($this->request->getUri()) && !empty($this->request->getUri()->getUri())) {
159            $requestData = $this->prepare();
160
161            $string .= $this->request->getMethod() . ' ' . $this->request->getUri()->getUri() . ' [' .
162                $requestData['timestamp'] . ' (' . $requestData['elapsed'] . ')]' . PHP_EOL . PHP_EOL;
163
164            foreach ($requestData as $key => $data) {
165                if (is_array($data) && (count($data) > 0)) {
166                    $string .= str_replace('DATA', '', strtoupper($key)) . ":" . PHP_EOL;
167                    $string .= str_repeat('-', (strlen(str_replace('DATA', '', strtoupper($key))) + 1)) . PHP_EOL;
168                    foreach ($data as $k => $v) {
169                        $string .= $k . ": " . ((is_array($v)) ? http_build_query($v) : $v) . PHP_EOL;
170                    }
171                    $string .= PHP_EOL;
172                }
173            }
174            if (!empty($this->request->getRawData())) {
175                $string .= "RAW:" . PHP_EOL;
176                $string .= "----" . PHP_EOL;
177                $string .= $this->request->getRawData() . PHP_EOL;
178            }
179        } else {
180            $string .= "No Request URI Detected." . PHP_EOL;
181        }
182
183        $string .= PHP_EOL;
184
185        return $string;
186    }
187
188    /**
189     * Trigger handler logging
190     *
191     * @throws Exception
192     * @return void
193     */
194    public function log(): void
195    {
196        if (($this->hasLogger()) && ($this->hasLoggingParams())) {
197            $logLevel  = $this->loggingParams['level'] ?? null;
198            $useContext = $this->loggingParams['context'] ?? null;
199            $timeLimit = $this->loggingParams['limit'] ?? null;
200
201            if ($logLevel !== null) {
202                $context     = [];
203                $requestData = $this->prepare();
204                if ($timeLimit !== null) {
205                    $elapsedTime = $requestData['elapsed'];
206                    if ($elapsedTime >= $timeLimit) {
207                        $this->logger->log($logLevel, 'The request \'' . $this->request->getUri()->getUri() .
208                            '\' has exceeded the time limit of ' . $timeLimit . ' second(s) by ' .
209                            $elapsedTime - $timeLimit . ' second(s). The request was a total of ' . $elapsedTime . ' second(s).',
210                            $context
211                        );
212                    }
213                } else {
214                    $context['request'] = (($useContext !== null) && (strtolower($useContext) == 'text')) ?
215                        $this->prepareAsString() : $this->prepare();
216
217                    if (is_string($useContext)) {
218                        $context['format'] = $useContext;
219                    }
220
221                    $this->logger->log($logLevel, "The request '" .  $this->request->getUri()->getUri() . "' was triggered.", $context);
222                }
223            } else {
224                throw new Exception('Error: The log level parameter was not set.');
225            }
226        }
227    }
228
229    /**
230     * Get request timestamp
231     *
232     * @return float
233     */
234    public function getRequestTimestamp(): float
235    {
236        return $this->requestTimestamp;
237    }
238
239}