Test Failed
Push — master ( 4cc386...066331 )
by Julien
10:30 queued 05:08
created

Rest::restoreAction()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 15
ccs 0
cts 9
cp 0
rs 9.6111
cc 5
nc 16
nop 1
crap 30
1
<?php
2
/**
3
 * This file is part of the Zemit Framework.
4
 *
5
 * (c) Zemit Team <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE.txt
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Zemit\Mvc\Controller;
12
13
use League\Csv\CharsetConverter;
14
use Phalcon\Http\Response;
15
use Phalcon\Mvc\Dispatcher;
16
use Phalcon\Mvc\Model\Resultset;
17
use League\Csv\Writer;
18
use Phalcon\Version;
19
use Zemit\Utils\Slug;
20
21
/**
22
 * Class Rest
23
 *
24
 * @author Julien Turbide <[email protected]>
25
 * @copyright Zemit Team <[email protected]>
26
 *
27
 * @since 1.0
28
 * @version 1.0
29
 *
30
 * @package Zemit\Mvc\Controller
31
 */
32
class Rest extends \Zemit\Mvc\Controller
33
{
34
    use Model;
0 ignored issues
show
Bug introduced by
The trait Zemit\Mvc\Controller\Model requires the property $loader which is not provided by Zemit\Mvc\Controller\Rest.
Loading history...
35
    
36
    /**
37
     * Rest Bootstrap
38
     */
39
    public function indexAction($id = null)
40
    {
41
        $this->restForwarding($id);
42
    }
43
    
44
    /**
45
     * Rest bootstrap forwarding
46
     *
47
     * @return \Phalcon\Http\ResponseInterface
48
     */
49
    protected function restForwarding($id = null)
50
    {
51
        $id ??= $this->getParam('id');
52
        
53
        if ($this->request->isPost() || $this->request->isPut()) {
54
            $this->dispatcher->forward(['action' => 'save']);
55
        }
56
        else if ($this->request->isDelete()) {
57
            $this->dispatcher->forward(['action' => 'delete']);
58
        }
59
        else if ($this->request->isGet()) {
60
            if (is_null($id)) {
61
                $this->dispatcher->forward(['action' => 'getAll']);
62
            }
63
            else {
64
                $this->dispatcher->forward(['action' => 'get']);
65
            }
66
        }
67
        else if ($this->request->isOptions()) {
68
            
69
            // @TODO handle this correctly
70
            return $this->setRestResponse(['result' => 'OK']);
71
        }
72
    }
73
    
74
    /**
75
     * Retrieving a record
76
     *
77
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
78
     *
79
     * @return bool|\Phalcon\Http\ResponseInterface
80
     */
81
    public function getAction($id = null)
82
    {
83
        $modelName = $this->getModelName();
0 ignored issues
show
Deprecated Code introduced by
The function Zemit\Mvc\Controller\Rest::getModelName() has been deprecated: change to getModelClassName() instead ( Ignorable by Annotation )

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

83
        $modelName = /** @scrutinizer ignore-deprecated */ $this->getModelName();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
84
        $single = $this->getSingle($id, $modelName, null);
85
        
86
        $this->view->single = $single ? $single->expose($this->getExpose()) : false;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getExpose() targeting Zemit\Mvc\Controller\Rest::getExpose() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
The method expose() does not exist on Phalcon\Mvc\Model\Resultset. ( Ignorable by Annotation )

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

86
        $this->view->single = $single ? $single->/** @scrutinizer ignore-call */ expose($this->getExpose()) : false;

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...
87
        $this->view->model = $modelName;
88
        $this->view->source = $single ? $single->getSource() : false;
0 ignored issues
show
Bug introduced by
The method getSource() does not exist on Phalcon\Mvc\Model\Resultset. ( Ignorable by Annotation )

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

88
        $this->view->source = $single ? $single->/** @scrutinizer ignore-call */ getSource() : false;

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...
89
        
90
        if (!$single) {
91
            $this->response->setStatusCode(404, 'Not Found');
92
            
93
            return false;
94
        }
95
        
96
        return $this->setRestResponse();
97
    }
98
    
99
    /**
100
     * Retrieving a record list
101
     *
102
     * @return \Phalcon\Http\ResponseInterface
103
     */
104
    public function getAllAction()
105
    {
106
        /** @var \Zemit\Mvc\Model $model */
107
        $model = $this->getModelNameFromController();
108
        
109
        /** @var Resultset $with */
110
        $find = $this->getFind();
111
//        dd($find);
112
        $with = $model::with($this->getWith() ? : [], $find ? : []);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getWith() targeting Zemit\Mvc\Controller\Rest::getWith() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
113
//        $list = $model::find($find ? : []);
114
        
115
        /**
116
         * @var int $key
117
         * @var \Zemit\Mvc\Model $item
118
         */
119
        $list = [];
120
        foreach ($with as $key => $item) {
121
            $list[$key] = $item->expose($this->getExpose());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getExpose() targeting Zemit\Mvc\Controller\Rest::getExpose() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
122
        }
123
        
124
        $list = is_array($list) ? array_values(array_filter($list)) : $list;
0 ignored issues
show
introduced by
The condition is_array($list) is always true.
Loading history...
125
        $this->view->list = $list;
126
        $this->view->listCount = count($list);
127
        $this->view->totalCount = $model::find($this->getFindCount($find));
128
        $this->view->totalCount = is_int($this->view->totalCount)? $this->view->totalCount : count($this->view->totalCount); // @todo fix count to work with rollup when joins
0 ignored issues
show
introduced by
The condition is_int($this->view->totalCount) is always false.
Loading history...
129
        $this->view->limit = $find['limit'] ?? false;
130
        $this->view->offset = $find['offset'] ?? false;
131
        $this->view->find = ($this->config->app->debug || $this->config->debug->enable) ? $find : false;
0 ignored issues
show
Bug Best Practice introduced by
The property debug does not exist on Zemit\Bootstrap\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property app does not exist on Zemit\Bootstrap\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
132
        
133
        return $this->setRestResponse();
134
    }
135
    
136
    /**
137
     * Exporting a record list into a CSV stream
138
     *
139
     * @return \Phalcon\Http\ResponseInterface
140
     * @throws \League\Csv\CannotInsertRecord
141
     * @throws \Zemit\Exception
142
     */
143
    public function exportAction()
144
    {
145
        $response = $this->getAllAction();
146
        $params = $this->view->getParamsToView();
147
        $list = $params['list'] ?? null;
148
        if (isset($list[0])) {
149
            
150
            // Get the export mode (csv, csv-windows, csv-mac, xlsx)
151
            $contentType = $this->getContentType();
152
            
153
            // Flattern the array for the CSV / XLSX writing
154
            $this->flatternArrayForCsv($list);
155
            
156
            // Prepare the filename to export
157
            $fileName = ucfirst(Slug::generate(basename(str_replace('\\', '/', $this->getModelClassName())))) . ' List (' . date('Y-m-d') . ')';
158
            
159
            if ($contentType === 'json') {
160
//                $this->response->setJsonContent($list);
161
                $this->response->setContent(json_encode($list, JSON_PRETTY_PRINT, 2048));
162
                $this->response->setContentType('application/json');
163
                $this->response->setHeader('Content-disposition', 'attachment; filename="'.addslashes($fileName).'.json"');
164
                return $this->response->send();
165
            }
166
            
167
            // CSV
168
            if ($contentType === 'csv') {
169
                
170
                // Get CSV custom request parameters
171
                $mode = $params['mode'] ?? null;
172
                $delimiter = $params['delimiter'] ?? null;
173
                $newline = $params['newline'] ?? null;
174
                $escape = $params['escape'] ?? null;
175
                $outputBOM = $params['outputBOM'] ?? null;
176
                $skipIncludeBOM = $params['skipIncludeBOM'] ?? null;
177
                
178
//                $csv = Writer::createFromFileObject(new \SplTempFileObject());
179
                $csv = Writer::createFromStream(fopen('php://memory', 'r+'));
0 ignored issues
show
Bug introduced by
It seems like fopen('php://memory', 'r+') can also be of type false; however, parameter $stream of League\Csv\AbstractCsv::createFromStream() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

179
                $csv = Writer::createFromStream(/** @scrutinizer ignore-type */ fopen('php://memory', 'r+'));
Loading history...
180
    
181
                // CSV - MS Excel on MacOS
182
                if ($mode === 'mac') {
183
                    $csv->setOutputBOM(Writer::BOM_UTF16_LE); // utf-16
184
                    $csv->setDelimiter("\t"); // tabs separated
185
                    $csv->setNewline("\r\n"); // new lines
186
                    CharsetConverter::addTo($csv, 'UTF-8', 'UTF-16');
187
                }
188
                
189
                // CSV - MS Excel on Windows
190
                else {
191
                    $csv->setOutputBOM(Writer::BOM_UTF8); // utf-8
192
                    $csv->setDelimiter(','); // comma separated
193
                    $csv->setNewline("\n"); // new line windows
194
                    CharsetConverter::addTo($csv, 'UTF-8', 'UTF-8');
195
                }
196
                
197
                // Apply forced params from request
198
                if (isset($outputBOM)) {
199
                    $csv->setOutputBOM($outputBOM);
200
                }
201
                if (isset($delimiter)) {
202
                    $csv->setDelimiter($delimiter);
203
                }
204
                if (isset($newline)) {
205
                    $csv->setNewline($newline);
206
                }
207
                if (isset($escape)) {
208
                    $csv->setEscape($escape);
209
                }
210
                if ($skipIncludeBOM) {
211
                    $csv->skipInputBOM();
212
                }
213
                else {
214
                    $csv->includeInputBOM();
215
                }
216
    
217
                // CSV
218
                $csv->insertOne(array_keys($list[0]));
219
                $csv->insertAll($list);
220
                $csv->output($fileName . '.csv');
221
                die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
222
            }
223
224
            // XLSX
225
            if ($contentType === 'xlsx') {
226
                $xlsxArray = [];
227
                foreach ($list as $array) {
228
                    if (empty($xlsxArray)) {
229
                        $xlsxArray []= array_keys($array);
230
                    }
231
                    $xlsxArray []= array_values($array);
232
                }
233
                $xlsx = \SimpleXLSXGen::fromArray($xlsxArray);
234
                $xlsx->downloadAs($fileName . '.xlsx');
235
                die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
236
            }
237
            
238
            // Something went wrong
239
            throw new \Exception('Failed to export `' . $this->getModelClassName() . '` using content-type `' . $contentType . '`', 400);
240
        }
241
        
242
        return $response;
243
    }
244
    
245
    /**
246
     * @param array|null $array
247
     *
248
     * @return array|null
249
     */
250
    public function flatternArrayForCsv(?array &$list = null) {
251
        
252
        foreach ($list as $listKey => $listValue) {
253
            foreach ($listValue as $column => $value) {
254
                if (is_array($value) || is_object($value)) {
255
                    $list[$listKey][$column] = gettype($value);
256
                }
257
            }
258
        }
259
        
260
        return $list;
261
    }
262
    
263
    /**
264
     * Count a record list
265
     * @TODO add total count / deleted count / active count
266
     *
267
     * @return \Phalcon\Http\ResponseInterface
268
     */
269
    public function countAction()
270
    {
271
        /** @var \Zemit\Mvc\Model $model */
272
        $model = $this->getModelNameFromController();
273
        $instance = new $model();
274
        $this->view->totalCount = $model::count($this->getFindCount($this->getFind()));
275
        $this->view->totalCount = is_int($this->view->totalCount)? $this->view->totalCount : count($this->view->totalCount);
276
        $this->view->model = get_class($instance);
277
        $this->view->source = $instance->getSource();
278
        
279
        return $this->setRestResponse();
280
    }
281
    
282
    /**
283
     * Prepare a new model for the frontend
284
     *
285
     * @return \Phalcon\Http\ResponseInterface
286
     */
287
    public function newAction()
288
    {
289
        /** @var \Zemit\Mvc\Model $model */
290
        $model = $this->getModelNameFromController();
291
        
292
        $entity = new $model();
293
        $entity->assign($this->getParams(), $this->getWhitelist(), $this->getColumnMap());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getWhitelist() targeting Zemit\Mvc\Controller\Rest::getWhitelist() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure the usage of $this->getColumnMap() targeting Zemit\Mvc\Controller\Rest::getColumnMap() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
294
        
295
        $this->view->model = get_class($entity);
296
        $this->view->source = $entity->getSource();
297
        $this->view->single = $entity->expose($this->getExpose());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getExpose() targeting Zemit\Mvc\Controller\Rest::getExpose() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
298
        
299
        return $this->setRestResponse();
300
    }
301
    
302
    /**
303
     * Prepare a new model for the frontend
304
     *
305
     * @return \Phalcon\Http\ResponseInterface
306
     */
307
    public function validateAction($id = null)
308
    {
309
        /** @var \Zemit\Mvc\Model $model */
310
        $model = $this->getModelNameFromController();
311
        
312
        /** @var \Zemit\Mvc\Model $instance */
313
        $entity = $this->getSingle($id);
314
        $new = !$entity;
315
        
316
        if ($new) {
317
            $entity = new $model();
318
        }
319
        
320
        $entity->assign($this->getParams(), $this->getWhitelist(), $this->getColumnMap());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getWhitelist() targeting Zemit\Mvc\Controller\Rest::getWhitelist() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure the usage of $this->getColumnMap() targeting Zemit\Mvc\Controller\Rest::getColumnMap() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
The method assign() does not exist on Phalcon\Mvc\Model\Resultset. ( Ignorable by Annotation )

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

320
        $entity->/** @scrutinizer ignore-call */ 
321
                 assign($this->getParams(), $this->getWhitelist(), $this->getColumnMap());

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...
321
        
322
        /**
323
         * Event to run
324
         * @see https://docs.phalcon.io/4.0/en/db-models-events
325
         */
326
        $events = [
327
            'beforeCreate' => null,
328
            'beforeUpdate' => null,
329
            'beforeSave' => null,
330
            'beforeValidationOnCreate' => null,
331
            'beforeValidationOnUpdate' => null,
332
            'beforeValidation' => null,
333
            'prepareSave' => null,
334
            'validation' => null,
335
            'afterValidationOnCreate' => null,
336
            'afterValidationOnUpdate' => null,
337
            'afterValidation' => null,
338
        ];
339
        
340
        // run events, as it would normally
341
        foreach ($events as $event => $state) {
342
            $this->skipped = false;
0 ignored issues
show
Bug Best Practice introduced by
The property skipped does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
343
            
344
            // skip depending wether it's a create or update
345
            if (str_contains($event, $new ? 'Update' : 'Create')) {
346
                continue;
347
            }
348
            
349
            // fire the event, allowing to fail or skip
350
            $events[$event] = $entity->fireEventCancel($event);
0 ignored issues
show
Bug introduced by
The method fireEventCancel() does not exist on Phalcon\Mvc\Model\Resultset. ( Ignorable by Annotation )

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

350
            /** @scrutinizer ignore-call */ 
351
            $events[$event] = $entity->fireEventCancel($event);

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...
351
            if ($events[$event] === false) {
352
                // event failed
353
                break;
354
            }
355
            
356
            // event was skipped, just for consistencies purpose
357
            if ($this->skipped) {
358
                continue;
359
            }
360
        }
361
        
362
        $this->view->model = get_class($entity);
0 ignored issues
show
Bug introduced by
It seems like $entity can also be of type true; however, parameter $object of get_class() does only seem to accept object, maybe add an additional type check? ( Ignorable by Annotation )

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

362
        $this->view->model = get_class(/** @scrutinizer ignore-type */ $entity);
Loading history...
363
        $this->view->source = $entity->getSource();
364
        $this->view->single = $entity->expose($this->getExpose());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getExpose() targeting Zemit\Mvc\Controller\Rest::getExpose() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
365
        $this->view->messages = $entity->getMessages();
366
        $this->view->events = $events;
367
        $this->view->validated = empty($this->view->messages);
368
        
369
        return $this->setRestResponse($this->view->validated);
0 ignored issues
show
Bug introduced by
$this->view->validated of type boolean is incompatible with the type array|null expected by parameter $response of Zemit\Mvc\Controller\Rest::setRestResponse(). ( Ignorable by Annotation )

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

369
        return $this->setRestResponse(/** @scrutinizer ignore-type */ $this->view->validated);
Loading history...
370
    }
371
    
372
    /**
373
     * Saving a record
374
     * - Create
375
     * - Update
376
     *
377
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
378
     *
379
     * @return array
380
     */
381
    public function saveAction($id = null)
382
    {
383
        $this->view->setVars($this->save($id));
0 ignored issues
show
Bug introduced by
The method setVars() does not exist on Phalcon\Mvc\ViewInterface. Did you maybe mean setVar()? ( Ignorable by Annotation )

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

383
        $this->view->/** @scrutinizer ignore-call */ 
384
                     setVars($this->save($id));

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...
384
        
385
        return $this->setRestResponse($this->view->saved);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->setRestResponse($this->view->saved) returns the type Phalcon\Http\ResponseInterface which is incompatible with the documented return type array.
Loading history...
386
    }
387
    
388
    /**
389
     * Deleting a record
390
     *
391
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
392
     *
393
     * @return bool
394
     */
395
    public function deleteAction($id = null)
396
    {
397
        $single = $this->getSingle($id);
398
        
399
        $this->view->deleted = $single ? $single->delete() : false;
400
        $this->view->single = $single ? $single->expose($this->getExpose()) : false;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getExpose() targeting Zemit\Mvc\Controller\Rest::getExpose() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
401
        $this->view->messages = $single ? $single->getMessages() : false;
402
        
403
        if (!$single) {
404
            $this->response->setStatusCode(404, 'Not Found');
405
            
406
            return false;
407
        }
408
        
409
        return $this->setRestResponse($this->view->deleted);
0 ignored issues
show
Bug introduced by
$this->view->deleted of type boolean is incompatible with the type array|null expected by parameter $response of Zemit\Mvc\Controller\Rest::setRestResponse(). ( Ignorable by Annotation )

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

409
        return $this->setRestResponse(/** @scrutinizer ignore-type */ $this->view->deleted);
Loading history...
Bug Best Practice introduced by
The expression return $this->setRestRes...e($this->view->deleted) returns the type Phalcon\Http\ResponseInterface which is incompatible with the documented return type boolean.
Loading history...
410
    }
411
    
412
    /**
413
     * Restoring record
414
     *
415
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
416
     *
417
     * @return bool
418
     */
419
    public function restoreAction($id = null)
420
    {
421
        $single = $this->getSingle($id);
422
        
423
        $this->view->restored = $single ? $single->restore() : false;
0 ignored issues
show
Bug introduced by
The method restore() does not exist on Phalcon\Mvc\Model\Resultset. ( Ignorable by Annotation )

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

423
        $this->view->restored = $single ? $single->/** @scrutinizer ignore-call */ restore() : false;

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...
424
        $this->view->single = $single ? $single->expose($this->getExpose()) : false;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getExpose() targeting Zemit\Mvc\Controller\Rest::getExpose() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
425
        $this->view->messages = $single ? $single->getMessages() : false;
426
        
427
        if (!$single) {
428
            $this->response->setStatusCode(404, 'Not Found');
429
            
430
            return false;
431
        }
432
        
433
        return $this->setRestResponse($this->view->restored);
0 ignored issues
show
Bug introduced by
It seems like $this->view->restored can also be of type false; however, parameter $response of Zemit\Mvc\Controller\Rest::setRestResponse() does only seem to accept array|null, maybe add an additional type check? ( Ignorable by Annotation )

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

433
        return $this->setRestResponse(/** @scrutinizer ignore-type */ $this->view->restored);
Loading history...
Bug Best Practice introduced by
The expression return $this->setRestRes...($this->view->restored) returns the type Phalcon\Http\ResponseInterface which is incompatible with the documented return type boolean.
Loading history...
434
    }
435
    
436
    /**
437
     * Re-ordering a position
438
     *
439
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
440
     * @param null $position
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $position is correct as it would always require null to be passed?
Loading history...
441
     *
442
     * @return bool|\Phalcon\Http\ResponseInterface
443
     */
444
    public function reorderAction($id = null)
445
    {
446
        $single = $this->getSingle($id);
447
        
448
        $position = $this->getParam('position', 'int');
449
        
450
        $this->view->reordered = $single ? $single->reorder($position) : false;
0 ignored issues
show
Bug introduced by
The method reorder() does not exist on Phalcon\Mvc\Model\Resultset. ( Ignorable by Annotation )

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

450
        $this->view->reordered = $single ? $single->/** @scrutinizer ignore-call */ reorder($position) : false;

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...
451
        $this->view->single = $single ? $single->expose($this->getExpose()) : false;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getExpose() targeting Zemit\Mvc\Controller\Rest::getExpose() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
452
        $this->view->messages = $single ? $single->getMessages() : false;
453
        
454
        if (!$single) {
455
            $this->response->setStatusCode(404, 'Not Found');
456
            
457
            return false;
458
        }
459
        
460
        return $this->setRestResponse($this->view->reordered);
0 ignored issues
show
Bug introduced by
It seems like $this->view->reordered can also be of type false; however, parameter $response of Zemit\Mvc\Controller\Rest::setRestResponse() does only seem to accept array|null, maybe add an additional type check? ( Ignorable by Annotation )

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

460
        return $this->setRestResponse(/** @scrutinizer ignore-type */ $this->view->reordered);
Loading history...
461
    }
462
    
463
    /**
464
     * Sending an error as an http response
465
     *
466
     * @param null $error
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $error is correct as it would always require null to be passed?
Loading history...
467
     * @param null $response
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $response is correct as it would always require null to be passed?
Loading history...
468
     *
469
     * @return \Phalcon\Http\ResponseInterface
470
     */
471
    public function setRestErrorResponse($code = 400, $status = 'Bad Request', $response = null)
472
    {
473
        return $this->setRestResponse($response, $code, $status);
474
    }
475
    
476
    /**
477
     * Sending rest response as an http response
478
     *
479
     * @param array|null $response
480
     * @param null $status
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $status is correct as it would always require null to be passed?
Loading history...
481
     * @param null $code
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $code is correct as it would always require null to be passed?
Loading history...
482
     * @param int $jsonOptions
483
     * @param int $depth
484
     *
485
     * @return \Phalcon\Http\ResponseInterface
486
     */
487
    public function setRestResponse($response = null, $code = null, $status = null, $jsonOptions = 0, $depth = 512)
488
    {
489
        $debug = $this->config->app->debug ?? false;
0 ignored issues
show
Bug Best Practice introduced by
The property app does not exist on Zemit\Bootstrap\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
490
        
491
        // keep forced status code or set our own
492
        $responseStatusCode = $this->response->getStatusCode();
493
        $reasonPhrase = $this->response->getReasonPhrase();
494
        $status ??= $reasonPhrase ? : 'OK';
495
        $code ??= (int)$responseStatusCode ? : 200;
496
        $view = $this->view->getParamsToView();
497
        $hash = hash('sha512', json_encode($view));
498
        
499
        /**
500
         * Debug section
501
         * - Versions
502
         * - Request
503
         * - Identity
504
         * - Profiler
505
         * - Dispatcher
506
         * - Router
507
         */
508
        $request = $debug ? $this->request->toArray() : null;
0 ignored issues
show
Bug introduced by
The method toArray() does not exist on Phalcon\Http\RequestInterface. It seems like you code against a sub-type of Phalcon\Http\RequestInterface such as Zemit\Http\Request. ( Ignorable by Annotation )

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

508
        $request = $debug ? $this->request->/** @scrutinizer ignore-call */ toArray() : null;
Loading history...
introduced by
The method toArray() does not exist on Phalcon\Http\Request. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

508
        $request = $debug ? $this->request->/** @scrutinizer ignore-call */ toArray() : null;
Loading history...
509
        $identity = $debug ? $this->identity->getIdentity() : null;
510
        $profiler = $debug && $this->profiler ? $this->profiler->toArray() : null;
0 ignored issues
show
Bug Best Practice introduced by
The property profiler does not exist on Zemit\Mvc\Controller\Rest. Since you implemented __get, consider adding a @property annotation.
Loading history...
511
        $dispatcher = $debug ? $this->dispatcher->toArray() : null;
512
        $router = $debug ? $this->router->toArray() : null;
513
        
514
        $api = $debug ? [
515
            'php' => phpversion(),
516
            'phalcon' => Version::get(),
517
            'zemit' => $this->config->core->version,
0 ignored issues
show
Bug Best Practice introduced by
The property core does not exist on Zemit\Bootstrap\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
518
            'core' => $this->config->core->name,
519
            'app' => $this->config->app->version,
520
            'name' => $this->config->app->name,
521
        ] : [];
522
        $api['version'] = '0.1';
523
        
524
        $this->response->setStatusCode($code, $code . ' ' . $status);
525
        
526
        // @todo handle this correctly
527
        // @todo private vs public cache type
528
        $cache = $this->getCache();
529
        if (!empty($cache['lifetime'])) {
530
            if ($this->response->getStatusCode() === 200) {
531
                $this->response->setCache($cache['lifetime']);
532
                $this->response->setEtag($hash);
533
            }
534
        } else {
535
            $this->response->setCache(0);
536
            $this->response->setHeader('Cache-Control', 'no-cache, max-age=0');
537
        }
538
        
539
        return $this->response->setJsonContent(array_merge([
540
            'api' => $api,
541
            'timestamp' => date('c'),
542
            'hash' => $hash,
543
            'status' => $status,
544
            'code' => $code,
545
            'response' => $response,
546
            'view' => $view,
547
        ], $debug ? [
548
            'identity' => $identity,
549
            'profiler' => $profiler,
550
            'request' => $request,
551
            'dispatcher' => $dispatcher,
552
            'router' => $router,
553
        ] : []), $jsonOptions, $depth);
0 ignored issues
show
Unused Code introduced by
The call to Phalcon\Http\ResponseInterface::setJsonContent() has too many arguments starting with $jsonOptions. ( Ignorable by Annotation )

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

553
        return $this->response->/** @scrutinizer ignore-call */ setJsonContent(array_merge([

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
554
    }
555
    
556
    /**
557
     * Handle rest response automagically
558
     *
559
     * @param Dispatcher $dispatcher
560
     */
561
    public function afterExecuteRoute(Dispatcher $dispatcher)
562
    {
563
        $response = $dispatcher->getReturnedValue();
564
        
565
        // Avoid breaking default phalcon behaviour
566
        if ($response instanceof Response) {
567
            return;
568
        }
569
        
570
        // Merge response into view variables
571
        if (is_array($response)) {
572
            $this->view->setVars($response, true);
573
        }
574
        
575
        // Return our Rest normalized response
576
        $dispatcher->setReturnedValue($this->setRestResponse(is_array($response) ? null : $response));
577
    }
578
}
579