Failed Conditions
Push — master ( 141f54...437209 )
by Atanas
03:01
created

ErrorHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 3
c 1
b 0
f 1
nc 1
nop 3
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
1
<?php
2
/**
3
 * @package   WPEmerge
4
 * @author    Atanas Angelov <[email protected]>
5
 * @copyright 2017-2019 Atanas Angelov
6
 * @license   https://www.gnu.org/licenses/gpl-2.0.html GPL-2.0
7
 * @link      https://wpemerge.com/
8
 */
9
10
namespace WPEmerge\Exceptions;
11
12
use Exception as PhpException;
13
use Psr\Http\Message\ResponseInterface;
14
use Whoops\RunInterface;
15
use WPEmerge\Csrf\InvalidCsrfTokenException;
16
use WPEmerge\Requests\RequestInterface;
17
use WPEmerge\Responses\ResponseService;
18
use WPEmerge\Routing\NotFoundException;
19
use WPEmerge\Support\Arr;
20
21
class ErrorHandler implements ErrorHandlerInterface {
22
	/**
23
	 * Response service.
24
	 *
25
	 * @var ResponseService
26
	 */
27
	protected $response_service = null;
28
29
	/**
30
	 * Pretty handler.
31
	 *
32
	 * @var RunInterface|null
33
	 */
34
	protected $whoops = null;
35
36
	/**
37
	 * Whether debug mode is enabled.
38
	 *
39
	 * @var boolean
40
	 */
41
	protected $debug = false;
42
43
	/**
44
	 * Constructor.
45
	 *
46
	 * @codeCoverageIgnore
47
	 * @param ResponseService   $response_service
48
	 * @param RunInterface|null $whoops
49
	 * @param boolean           $debug
50
	 */
51
	public function __construct( $response_service, $whoops, $debug = false ) {
52
		$this->response_service = $response_service;
53
		$this->whoops = $whoops;
54
		$this->debug = $debug;
55
	}
56
57
	/**
58
	 * {@inheritDoc}
59
	 * @codeCoverageIgnore
60
	 */
61
	public function register() {
62
		if ( $this->debug && $this->whoops !== null ) {
63
			$this->whoops->register();
64
		}
65
	}
66
67
	/**
68
	 * {@inheritDoc}
69
	 * @codeCoverageIgnore
70
	 */
71
	public function unregister() {
72
		if ( $this->debug && $this->whoops !== null ) {
73
			$this->whoops->unregister();
74
		}
75
	}
76
77
	/**
78
	 * Convert an exception to a ResponseInterface instance if possible.
79
	 *
80
	 * @param  PhpException            $exception
81
	 * @return ResponseInterface|false
82
	 */
83 2
	protected function toResponse( $exception ) {
84
		// @codeCoverageIgnoreStart
85
		if ( $exception instanceof InvalidCsrfTokenException ) {
86
			wp_nonce_ays( '' );
87
		}
88
		// @codeCoverageIgnoreEnd
89
90 2
		if ( $exception instanceof NotFoundException ) {
91 1
			return $this->response_service->error( 404 );
92
		}
93
94 1
		return false;
95
	}
96
97
	/**
98
	 * Convert an exception to a debug ResponseInterface instance if possible.
99
	 *
100
	 * @throws PhpException
101
	 * @param  RequestInterface  $request
102
	 * @param  PhpException      $exception
103
	 * @return ResponseInterface
104
	 */
105 3
	protected function toDebugResponse( RequestInterface $request, PhpException $exception ) {
106 3
		if ( $request->isAjax() ) {
107 1
			return $this->response_service->json( [
108 1
				'message' => $exception->getMessage(),
109 1
				'exception' => get_class( $exception ),
110 1
				'file' => $exception->getFile(),
111 1
				'line' => $exception->getLine(),
112
				'trace' => array_map( function ( $trace ) {
113 1
					return Arr::except( $trace, ['args'] );
114 1
				}, $exception->getTrace() ),
115 1
			] )->withStatus( 500 );
116
		}
117
118 2
		if ( $this->whoops !== null ) {
119 1
			return $this->toPrettyErrorResponse( $exception );
120
		}
121
122 1
		throw $exception;
123
	}
124
125
	/**
126
	 * Convert an exception to a pretty error response.
127
	 *
128
	 * @codeCoverageIgnore
129
	 * @param  PhpException      $exception
130
	 * @return ResponseInterface
131
	 */
132
	protected function toPrettyErrorResponse( $exception ) {
133
		$method = RunInterface::EXCEPTION_HANDLER;
134
		ob_start();
135
		$this->whoops->$method( $exception );
136
		$response = ob_get_clean();
137
		return $this->response_service->output( $response )->withStatus( 500 );
138
	}
139
140
	/**
141
	 * {@inheritDoc}
142
	 * @throws PhpException
143
	 */
144 5
	public function getResponse( RequestInterface $request, PhpException $exception ) {
145 5
		$response = $this->toResponse( $exception );
146
147 5
		if ( $response !== false ) {
148 1
			return $response;
149
		}
150
151 4
		if ( ! defined( 'WPEMERGE_TEST_DIR' ) ) {
152
			// @codeCoverageIgnoreStart
153
			// Only log errors if we are not running the WP Emerge test suite.
154
			error_log( $exception );
155
			// @codeCoverageIgnoreEnd
156
		}
157
158 4
		if ( ! $this->debug ) {
159 1
			return $this->response_service->error( 500 );
160
		}
161
162 3
		return $this->toDebugResponse( $request, $exception );
163
	}
164
}
165