HttpErrorsController::createDefault()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
namespace Mouf\Mvc\Splash\Controllers;
4
5
use Mouf\Html\HtmlElement\Scopable;
6
use Mouf\Html\HtmlElement\HtmlBlock;
7
use Mouf\Html\Template\TemplateInterface;
8
use Mouf\Html\HtmlElement\HtmlElementInterface;
9
use Mouf\Mvc\Splash\Exception\BadRequestException;
10
use Mouf\Mvc\Splash\HtmlResponse;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
use Zend\Diactoros\Response\JsonResponse;
14
15
/**
16
 * This class provides the default Splash behaviour when a HTTP 404 and HTTP 500 error is triggered.
17
 * Fill free to configure/override/replace this controller with your own if you want to provide
18
 * a customized HTTP 400/404/500 page.
19
 *
20
 * @author David Négrier
21
 */
22
class HttpErrorsController implements Http400HandlerInterface, Http404HandlerInterface, Http500HandlerInterface, Scopable
23
{
24
    /**
25
     * The template used by Splash for displaying error pages (HTTP 400, 404 and 500).
26
     *
27
     * @var TemplateInterface
28
     */
29
    private $template;
30
31
    /**
32
     * The content block the template will be written into.
33
     *
34
     * @var HtmlBlock
35
     */
36
    private $contentBlock;
37
38
    /**
39
     * Whether we should display exception stacktrace or not in HTTP 500.
40
     *
41
     * @var bool
42
     */
43
    private $debugMode = true;
44
45
    /**
46
     * Content block displayed in case of a 400 error.
47
     * If not set, a default block will be used instead.
48
     *
49
     * @var HtmlElementInterface
50
     */
51
    protected $contentFor400;
52
53
    /**
54
     * Content block displayed in case of a 404 error.
55
     * If not set, a default block will be used instead.
56
     *
57
     * @var HtmlElementInterface
58
     */
59
    protected $contentFor404;
60
61
    /**
62
     * Content block displayed in case of a 500 error.
63
     * If not set, a default block will be used instead.
64
     *
65
     * @var HtmlElementInterface
66
     */
67
    protected $contentFor500;
68
69
    protected $exception;
70
71
    /**
72
     * @param TemplateInterface $template     The template used by Splash for displaying error pages (HTTP 400, 404 and 500).
73
     * @param HtmlBlock         $contentBlock The content block the template will be written into.
74
     * @param bool              $debugMode    Whether we should display exception stacktrace or not in HTTP 500.
75
     */
76
    public function __construct(TemplateInterface $template, HtmlBlock $contentBlock, bool $debugMode = true)
77
    {
78
        $this->template = $template;
79
        $this->contentBlock = $contentBlock;
80
        $this->debugMode = $debugMode;
81
    }
82
83
    /**
84
     * Creates a default controller.
85
     *
86
     * @param bool $debugMode
87
     *
88
     * @return HttpErrorsController
89
     */
90
    public static function createDefault(bool $debugMode = true)
91
    {
92
        $block = new HtmlBlock();
93
        $template = new DefaultSplashTemplate($block);
94
95
        return new self($template, $block, $debugMode);
96
    }
97
98
    /**
99
     * This function is called when a HTTP 400 error is triggered by the user.
100
     *
101
     * @param ServerRequestInterface $request
102
     *
103
     * @return ResponseInterface
104
     */
105 View Code Duplication
    public function badRequest(BadRequestException $exception, ServerRequestInterface $request) : ResponseInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
106
    {
107
        $this->exception = $exception;
108
109
        $acceptType = $request->getHeader('Accept');
110
        if (is_array($acceptType) && count($acceptType) > 0 && strpos($acceptType[0], 'json') !== false) {
111
            return new JsonResponse(['error' => ['message' => 'Bad request sent', 'type' => 'bad_request']], 400);
112
        }
113
114
        if ($this->contentFor400) {
115
            $this->contentBlock = $this->contentFor400;
0 ignored issues
show
Documentation Bug introduced by
$this->contentFor400 is of type object<Mouf\Html\HtmlEle...t\HtmlElementInterface>, but the property $contentBlock was declared to be of type object<Mouf\Html\HtmlElement\HtmlBlock>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
116
        } else {
117
            $this->contentBlock->addFile(__DIR__.'/../../../../views/400.php', $this);
118
        }
119
120
        return HtmlResponse::create($this->template, 400);
121
    }
122
123
    /**
124
     * This function is called when a HTTP 404 error is triggered by the user.
125
     *
126
     * @param ServerRequestInterface $request
127
     *
128
     * @return ResponseInterface
129
     */
130 View Code Duplication
    public function pageNotFound(ServerRequestInterface $request) : ResponseInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
131
    {
132
        $acceptType = $request->getHeader('Accept');
133
        if (is_array($acceptType) && count($acceptType) > 0 && strpos($acceptType[0], 'json') !== false) {
134
            return new JsonResponse(['error' => ['message' => 'Page not found', 'type' => 'page_not_found']], 404);
135
        }
136
137
        if ($this->contentFor404) {
138
            $this->contentBlock->addHtmlElement($this->contentFor404);
139
        } else {
140
            $this->contentBlock->addFile(__DIR__.'/../../../../views/404.php', $this);
141
        }
142
143
        return HtmlResponse::create($this->template, 404);
144
    }
145
146
    /**
147
     * (non-PHPdoc).
148
     *
149
     * @see Mouf\Mvc\Splash\Controllers.Http500HandlerInterface::serverError()
150
     */
151
    public function serverError(\Throwable $exception, ServerRequestInterface $request) : ResponseInterface
152
    {
153
        $this->exception = $exception;
154
155
        $acceptType = $request->getHeader('Accept');
156
        if (is_array($acceptType) && count($acceptType) > 0 && strpos($acceptType[0], 'json') !== false) {
157
            return new JsonResponse(['error' => ['message' => $exception->getMessage(), 'type' => 'Exception', 'trace' => $this->debugMode ? $exception->getTraceAsString() : '']], 500);
158
        }
159
160
        if ($this->contentFor500) {
161
            $this->contentBlock->addHtmlElement($this->contentFor500);
162
        } else {
163
            $this->contentBlock->addFile(__DIR__.'/../../../../views/500.php', $this);
164
        }
165
166
        return HtmlResponse::create($this->template, 500);
167
    }
168
169
    /**
170
     * Includes the file (useful to load a view inside the Controllers scope).
171
     *
172
     * @param string $file
173
     */
174
    public function loadFile($file)
175
    {
176
        include $file;
177
    }
178
179
    /**
180
     * Content block displayed in case of a 400 error.
181
     * If not set, a default block will be used instead.
182
     *
183
     * @param HtmlElementInterface $contentFor400
184
     *
185
     * @return $this
186
     */
187
    public function setContentFor400(HtmlElementInterface $contentFor400)
188
    {
189
        $this->contentFor400 = $contentFor400;
190
191
        return $this;
192
    }
193
194
    /**
195
     * Content block displayed in case of a 404 error.
196
     * If not set, a default block will be used instead.
197
     *
198
     * @param HtmlElementInterface $contentFor404
199
     *
200
     * @return $this
201
     */
202
    public function setContentFor404(HtmlElementInterface $contentFor404)
203
    {
204
        $this->contentFor404 = $contentFor404;
205
206
        return $this;
207
    }
208
209
    /**
210
     * Content block displayed in case of a 500 error.
211
     * If not set, a default block will be used instead.
212
     *
213
     * @param HtmlElementInterface $contentFor500
214
     *
215
     * @return $this
216
     */
217
    public function setContentFor500(HtmlElementInterface $contentFor500)
218
    {
219
        $this->contentFor500 = $contentFor500;
220
221
        return $this;
222
    }
223
}
224