Passed
Push — master ( 1e5bb4...983543 )
by Dante
02:00
created

ModulesController::save()   C

Complexity

Conditions 11
Paths 70

Size

Total Lines 80
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 11
eloc 57
c 2
b 1
f 0
nc 70
nop 0
dl 0
loc 80
rs 6.7915

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2018 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
namespace App\Controller;
14
15
use App\Utility\ApiConfigTrait;
16
use App\Utility\CacheTools;
17
use App\Utility\Message;
18
use App\Utility\PermissionsTrait;
19
use BEdita\SDK\BEditaClientException;
20
use BEdita\WebTools\Utility\ApiTools;
21
use Cake\Core\Configure;
22
use Cake\Event\Event;
23
use Cake\Event\EventInterface;
24
use Cake\Http\Exception\UnauthorizedException;
25
use Cake\Http\Response;
26
use Cake\I18n\I18n;
27
use Cake\Utility\Hash;
28
use Exception;
29
use Psr\Log\LogLevel;
30
31
/**
32
 * Modules controller: list, add, edit, remove objects
33
 *
34
 * @property \App\Controller\Component\CategoriesComponent $Categories
35
 * @property \App\Controller\Component\ChildrenComponent $Children
36
 * @property \App\Controller\Component\HistoryComponent $History
37
 * @property \App\Controller\Component\ObjectsEditorsComponent $ObjectsEditors
38
 * @property \App\Controller\Component\ParentsComponent $Parents
39
 * @property \App\Controller\Component\ProjectConfigurationComponent $ProjectConfiguration
40
 * @property \App\Controller\Component\PropertiesComponent $Properties
41
 * @property \App\Controller\Component\QueryComponent $Query
42
 * @property \App\Controller\Component\ThumbsComponent $Thumbs
43
 * @property \BEdita\WebTools\Controller\Component\ApiFormatterComponent $ApiFormatter
44
 */
45
class ModulesController extends AppController
46
{
47
    use ApiConfigTrait;
48
    use PermissionsTrait;
49
50
    /**
51
     * Object type currently used
52
     *
53
     * @var string
54
     */
55
    protected $objectType = null;
56
57
    /**
58
     * @inheritDoc
59
     */
60
    public function initialize(): void
61
    {
62
        parent::initialize();
63
64
        $this->loadComponent('Children');
65
        $this->loadComponent('History');
66
        $this->loadComponent('ObjectsEditors');
67
        $this->loadComponent('Parents');
68
        $this->loadComponent('Properties');
69
        $this->loadComponent('ProjectConfiguration');
70
        $this->loadComponent('Query');
71
        $this->loadComponent('Thumbs', Configure::read('Thumbs', []));
72
        $this->loadComponent('BEdita/WebTools.ApiFormatter');
73
        if ($this->getRequest()->getParam('object_type')) {
74
            $this->objectType = $this->getRequest()->getParam('object_type');
75
            $this->Modules->setConfig('currentModuleName', $this->objectType);
76
            $this->Schema->setConfig('type', $this->objectType);
77
        }
78
        $this->Security->setConfig('unlockedActions', ['save', 'setup']);
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     *
84
     * @codeCoverageIgnore
85
     */
86
    public function beforeRender(EventInterface $event): ?Response
87
    {
88
        $this->set('objectType', $this->objectType);
89
90
        return parent::beforeRender($event);
91
    }
92
93
    /**
94
     * Display resources list.
95
     *
96
     * @return \Cake\Http\Response|null
97
     */
98
    public function index(): ?Response
99
    {
100
        $this->getRequest()->allowMethod(['get']);
101
102
        // handle filter and query parameters using session
103
        $result = $this->applySessionFilter();
104
        if ($result != null) {
105
            return $result;
106
        }
107
108
        try {
109
            $params = $this->Query->index();
110
            $response = $this->apiClient->getObjects($this->objectType, $params);
111
            if (empty($params['q']) && empty($params['filter'])) {
112
                CacheTools::setModuleCount((array)$response, $this->Modules->getConfig('currentModuleName'));
113
            }
114
        } catch (BEditaClientException $e) {
115
            $this->log($e->getMessage(), LogLevel::ERROR);
116
            $this->Flash->error($e->getMessage(), ['params' => $e]);
117
            // remove session filter to avoid error repetition
118
            $session = $this->getRequest()->getSession();
119
            $session->delete(sprintf('%s.filter', $this->Modules->getConfig('currentModuleName')));
120
121
            return $this->redirect(['_name' => 'dashboard']);
122
        }
123
124
        $this->ProjectConfiguration->read();
125
126
        $response = $this->ApiFormatter->embedIncluded((array)$response);
127
        $objects = (array)Hash::get($response, 'data');
128
        $this->set('objects', $objects);
129
        $this->set('meta', (array)Hash::get($response, 'meta'));
130
        $this->set('links', (array)Hash::get($response, 'links'));
131
        $this->set('types', ['right' => $this->Schema->descendants($this->objectType)]);
132
133
        $this->set('properties', $this->Properties->indexList($this->objectType));
134
135
        // base/custom filters for filter view
136
        $this->set('filter', $this->Properties->filterList($this->objectType));
137
138
        // base/custom bulk actions for index view
139
        $this->set('bulkActions', $this->Properties->bulkList($this->objectType));
140
141
        // objectTypes schema
142
        $this->set('schema', $this->getSchemaForIndex($this->objectType));
143
        // custom properties
144
        $this->set('customProps', $this->Schema->customProps($this->objectType));
145
146
        // set prevNext for views navigations
147
        $this->setObjectNav($objects);
148
149
        return null;
150
    }
151
152
    /**
153
     * View single resource.
154
     *
155
     * @param string|int $id Resource ID.
156
     * @return \Cake\Http\Response|null
157
     */
158
    public function view($id): ?Response
159
    {
160
        $this->getRequest()->allowMethod(['get']);
161
162
        try {
163
            $query = ['count' => 'all'];
164
            $response = $this->apiClient->getObject($id, $this->objectType, $query);
165
        } catch (BEditaClientException $e) {
166
            // Error! Back to index.
167
            $this->log($e->getMessage(), LogLevel::ERROR);
168
            $this->Flash->error(__('Error retrieving the requested content'), ['params' => $e]);
169
170
            return $this->redirect(['_name' => 'modules:list', 'object_type' => $this->objectType]);
171
        }
172
        $this->ProjectConfiguration->read();
173
174
        $revision = Hash::get($response, 'meta.schema.' . $this->objectType . '.revision', null);
175
        $schema = $this->Schema->getSchema($this->objectType, $revision);
176
177
        $object = $response['data'];
178
179
        // setup `currentAttributes` and recover failure data from session.
180
        $this->Modules->setupAttributes($object);
181
182
        $included = !empty($response['included']) ? $response['included'] : [];
183
        $typeIncluded = Hash::combine($included, '{n}.id', '{n}', '{n}.type');
184
        $streams = Hash::get($typeIncluded, 'streams');
185
        $this->History->load($id, $object);
186
        $this->set(compact('object', 'included', 'schema', 'streams'));
187
        $this->set('properties', $this->Properties->viewGroups($object, $this->objectType));
188
        $this->set('foldersSchema', $this->Schema->getSchema('folders'));
189
190
        $computedRelations = array_reduce(
191
            array_keys($object['relationships']),
192
            function ($acc, $relName) use ($schema) {
193
                $acc[$relName] = (array)Hash::get($schema, sprintf('relations.%s', $relName), []);
194
195
                return $acc;
196
            },
197
            []
198
        );
199
        $this->setupViewRelations($computedRelations);
200
201
        // set objectNav
202
        $objectNav = $this->getObjectNav((string)$id);
203
        $this->set('objectNav', $objectNav);
204
205
        $this->ObjectsEditors->update((string)$id);
206
207
        return null;
208
    }
209
210
    /**
211
     * View single resource by id, doing a proper redirect (302) to resource module view by type.
212
     * If no resource found by ID, redirect to referer.
213
     *
214
     * @param string|int $id Resource ID.
215
     * @return \Cake\Http\Response|null
216
     */
217
    public function uname($id): ?Response
218
    {
219
        try {
220
            $response = $this->apiClient->get(sprintf('/objects/%s', $id));
221
        } catch (BEditaClientException $e) {
222
            $msg = $e->getMessage();
223
            $msgNotFound = sprintf(__('Resource "%s" not found', true), $id);
224
            $msgNotAvailable = sprintf(__('Resource "%s" not available. Error: %s', true), $id, $msg);
225
            $error = $e->getCode() === 404 ? $msgNotFound : $msgNotAvailable;
226
            $this->Flash->error($error);
227
228
            return $this->redirect($this->referer());
229
        }
230
        $_name = 'modules:view';
231
        $object_type = $response['data']['type'];
232
        $id = $response['data']['id'];
233
234
        return $this->redirect(compact('_name', 'object_type', 'id'));
235
    }
236
237
    /**
238
     * Display new resource form.
239
     *
240
     * @return \Cake\Http\Response|null
241
     */
242
    public function create(): ?Response
243
    {
244
        $this->viewBuilder()->setTemplate('view');
245
246
        // Create stub object with empty `attributes`.
247
        $schema = $this->Schema->getSchema();
248
        if (!is_array($schema)) {
249
            $this->Flash->error(__('Cannot create abstract objects or objects without schema'));
250
251
            return $this->redirect(['_name' => 'modules:list', 'object_type' => $this->objectType]);
252
        }
253
        $attributes = array_fill_keys(
254
            array_keys(
255
                array_filter(
256
                    $schema['properties'],
257
                    function ($schema) {
258
                        return empty($schema['readOnly']);
259
                    }
260
                )
261
            ),
262
            null
263
        );
264
        $object = [
265
            'type' => $this->objectType,
266
            'attributes' => $attributes,
267
        ];
268
269
        $this->set(compact('object', 'schema'));
270
        $this->set('properties', $this->Properties->viewGroups($object, $this->objectType));
271
        $this->ProjectConfiguration->read();
272
273
        $this->setupViewRelations((array)Hash::get($schema, 'relations'));
274
275
        return null;
276
    }
277
278
    /**
279
     * Create new object from ajax request.
280
     *
281
     * @return void
282
     */
283
    public function save(): void
284
    {
285
        $this->viewBuilder()->setClassName('Json'); // force json response
286
        $this->getRequest()->allowMethod(['post']);
287
        $requestData = $this->prepareRequest($this->objectType);
288
        unset($requestData['_csrfToken']);
289
        // extract related objects data
290
        $relatedData = (array)Hash::get($requestData, '_api');
291
        unset($requestData['_api']);
292
293
        try {
294
            $uname = Hash::get($requestData, 'uname');
295
            if (!empty($uname) && is_numeric($uname)) {
296
                $this->set(['error' => __('Invalid numeric uname. Change it to a valid string')]);
297
                $this->setSerialize(['error']);
298
299
                return;
300
            }
301
            $id = (string)Hash::get($requestData, 'id');
302
            // skip save if no data changed
303
            $schema = (array)$this->Schema->getSchema($this->objectType);
304
            $permissions = (array)Hash::get($requestData, 'permissions');
305
            $skipSaveObject = $this->Modules->skipSaveObject($id, $requestData);
306
            $skipSaveRelated = $this->Modules->skipSaveRelated($id, $relatedData);
307
            $skipSavePermissions = $this->Modules->skipSavePermissions($id, $permissions, $schema);
308
            if ($skipSaveObject && $skipSaveRelated && $skipSavePermissions) {
309
                $response = $this->apiClient->getObject($id, $this->objectType, ['count' => 'all']);
310
                $this->Thumbs->urls($response);
311
                $this->set((array)$response);
312
                $this->setSerialize(array_keys($response));
313
314
                return;
315
            }
316
317
            // upload file (if available)
318
            $this->Modules->upload($requestData);
319
320
            // save data
321
            $lang = I18n::getLocale();
322
            $headers = ['Accept-Language' => $lang];
323
            if (!$skipSaveObject) {
324
                $response = $this->apiClient->save($this->objectType, $requestData, $headers);
325
            } else {
326
                $response = $this->apiClient->getObject($id, $this->objectType);
327
            }
328
            if (!$skipSavePermissions) {
329
                $this->savePermissions(
330
                    (array)$response,
331
                    $schema,
332
                    $permissions
333
                );
334
            }
335
            $id = (string)Hash::get($response, 'data.id');
336
            if (!$skipSaveRelated) {
337
                $this->Modules->saveRelated($id, $this->objectType, $relatedData);
338
            }
339
            $options = [
340
                'id' => Hash::get($response, 'data.id'),
341
                'type' => $this->objectType,
342
                'data' => $requestData,
343
            ];
344
            $event = new Event('Controller.afterSave', $this, $options);
345
            $this->getEventManager()->dispatch($event);
346
        } catch (BEditaClientException $error) {
347
            $message = new Message($error);
348
            $this->log($message->get(), LogLevel::ERROR);
349
            $this->Flash->error($message->get(), ['params' => $error]);
350
            $this->set(['error' => $message->get()]);
351
            $this->setSerialize(['error']);
352
353
            return;
354
        }
355
        if ($response['data']) {
356
            $response['data'] = [ $response['data'] ];
357
        }
358
359
        $this->Thumbs->urls($response);
360
361
        $this->set((array)$response);
362
        $this->setSerialize(array_keys($response));
363
    }
364
365
    /**
366
     * Clone single object.
367
     *
368
     * @param string|int $id Object ID.
369
     * @return \Cake\Http\Response|null
370
     */
371
    public function clone($id): ?Response
372
    {
373
        $this->viewBuilder()->setTemplate('view');
374
        $schema = $this->Schema->getSchema();
375
        if (!is_array($schema)) {
376
            $this->Flash->error(__('Cannot create abstract objects or objects without schema'));
377
378
            return $this->redirect(['_name' => 'modules:list', 'object_type' => $this->objectType]);
379
        }
380
        try {
381
            $modified = [
382
                'title' => $this->getRequest()->getQuery('title'),
383
                'status' => 'draft',
384
            ];
385
            $reset = (array)Configure::read(sprintf('Clone.%s.reset', $this->objectType));
386
            foreach ($reset as $field) {
387
                $modified[$field] = null;
388
            }
389
            $included = [];
390
            foreach (['relationships', 'translations'] as $attribute) {
391
                if ($this->getRequest()->getQuery($attribute) === 'true') {
392
                    $included[] = $attribute;
393
                }
394
            }
395
            $clone = $this->apiClient->clone($this->objectType, $id, $modified, $included);
396
            $id = (string)Hash::get($clone, 'data.id');
397
        } catch (BEditaClientException $e) {
398
            $this->log($e->getMessage(), LogLevel::ERROR);
399
            $this->Flash->error($e->getMessage(), ['params' => $e]);
400
        }
401
402
        return $this->redirect(['_name' => 'modules:view', 'object_type' => $this->objectType, 'id' => $id]);
403
    }
404
405
    /**
406
     * Delete single resource.
407
     *
408
     * @return \Cake\Http\Response|null
409
     */
410
    public function delete(): ?Response
411
    {
412
        $this->getRequest()->allowMethod(['post']);
413
        $id = $this->getRequest()->getData('id');
414
        $ids = $this->getRequest()->getData('ids');
415
        $ids = is_string($ids) ? explode(',', $ids) : $ids;
416
        $ids = empty($ids) ? [$id] : $ids;
417
        try {
418
            $this->apiClient->deleteObjects($ids, $this->objectType);
419
            $eventManager = $this->getEventManager();
420
            foreach ($ids as $id) {
421
                $event = new Event('Controller.afterDelete', $this, ['id' => $id, 'type' => $this->objectType]);
422
                $eventManager->dispatch($event);
423
            }
424
        } catch (BEditaClientException $e) {
425
            $this->log($e->getMessage(), LogLevel::ERROR);
426
            $this->Flash->error($e->getMessage(), ['params' => $e]);
427
            $id = $this->getRequest()->getData('id');
428
            $options = empty($id) ? $this->referer() : ['_name' => 'modules:view', 'object_type' => $this->objectType, 'id' => $id];
429
430
            return $this->redirect($options);
431
        }
432
        $this->Flash->success(__('Object(s) deleted'));
433
434
        return $this->redirect([
435
            '_name' => 'modules:list',
436
            'object_type' => $this->objectType,
437
        ]);
438
    }
439
440
    /**
441
     * Relation data load via API => `GET /:object_type/:id/related/:relation`
442
     *
443
     * @param string|int $id The object ID.
444
     * @param string $relation The relation name.
445
     * @return void
446
     */
447
    public function related($id, string $relation): void
448
    {
449
        if ($id === 'new') {
450
            $this->set('data', []);
451
            $this->setSerialize(['data']);
452
453
            return;
454
        }
455
456
        $this->getRequest()->allowMethod(['get']);
457
        $query = $this->Query->prepare($this->getRequest()->getQueryParams());
458
        try {
459
            $response = $this->apiClient->getRelated($id, $this->objectType, $relation, $query);
460
            $response = $this->ApiFormatter->embedIncluded((array)$response);
461
        } catch (BEditaClientException $error) {
462
            $this->log($error->getMessage(), LogLevel::ERROR);
463
464
            $this->set(compact('error'));
465
            $this->setSerialize(['error']);
466
467
            return;
468
        }
469
470
        $this->Thumbs->urls($response);
471
472
        $this->set((array)$response);
473
        $this->setSerialize(array_keys($response));
474
    }
475
476
    /**
477
     * Load resources of $type callig api `GET /:type/`
478
     * Json response
479
     *
480
     * @param string|int $id the object identifier.
481
     * @param string $type the resource type name.
482
     * @return void
483
     */
484
    public function resources($id, string $type): void
485
    {
486
        $this->getRequest()->allowMethod(['get']);
487
        $query = $this->Query->prepare($this->getRequest()->getQueryParams());
488
        try {
489
            $response = $this->apiClient->get($type, $query);
490
        } catch (BEditaClientException $error) {
491
            $this->log($error, LogLevel::ERROR);
492
493
            $this->set(compact('error'));
494
            $this->setSerialize(['error']);
495
496
            return;
497
        }
498
499
        $this->set((array)$response);
500
        $this->setSerialize(array_keys($response));
501
    }
502
503
    /**
504
     * Relation data load calling api `GET /:object_type/:id/relationships/:relation`
505
     * Json response
506
     *
507
     * @param string|int $id The object ID.
508
     * @param string $relation The relation name.
509
     * @return void
510
     */
511
    public function relationships($id, string $relation): void
512
    {
513
        $this->getRequest()->allowMethod(['get']);
514
        $available = $this->availableRelationshipsUrl($relation);
515
516
        try {
517
            $query = $this->Query->prepare($this->getRequest()->getQueryParams());
518
            $response = $this->apiClient->get($available, $query);
519
520
            $this->Thumbs->urls($response);
521
        } catch (BEditaClientException $ex) {
522
            $this->log($ex->getMessage(), LogLevel::ERROR);
523
524
            $this->set('error', $ex->getMessage());
525
            $this->setSerialize(['error']);
526
527
            return;
528
        }
529
530
        $this->set((array)$response);
531
        $this->setSerialize(array_keys($response));
532
    }
533
534
    /**
535
     * Retrieve URL to get objects available for a relation
536
     *
537
     * @param string $relation The relation name.
538
     * @return string
539
     */
540
    protected function availableRelationshipsUrl(string $relation): string
541
    {
542
        $defaults = [
543
            'children' => '/objects',
544
            'parent' => '/folders',
545
            'parents' => '/folders',
546
        ];
547
        $defaultUrl = (string)Hash::get($defaults, $relation);
548
        if (!empty($defaultUrl)) {
549
            return $defaultUrl;
550
        }
551
552
        $relationsSchema = $this->Schema->getRelationsSchema();
553
        $types = $this->Modules->relatedTypes($relationsSchema, $relation);
554
555
        return count($types) === 1 ? sprintf('/%s', $types[0]) : '/objects?filter[type][]=' . implode('&filter[type][]=', $types);
556
    }
557
558
    /**
559
     * get object properties and format them for index
560
     *
561
     * @param string $objectType objecte type name
562
     * @return array $schema
563
     */
564
    public function getSchemaForIndex($objectType): array
565
    {
566
        $schema = (array)$this->Schema->getSchema($objectType);
567
568
        // if prop is an enum then prepend an empty string for select element
569
        if (!empty($schema['properties'])) {
570
            foreach ($schema['properties'] as &$property) {
571
                if (isset($property['enum'])) {
572
                    array_unshift($property['enum'], '');
573
                }
574
            }
575
        }
576
577
        return $schema;
578
    }
579
580
    /**
581
     * Get objectType
582
     *
583
     * @return string|null
584
     */
585
    public function getObjectType(): ?string
586
    {
587
        return $this->objectType;
588
    }
589
590
    /**
591
     * Set objectType
592
     *
593
     * @param string|null $objectType The object type
594
     * @return void
595
     */
596
    public function setObjectType(?string $objectType): void
597
    {
598
        $this->objectType = $objectType;
599
    }
600
601
    /**
602
     * Set schemasByType and filtersByType, considering relations and schemas.
603
     *
604
     * @param array $relations The relations
605
     * @return void
606
     */
607
    private function setupViewRelations(array $relations): void
608
    {
609
        // setup relations schema
610
        $relationsSchema = $this->Schema->getRelationsSchema();
611
        $this->set('relationsSchema', $relationsSchema);
612
613
        // setup relations metadata
614
        $this->Modules->setupRelationsMeta(
615
            $relationsSchema,
616
            $relations,
617
            $this->Properties->relationsList($this->objectType),
618
            $this->Properties->hiddenRelationsList($this->objectType),
619
            $this->Properties->readonlyRelationsList($this->objectType)
620
        );
621
622
        // set right types, considering the object type relations
623
        $rel = (array)$this->viewBuilder()->getVar('relationsSchema');
624
        $rightTypes = \App\Utility\Schema::rightTypes($rel);
625
        $this->set('rightTypes', $rightTypes);
626
627
        // set schemas for relations right types
628
        $schemasByType = $this->Schema->getSchemasByType($rightTypes);
629
        $this->set('schemasByType', $schemasByType);
630
        $this->set('filtersByType', $this->Properties->filtersByType($rightTypes));
631
    }
632
633
    /**
634
     * Get list of users / no email, no relationships, no links, no schema, no included.
635
     *
636
     * @return void
637
     */
638
    public function users(): void
639
    {
640
        $this->viewBuilder()->setClassName('Json');
641
        $this->getRequest()->allowMethod('get');
642
        $query = array_merge(
643
            $this->getRequest()->getQueryParams(),
644
            ['fields' => 'id,title,username,name,surname']
645
        );
646
        $response = (array)$this->apiClient->get('users', $query);
647
        $response = ApiTools::cleanResponse($response);
648
        $data = (array)Hash::get($response, 'data');
649
        $meta = (array)Hash::get($response, 'meta');
650
        $this->set(compact('data', 'meta'));
651
        $this->setSerialize(['data', 'meta']);
652
    }
653
654
    /**
655
     * Get single resource, minimal data / no relationships, no links, no schema, no included.
656
     *
657
     * @param string $id The object ID
658
     * @return void
659
     */
660
    public function get(string $id): void
661
    {
662
        $this->viewBuilder()->setClassName('Json');
663
        $this->getRequest()->allowMethod('get');
664
        $data = $meta = [];
665
        $response = (array)$this->apiClient->getObject($id, 'objects', $this->getRequest()->getQueryParams());
666
        $type = (string)Hash::get($response, 'data.type');
667
        $filter = (array)$this->getRequest()->getQuery('filter');
668
        $types = (string)Hash::get($filter, 'type');
669
        $filterType = !empty($types) ? explode(',', (string)Hash::get($filter, 'type')) : [];
670
        if (count($filterType) === 0 || in_array($type, $filterType)) {
671
            $query = array_merge(
672
                $this->getRequest()->getQueryParams(),
673
                ['fields' => 'id,title,description,uname,status,media_url']
674
            );
675
            $response = (array)$this->apiClient->getObject($id, $type, $query);
676
            $response = ApiTools::cleanResponse($response);
677
            $data = (array)Hash::get($response, 'data');
678
            $meta = (array)Hash::get($response, 'meta');
679
        }
680
        $this->set(compact('data', 'meta'));
681
        $this->setSerialize(['data', 'meta']);
682
    }
683
684
    /**
685
     * Setup module.
686
     *
687
     * @return \Cake\Http\Response|null
688
     */
689
    public function setup(): ?Response
690
    {
691
        /** @var \Authentication\Identity|null $user */
692
        $user = $this->Authentication->getIdentity();
693
        $roles = (array)$user->get('roles');
694
        if (!in_array('admin', $roles)) {
695
            throw new UnauthorizedException(__('You are not authorized to access here'));
696
        }
697
        $this->getRequest()->allowMethod(['get', 'post']);
698
        if ($this->getRequest()->is('post')) {
699
            try {
700
                $requestData = $this->getRequest()->getData();
701
                $configurationKey = $requestData['configurationKey'] ?? null;
702
                unset($requestData['configurationKey']);
703
                $propertyName = explode('.', $configurationKey)[0];
704
                $subkey = explode('.', $configurationKey)[1];
705
                $propertyValue = (array)Configure::read($propertyName);
706
                $propertyValue = (array)Hash::insert($propertyValue, $subkey, $requestData);
707
                $this->saveApiConfig($propertyName, $propertyValue);
708
                $response = 'Configuration saved';
709
                $this->set('response', $response);
710
                $this->setSerialize(['response']);
711
            } catch (Exception $e) {
712
                $error = $e->getMessage();
713
                $this->set('error', $error);
714
                $this->setSerialize(['error']);
715
            }
716
        }
717
718
        return null;
719
    }
720
}
721