Completed
Push — 4-cactus ( 35f1a2...d71008 )
by Stefano
16s queued 11s
created

plugins/BEdita/API/src/Error/ExceptionRenderer.php (1 issue)

1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2016 ChannelWeb Srl, Chialab Srl
5
 *
6
 * This file is part of BEdita: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
12
 */
13
14
namespace BEdita\API\Error;
15
16
use Cake\Core\Configure;
17
use Cake\Core\Exception\Exception as CakeException;
18
use Cake\Error\ExceptionRenderer as CakeExceptionRenderer;
19
use Cake\Http\ServerRequest;
20
use Cake\Utility\Hash;
21
22
/**
23
 * Exception renderer.
24
 *
25
 * @since 4.0.0
26
 */
27
class ExceptionRenderer extends CakeExceptionRenderer
28
{
29
    /**
30
     * {@inheritDoc}
31
     *
32
     * @codeCoverageIgnore
33
     */
34
    public function __construct(\Exception $exception)
35
    {
36
        parent::__construct($exception);
37
38
        ServerRequest::addDetector('html', [
39
            'accept' => ['text/html', 'application/xhtml+xml', 'application/xhtml', 'text/xhtml'],
40
        ]);
41
    }
42
43
    /**
44
     * {@inheritDoc}
45
     */
46
    public function render()
47
    {
48
        $isDebug = Configure::read('debug');
49
50
        $status = $this->_code($this->error);
51
        $title = $this->_message($this->error, $status);
52
        $detail = $this->errorDetail($this->error);
53
        $code = $this->appErrorCode($this->error);
54
        $trace = null;
55
        if ($isDebug) {
56
            $trace = explode("\n", $this->_unwrap($this->error)->getTraceAsString());
57
        }
58
59
        $this->controller->loadComponent('RequestHandler');
60
        $this->controller->RequestHandler->setConfig('viewClassMap.json', 'BEdita/API.JsonApi');
61
        $this->controller->loadComponent('BEdita/API.JsonApi', [
62
            'contentType' => $this->controller->request->is('json') ? 'json' : null,
0 ignored issues
show
The method is() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

62
            'contentType' => $this->controller->request->/** @scrutinizer ignore-call */ is('json') ? 'json' : null,

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
63
            'checkMediaType' => $this->controller->request->is('jsonapi'),
64
        ]);
65
66
        $this->controller->JsonApi->error($status, $title, $detail, $code, array_filter(compact('trace')));
67
        $this->controller->RequestHandler->renderAs($this->controller, 'jsonapi');
68
69
        return parent::render();
70
    }
71
72
    /**
73
     * {@inheritDoc}
74
     */
75
    protected function _message(\Exception $error, $status)
76
    {
77
        $message = parent::_message($error, $status);
78
        if (empty($message) && $error instanceof CakeException) {
79
            $errorAttributes = $error->getAttributes();
80
            if (!empty($errorAttributes['title'])) {
81
                $message = $errorAttributes['title'];
82
            }
83
        }
84
85
        return $message;
86
    }
87
88
    /**
89
     * Human readable error detail from error attributes
90
     * In case of 'detail' array, format like this is expected
91
     *  [
92
     *    ['field1' => ['unique' => 'The provided value is invalid']],
93
     *    ['field2' => [...]],
94
     *  ],
95
     *
96
     *
97
     *
98
     * @param \Exception $error Exception.
99
     * @return string Error message
100
     */
101
    protected function errorDetail(\Exception $error)
102
    {
103
        if (!$error instanceof CakeException) {
104
            return '';
105
        }
106
107
        $errorAttributes = $error->getAttributes();
108
        if (empty($errorAttributes['detail'])) {
109
            return '';
110
        }
111
        $d = $errorAttributes['detail'];
112
        if (is_string($d)) {
113
            return $d;
114
        }
115
116
        $res = '';
117
        if (is_array($d)) {
118
            $d = Hash::flatten($d);
119
            $res = implode(
120
                ' ',
121
                array_map(
122
                    function ($key, $val) {
123
                        return sprintf('[%s]: %s', $key, $val);
124
                    },
125
                    array_keys($d),
126
                    array_values($d)
127
                )
128
            );
129
        }
130
131
        return $res;
132
    }
133
134
    /**
135
     * Application specific error code.
136
     *
137
     * @param \Exception $error Exception.
138
     * @return string Error code
139
     */
140
    protected function appErrorCode(\Exception $error)
141
    {
142
        if (!$error instanceof CakeException) {
143
            return '';
144
        }
145
146
        $errorAttributes = $error->getAttributes();
147
        if (empty($errorAttributes['code']) || !is_scalar($errorAttributes['code'])) {
148
            return '';
149
        }
150
151
        return (string)$errorAttributes['code'];
152
    }
153
154
    /**
155
     * {@inheritDoc}
156
     */
157
    protected function _outputMessageSafe($template)
158
    {
159
        $this->controller
160
            ->viewBuilder()
161
            ->setClassName('BEdita\API\View\JsonApiView');
162
163
        $view = $this->controller->createView();
164
165
        return $this->controller->response->withStringBody($view->render());
166
    }
167
168
    /**
169
     * {@inheritDoc}
170
     */
171
    protected function _template(\Exception $exception, $method, $status)
172
    {
173
        return $this->template = 'error';
174
    }
175
}
176