JSendRenderer::_error()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 4
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
ccs 8
cts 8
cp 1
crap 2
1
<?php
2
/**
3
 * Copyright 2016 - 2018, Cake Development Corporation (http://cakedc.com)
4
 *
5
 * Licensed under The MIT License
6
 * Redistributions of files must retain the above copyright notice.
7
 *
8
 * @copyright Copyright 2016 - 2018, Cake Development Corporation (http://cakedc.com)
9
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
10
 */
11
12
namespace CakeDC\Api\Service\Renderer;
13
14
use CakeDC\Api\Exception\ValidationException;
15
use CakeDC\Api\Service\Action\Result;
16
use Cake\Core\Configure;
17
use Cake\Utility\Hash;
18
use Exception;
19
use stdClass;
20
21
/**
22
 * Class JSendRenderer
23
 * JSend content negotiation Renderer.
24
 *
25
 * @package CakeDC\Api\Service\Renderer
26
 */
27
class JSendRenderer extends BaseRenderer
28
{
29
30
    /**
31
     * Success status.
32
     */
33
    const STATUS_SUCCESS = 'success';
34
35
    /**
36
     * Fail status.
37
     */
38
    const STATUS_FAIL = 'fail';
39
40
    /**
41
     * Error status.
42
     */
43
    const STATUS_ERROR = 'error';
44
45
    /**
46
     * Response status.
47
     */
48
    public $status = self::STATUS_SUCCESS;
49
50
    /**
51
     * HTTP error code.
52
     */
53
    public $errorCode = 200;
54
55
    /**
56
     * Confirms if the specified content type is acceptable for the response.
57
     *
58
     * @return bool
59
     */
60
    public function accept()
61
    {
62
        $request = $this->_service->getRequest();
63
64
        return ($request->accepts('application/json') || $request->accepts('text/json') || $request->accepts('text/javascript'));
65
    }
66
67
    /**
68
     * Builds the HTTP response.
69
     *
70
     * @param Result $result The result object returned by the Service.
71
     * @return bool
72
     */
73 53
    public function response(Result $result = null)
74
    {
75 53
        $response = $this->_service->getResponse();
76
77 53
        $data = $result->getData();
0 ignored issues
show
Bug introduced by
It seems like $result is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
78 53
        $payload = $result->getPayload();
79
        $return = [
80
            'data' => $data
81 53
        ];
82 53
        if (is_array($payload)) {
83 53
            $return = Hash::merge($return, $payload);
84 53
        }
85 53
        $this->_mapStatus($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by parameter $result on line 73 can be null; however, CakeDC\Api\Service\Rende...dRenderer::_mapStatus() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
86
87 53
        $this->_service->setResponse($response->withStringBody($this->_format($this->status, $return))->withStatus($result->getCode())->withType('application/json'));
88
89 53
        return true;
90
    }
91
92
    /**
93
     * Processes an exception thrown while processing the request.
94
     *
95
     * @param Exception $exception The exception object.
96
     * @return void
97
     */
98 9
    public function error(Exception $exception)
99
    {
100 9
        $response = $this->_service->getResponse();
101 9
        if ($exception instanceof ValidationException) {
102 1
            $data = $exception->getValidationErrors();
103 1
        } else {
104 8
            $data = null;
105
        }
106 9
        $message = $this->_buildMessage($exception);
107 9
        $trace = $this->_stackTrace($exception);
108 9
        $this->_service->setResponse($response->withStringBody($this->_error($message, $exception->getCode(), $data, $trace))->withStatus((int)$this->errorCode)->withType('application/json'));
109 9
    }
110
111
    /**
112
     * Formats a response to JSend specification.
113
     *
114
     * @param string $status The status of the response.
115
     * @param array $response The response properties.
116
     * @return string
117
     */
118 58
    protected function _format($status, $response = [])
119
    {
120 58
        $object = new stdClass();
121 58
        $object->status = $status;
122 58
        foreach ($response as $param => $value) {
123 58
            $object->{$param} = $value;
124 58
        }
125 58
        $format = Configure::read('debug') ? JSON_PRETTY_PRINT : 0;
126
127 58
        return json_encode($object, $format);
128
    }
129
130
    /**
131
     * Creates a successful response.
132
     *
133
     * @param array $data The response data object.
134
     * @return string
135
     */
136
    protected function _success($data = null)
137
    {
138
        return $this->_format(self::STATUS_SUCCESS, ['data' => $data]);
139
    }
140
141
    /**
142
     * Creates a failure response.
143
     *
144
     * @param array $data The response data object.
145
     * @return string
146
     */
147
    protected function _fail($data = null)
148
    {
149
        return $this->_format(self::STATUS_FAIL, ['data' => $data]);
150
    }
151
152
    /**
153
     * Creates an error response.
154
     *
155
     * @param string $message The error message.
156
     * @param int $code The error code.
157
     * @param array $data The response data object.
158
     * @param array $trace The exception trace
159
     * @return string
160
     */
161 9
    protected function _error($message = 'Unknown error', $code = 0, $data = null, $trace = null)
162
    {
163
        $response = [
164 9
            'message' => $message,
165 9
            'code' => $code,
166
            'data' => $data
167 9
        ];
168 9
        if (Configure::read('debug') > 0) {
169 8
            $response['trace'] = $trace;
170 8
        }
171
172 9
        return $this->_format(self::STATUS_ERROR, $response);
173
    }
174
175
    /**
176
     * Update status based on result code
177
     *
178
     * @param Result $result A result object instance.
179
     * @return void
180
     */
181 53
    protected function _mapStatus(Result $result)
182
    {
183 53
        $code = (int)$result->getCode();
184 53
        if ($code == 0 || $code >= 200 && $code <= 399) {
185 53
            $this->status = self::STATUS_SUCCESS;
186 53
        } else {
187
            $this->status = self::STATUS_ERROR;
188
        }
189 53
    }
190
}
191