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 BEdita\SDK\BEditaClientException; |
16
|
|
|
use Cake\Event\Event; |
17
|
|
|
use Cake\Http\Response; |
18
|
|
|
use Cake\Utility\Hash; |
19
|
|
|
use Psr\Log\LogLevel; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Modules controller: list, add, edit, remove objects |
23
|
|
|
* |
24
|
|
|
* @property \App\Controller\Component\CategoriesComponent $Categories |
25
|
|
|
* @property \App\Controller\Component\HistoryComponent $History |
26
|
|
|
* @property \App\Controller\Component\ObjectsEditorsComponent $ObjectsEditors |
27
|
|
|
* @property \App\Controller\Component\ProjectConfigurationComponent $ProjectConfiguration |
28
|
|
|
* @property \App\Controller\Component\PropertiesComponent $Properties |
29
|
|
|
* @property \App\Controller\Component\QueryComponent $Query |
30
|
|
|
* @property \App\Controller\Component\ThumbsComponent $Thumbs |
31
|
|
|
* @property \BEdita\WebTools\Controller\Component\ApiFormatterComponent $ApiFormatter |
32
|
|
|
*/ |
33
|
|
|
class ModulesController extends AppController |
34
|
|
|
{ |
35
|
|
|
/** |
36
|
|
|
* Object type currently used |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
protected $objectType = null; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* {@inheritDoc} |
44
|
|
|
*/ |
45
|
|
|
public function initialize(): void |
46
|
|
|
{ |
47
|
|
|
parent::initialize(); |
48
|
|
|
|
49
|
|
|
$this->loadComponent('Categories'); |
50
|
|
|
$this->loadComponent('History'); |
51
|
|
|
$this->loadComponent('ObjectsEditors'); |
52
|
|
|
$this->loadComponent('Properties'); |
53
|
|
|
$this->loadComponent('ProjectConfiguration'); |
54
|
|
|
$this->loadComponent('Query'); |
55
|
|
|
$this->loadComponent('Thumbs'); |
56
|
|
|
$this->loadComponent('BEdita/WebTools.ApiFormatter'); |
57
|
|
|
|
58
|
|
|
if (!empty($this->request)) { |
59
|
|
|
$this->objectType = $this->request->getParam('object_type'); |
60
|
|
|
$this->Modules->setConfig('currentModuleName', $this->objectType); |
61
|
|
|
$this->Schema->setConfig('type', $this->objectType); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
$this->Security->setConfig('unlockedActions', ['save']); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* {@inheritDoc} |
69
|
|
|
* @codeCoverageIgnore |
70
|
|
|
*/ |
71
|
|
|
public function beforeRender(Event $event): ?Response |
72
|
|
|
{ |
73
|
|
|
$this->set('objectType', $this->objectType); |
74
|
|
|
|
75
|
|
|
return parent::beforeRender($event); |
|
|
|
|
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Display resources list. |
80
|
|
|
* |
81
|
|
|
* @return \Cake\Http\Response|null |
82
|
|
|
*/ |
83
|
|
|
public function index(): ?Response |
84
|
|
|
{ |
85
|
|
|
$this->request->allowMethod(['get']); |
86
|
|
|
|
87
|
|
|
// handle filter and query parameters using session |
88
|
|
|
$result = $this->applySessionFilter(); |
89
|
|
|
if ($result != null) { |
90
|
|
|
return $result; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
try { |
94
|
|
|
$response = $this->apiClient->getObjects($this->objectType, $this->Query->index()); |
95
|
|
|
} catch (BEditaClientException $e) { |
96
|
|
|
$this->log($e, LogLevel::ERROR); |
97
|
|
|
$this->Flash->error($e->getMessage(), ['params' => $e]); |
98
|
|
|
// remove session filter to avoid error repetition |
99
|
|
|
$session = $this->request->getSession(); |
100
|
|
|
$session->delete(sprintf('%s.filter', $this->Modules->getConfig('currentModuleName'))); |
101
|
|
|
|
102
|
|
|
return $this->redirect(['_name' => 'dashboard']); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
$this->ProjectConfiguration->read(); |
106
|
|
|
|
107
|
|
|
$response = $this->ApiFormatter->embedIncluded((array)$response); |
108
|
|
|
$objects = (array)Hash::get($response, 'data'); |
109
|
|
|
$this->set('objects', $objects); |
110
|
|
|
$this->set('meta', (array)Hash::get($response, 'meta')); |
111
|
|
|
$this->set('links', (array)Hash::get($response, 'links')); |
112
|
|
|
$this->set('types', ['right' => $this->Schema->descendants($this->objectType)]); |
113
|
|
|
|
114
|
|
|
$this->set('properties', $this->Properties->indexList($this->objectType)); |
115
|
|
|
|
116
|
|
|
// base/custom filters for filter view |
117
|
|
|
$this->set('filter', $this->Properties->filterList($this->objectType)); |
118
|
|
|
|
119
|
|
|
// base/custom bulk actions for index view |
120
|
|
|
$this->set('bulkActions', $this->Properties->bulkList($this->objectType)); |
121
|
|
|
|
122
|
|
|
// objectTypes schema |
123
|
|
|
$this->set('schema', $this->getSchemaForIndex($this->objectType)); |
124
|
|
|
|
125
|
|
|
// set prevNext for views navigations |
126
|
|
|
$this->setObjectNav($objects); |
127
|
|
|
|
128
|
|
|
return null; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* View single resource. |
133
|
|
|
* |
134
|
|
|
* @param string|int $id Resource ID. |
135
|
|
|
* @return \Cake\Http\Response|null |
136
|
|
|
*/ |
137
|
|
|
public function view($id): ?Response |
138
|
|
|
{ |
139
|
|
|
$this->request->allowMethod(['get']); |
140
|
|
|
|
141
|
|
|
try { |
142
|
|
|
$query = ['count' => 'all']; |
143
|
|
|
$response = $this->apiClient->getObject($id, $this->objectType, $query); |
144
|
|
|
} catch (BEditaClientException $e) { |
145
|
|
|
// Error! Back to index. |
146
|
|
|
$this->log($e, LogLevel::ERROR); |
147
|
|
|
$this->Flash->error(__('Error retrieving the requested content'), ['params' => $e]); |
148
|
|
|
|
149
|
|
|
return $this->redirect(['_name' => 'modules:list', 'object_type' => $this->objectType]); |
150
|
|
|
} |
151
|
|
|
$this->ProjectConfiguration->read(); |
152
|
|
|
|
153
|
|
|
$revision = Hash::get($response, 'meta.schema.' . $this->objectType . '.revision', null); |
154
|
|
|
$schema = $this->Schema->getSchema($this->objectType, $revision); |
155
|
|
|
|
156
|
|
|
$object = $response['data']; |
157
|
|
|
|
158
|
|
|
// setup `currentAttributes` and recover failure data from session. |
159
|
|
|
$this->Modules->setupAttributes($object); |
160
|
|
|
|
161
|
|
|
$included = (!empty($response['included'])) ? $response['included'] : []; |
162
|
|
|
$typeIncluded = (array)Hash::combine($included, '{n}.id', '{n}', '{n}.type'); |
163
|
|
|
$streams = Hash::get($typeIncluded, 'streams'); |
164
|
|
|
$this->History->load($id, $object); |
165
|
|
|
$this->set(compact('object', 'included', 'schema', 'streams')); |
166
|
|
|
$this->set('properties', $this->Properties->viewGroups($object, $this->objectType)); |
167
|
|
|
|
168
|
|
|
// setup relations metadata |
169
|
|
|
$this->Modules->setupRelationsMeta( |
170
|
|
|
$this->Schema->getRelationsSchema(), |
171
|
|
|
$object['relationships'], |
172
|
|
|
$this->Properties->relationsList($this->objectType) |
173
|
|
|
); |
174
|
|
|
|
175
|
|
|
$rightTypes = \App\Utility\Schema::rightTypes($this->viewVars['relationsSchema']); |
176
|
|
|
|
177
|
|
|
// set schemas for relations right types |
178
|
|
|
$schemasByType = $this->Schema->getSchemasByType($rightTypes); |
179
|
|
|
$this->set('schemasByType', $schemasByType); |
180
|
|
|
|
181
|
|
|
$this->set('filtersByType', $this->Properties->filtersByType($rightTypes)); |
182
|
|
|
|
183
|
|
|
// set objectNav |
184
|
|
|
$objectNav = $this->getObjectNav((string)$id); |
185
|
|
|
$this->set('objectNav', $objectNav); |
186
|
|
|
|
187
|
|
|
$this->ObjectsEditors->update((string)$id); |
188
|
|
|
|
189
|
|
|
return null; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* View single resource by id, doing a proper redirect (302) to resource module view by type. |
194
|
|
|
* If no resource found by ID, redirect to referer. |
195
|
|
|
* |
196
|
|
|
* @param string|int $id Resource ID. |
197
|
|
|
* @return \Cake\Http\Response|null |
198
|
|
|
*/ |
199
|
|
|
public function uname($id): ?Response |
200
|
|
|
{ |
201
|
|
|
try { |
202
|
|
|
$response = $this->apiClient->get(sprintf('/objects/%s', $id)); |
203
|
|
|
} catch (BEditaClientException $e) { |
204
|
|
|
$msg = $e->getMessage(); |
205
|
|
|
$error = $e->getCode() === 404 ? |
206
|
|
|
sprintf(__('Resource "%s" not found', true), $id) : |
|
|
|
|
207
|
|
|
sprintf(__('Resource "%s" not available. Error: %s', true), $id, $msg); |
208
|
|
|
$this->Flash->error($error); |
209
|
|
|
|
210
|
|
|
return $this->redirect($this->referer()); |
211
|
|
|
} |
212
|
|
|
$_name = 'modules:view'; |
213
|
|
|
$object_type = $response['data']['type']; |
214
|
|
|
$id = $response['data']['id']; |
215
|
|
|
|
216
|
|
|
return $this->redirect(compact('_name', 'object_type', 'id')); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Display new resource form. |
221
|
|
|
* |
222
|
|
|
* @return \Cake\Http\Response|null |
223
|
|
|
*/ |
224
|
|
|
public function create(): ?Response |
225
|
|
|
{ |
226
|
|
|
$this->viewBuilder()->setTemplate('view'); |
227
|
|
|
|
228
|
|
|
// Create stub object with empty `attributes`. |
229
|
|
|
$schema = $this->Schema->getSchema(); |
230
|
|
|
if (!is_array($schema)) { |
231
|
|
|
$this->Flash->error(__('Cannot create abstract objects or objects without schema')); |
232
|
|
|
|
233
|
|
|
return $this->redirect(['_name' => 'modules:list', 'object_type' => $this->objectType]); |
234
|
|
|
} |
235
|
|
|
$attributes = array_fill_keys( |
236
|
|
|
array_keys( |
237
|
|
|
array_filter( |
238
|
|
|
$schema['properties'], |
239
|
|
|
function ($schema) { |
240
|
|
|
return empty($schema['readOnly']); |
241
|
|
|
} |
242
|
|
|
) |
243
|
|
|
), |
244
|
|
|
'' |
245
|
|
|
); |
246
|
|
|
$object = [ |
247
|
|
|
'type' => $this->objectType, |
248
|
|
|
'attributes' => $attributes, |
249
|
|
|
]; |
250
|
|
|
|
251
|
|
|
$this->set(compact('object', 'schema')); |
252
|
|
|
$this->set('properties', $this->Properties->viewGroups($object, $this->objectType)); |
253
|
|
|
$this->ProjectConfiguration->read(); |
254
|
|
|
|
255
|
|
|
// setup relations metadata |
256
|
|
|
$relationships = (array)Hash::get($schema, 'relations'); |
257
|
|
|
$this->Modules->setupRelationsMeta($this->Schema->getRelationsSchema(), $relationships); |
258
|
|
|
|
259
|
|
|
return null; |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
/** |
263
|
|
|
* Create new object from ajax request. |
264
|
|
|
* |
265
|
|
|
* @return void |
266
|
|
|
*/ |
267
|
|
|
public function save(): void |
268
|
|
|
{ |
269
|
|
|
$this->viewBuilder()->setClassName('Json'); // force json response |
270
|
|
|
$this->request->allowMethod(['post']); |
271
|
|
|
$requestData = $this->prepareRequest($this->objectType); |
272
|
|
|
unset($requestData['_csrfToken']); |
273
|
|
|
// extract related objects data |
274
|
|
|
$relatedData = (array)Hash::get($requestData, '_api'); |
275
|
|
|
unset($requestData['_api']); |
276
|
|
|
|
277
|
|
|
try { |
278
|
|
|
// upload file (if available) |
279
|
|
|
$this->Modules->upload($requestData); |
280
|
|
|
|
281
|
|
|
// save data |
282
|
|
|
$response = $this->apiClient->save($this->objectType, $requestData); |
283
|
|
|
$objectId = (string)Hash::get($response, 'data.id'); |
284
|
|
|
$this->Modules->saveRelated($objectId, $this->objectType, $relatedData); |
285
|
|
|
} catch (BEditaClientException $error) { |
286
|
|
|
$this->log($error->getMessage(), LogLevel::ERROR); |
287
|
|
|
$this->Flash->error($error->getMessage(), ['params' => $error]); |
288
|
|
|
|
289
|
|
|
$this->set(['error' => $error->getAttributes()]); |
290
|
|
|
$this->set('_serialize', ['error']); |
291
|
|
|
|
292
|
|
|
// set session data to recover form |
293
|
|
|
$this->Modules->setDataFromFailedSave($this->objectType, $requestData); |
294
|
|
|
|
295
|
|
|
return; |
296
|
|
|
} |
297
|
|
|
if ($response['data']) { |
298
|
|
|
$response['data'] = [ $response['data'] ]; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
$this->Thumbs->urls($response); |
302
|
|
|
|
303
|
|
|
$this->set((array)$response); |
304
|
|
|
$this->set('_serialize', array_keys($response)); |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* Clone single object. |
309
|
|
|
* |
310
|
|
|
* @param string|int $id Object ID. |
311
|
|
|
* @return \Cake\Http\Response|null |
312
|
|
|
*/ |
313
|
|
|
public function clone($id): ?Response |
314
|
|
|
{ |
315
|
|
|
$this->viewBuilder()->setTemplate('view'); |
316
|
|
|
|
317
|
|
|
$schema = $this->Schema->getSchema(); |
318
|
|
|
if (!is_array($schema)) { |
319
|
|
|
$this->Flash->error(__('Cannot create abstract objects or objects without schema')); |
320
|
|
|
|
321
|
|
|
return $this->redirect(['_name' => 'modules:list', 'object_type' => $this->objectType]); |
322
|
|
|
} |
323
|
|
|
try { |
324
|
|
|
$response = $this->apiClient->getObject($id, $this->objectType); |
325
|
|
|
$attributes = $response['data']['attributes']; |
326
|
|
|
$attributes['uname'] = ''; |
327
|
|
|
unset($attributes['relationships']); |
328
|
|
|
$attributes['title'] = $this->request->getQuery('title'); |
329
|
|
|
} catch (BEditaClientException $e) { |
330
|
|
|
$this->log($e, LogLevel::ERROR); |
331
|
|
|
$this->Flash->error($e->getMessage(), ['params' => $e]); |
332
|
|
|
|
333
|
|
|
return $this->redirect(['_name' => 'modules:view', 'object_type' => $this->objectType, 'id' => $id]); |
334
|
|
|
} |
335
|
|
|
$object = [ |
336
|
|
|
'type' => $this->objectType, |
337
|
|
|
'attributes' => $attributes, |
338
|
|
|
]; |
339
|
|
|
$this->History->load($id, $object); |
340
|
|
|
$this->set(compact('object', 'schema')); |
341
|
|
|
$this->set('properties', $this->Properties->viewGroups($object, $this->objectType)); |
342
|
|
|
|
343
|
|
|
return null; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* Delete single resource. |
348
|
|
|
* |
349
|
|
|
* @return \Cake\Http\Response|null |
350
|
|
|
*/ |
351
|
|
|
public function delete(): ?Response |
352
|
|
|
{ |
353
|
|
|
$this->request->allowMethod(['post']); |
354
|
|
|
$ids = []; |
355
|
|
|
if (!empty($this->request->getData('ids'))) { |
356
|
|
|
if (is_string($this->request->getData('ids'))) { |
357
|
|
|
$ids = explode(',', $this->request->getData('ids')); |
|
|
|
|
358
|
|
|
} |
359
|
|
|
} else { |
360
|
|
|
$ids = [$this->request->getData('id')]; |
361
|
|
|
} |
362
|
|
|
foreach ($ids as $id) { |
363
|
|
|
try { |
364
|
|
|
$this->apiClient->deleteObject($id, $this->objectType); |
365
|
|
|
} catch (BEditaClientException $e) { |
366
|
|
|
$this->log($e, LogLevel::ERROR); |
367
|
|
|
$this->Flash->error($e->getMessage(), ['params' => $e]); |
368
|
|
|
if (!empty($this->request->getData('id'))) { |
369
|
|
|
return $this->redirect(['_name' => 'modules:view', 'object_type' => $this->objectType, 'id' => $this->request->getData('id')]); |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
return $this->redirect(['_name' => 'modules:view', 'object_type' => $this->objectType, 'id' => $id]); |
373
|
|
|
} |
374
|
|
|
} |
375
|
|
|
$this->Flash->success(__('Object(s) deleted')); |
376
|
|
|
|
377
|
|
|
return $this->redirect([ |
378
|
|
|
'_name' => 'modules:list', |
379
|
|
|
'object_type' => $this->objectType, |
380
|
|
|
]); |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
/** |
384
|
|
|
* Relation data load via API => `GET /:object_type/:id/related/:relation` |
385
|
|
|
* |
386
|
|
|
* @param string|int $id The object ID. |
387
|
|
|
* @param string $relation The relation name. |
388
|
|
|
* @return void |
389
|
|
|
*/ |
390
|
|
|
public function related($id, string $relation): void |
391
|
|
|
{ |
392
|
|
|
if ($id === 'new') { |
393
|
|
|
$this->set('data', []); |
394
|
|
|
$this->set('_serialize', ['data']); |
395
|
|
|
|
396
|
|
|
return; |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
$this->request->allowMethod(['get']); |
400
|
|
|
$query = $this->Query->prepare($this->request->getQueryParams()); |
401
|
|
|
try { |
402
|
|
|
$response = $this->apiClient->getRelated($id, $this->objectType, $relation, $query); |
403
|
|
|
$response = $this->ApiFormatter->embedIncluded((array)$response); |
404
|
|
|
} catch (BEditaClientException $error) { |
405
|
|
|
$this->log($error, LogLevel::ERROR); |
406
|
|
|
|
407
|
|
|
$this->set(compact('error')); |
408
|
|
|
$this->set('_serialize', ['error']); |
409
|
|
|
|
410
|
|
|
return; |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
$this->Thumbs->urls($response); |
414
|
|
|
|
415
|
|
|
$this->set((array)$response); |
416
|
|
|
$this->set('_serialize', array_keys($response)); |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
/** |
420
|
|
|
* Load resources of $type callig api `GET /:type/` |
421
|
|
|
* Json response |
422
|
|
|
* |
423
|
|
|
* @param string|int $id the object identifier. |
424
|
|
|
* @param string $type the resource type name. |
425
|
|
|
* @return void |
426
|
|
|
*/ |
427
|
|
|
public function resources($id, string $type): void |
428
|
|
|
{ |
429
|
|
|
$this->request->allowMethod(['get']); |
430
|
|
|
$query = $this->Query->prepare($this->request->getQueryParams()); |
431
|
|
|
try { |
432
|
|
|
$response = $this->apiClient->get($type, $query); |
433
|
|
|
} catch (BEditaClientException $error) { |
434
|
|
|
$this->log($error, LogLevel::ERROR); |
435
|
|
|
|
436
|
|
|
$this->set(compact('error')); |
437
|
|
|
$this->set('_serialize', ['error']); |
438
|
|
|
|
439
|
|
|
return; |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
$this->set((array)$response); |
443
|
|
|
$this->set('_serialize', array_keys($response)); |
|
|
|
|
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* Relation data load callig api `GET /:object_type/:id/relationships/:relation` |
448
|
|
|
* Json response |
449
|
|
|
* |
450
|
|
|
* @param string|int $id The object ID. |
451
|
|
|
* @param string $relation The relation name. |
452
|
|
|
* @return void |
453
|
|
|
*/ |
454
|
|
|
public function relationships($id, string $relation): void |
455
|
|
|
{ |
456
|
|
|
$this->request->allowMethod(['get']); |
457
|
|
|
$available = $this->availableRelationshipsUrl($relation); |
458
|
|
|
|
459
|
|
|
try { |
460
|
|
|
$query = $this->Query->prepare($this->request->getQueryParams()); |
461
|
|
|
$response = $this->apiClient->get($available, $query); |
462
|
|
|
|
463
|
|
|
$this->Thumbs->urls($response); |
464
|
|
|
} catch (BEditaClientException $ex) { |
465
|
|
|
$this->log($ex, LogLevel::ERROR); |
466
|
|
|
|
467
|
|
|
$this->set([ |
468
|
|
|
'error' => $ex->getMessage(), |
469
|
|
|
'_serialize' => ['error'], |
470
|
|
|
]); |
471
|
|
|
|
472
|
|
|
return; |
473
|
|
|
} |
474
|
|
|
|
475
|
|
|
$this->set((array)$response); |
476
|
|
|
$this->set('_serialize', array_keys($response)); |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
/** |
480
|
|
|
* Retrieve URL to get objects available for a relation |
481
|
|
|
* |
482
|
|
|
* @param string $relation The relation name. |
483
|
|
|
* @return string |
484
|
|
|
*/ |
485
|
|
|
protected function availableRelationshipsUrl(string $relation): string |
486
|
|
|
{ |
487
|
|
|
$defaults = [ |
488
|
|
|
'children' => '/objects', |
489
|
|
|
'parent' => '/folders', |
490
|
|
|
'parents' => '/folders', |
491
|
|
|
]; |
492
|
|
|
$defaultUrl = (string)Hash::get($defaults, $relation); |
493
|
|
|
if (!empty($defaultUrl)) { |
494
|
|
|
return $defaultUrl; |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
$relationsSchema = $this->Schema->getRelationsSchema(); |
498
|
|
|
$types = $this->Modules->relatedTypes($relationsSchema, $relation); |
499
|
|
|
if (count($types) === 1) { |
500
|
|
|
return sprintf('/%s', $types[0]); |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
return '/objects?filter[type][]=' . implode('&filter[type][]=', $types); |
504
|
|
|
} |
505
|
|
|
|
506
|
|
|
/** |
507
|
|
|
* get object properties and format them for index |
508
|
|
|
* |
509
|
|
|
* @param string $objectType objecte type name |
510
|
|
|
* |
511
|
|
|
* @return array $schema |
512
|
|
|
*/ |
513
|
|
|
public function getSchemaForIndex($objectType): array |
514
|
|
|
{ |
515
|
|
|
$schema = (array)$this->Schema->getSchema($objectType); |
516
|
|
|
|
517
|
|
|
// if prop is an enum then prepend an empty string for select element |
518
|
|
|
if (!empty($schema['properties'])) { |
519
|
|
|
foreach ($schema['properties'] as &$property) { |
520
|
|
|
if (isset($property['enum'])) { |
521
|
|
|
array_unshift($property['enum'], ''); |
522
|
|
|
} |
523
|
|
|
} |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
return $schema; |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
/** |
530
|
|
|
* List categories for the object type. |
531
|
|
|
* |
532
|
|
|
* @return \Cake\Http\Response|null |
533
|
|
|
*/ |
534
|
|
|
public function listCategories() |
535
|
|
|
{ |
536
|
|
|
$this->viewBuilder()->setTemplate('categories'); |
537
|
|
|
|
538
|
|
|
$this->request->allowMethod(['get']); |
539
|
|
|
$response = $this->Categories->index($this->objectType, $this->request->getQueryParams()); |
540
|
|
|
$resources = $this->Categories->map($response); |
541
|
|
|
$roots = $this->Categories->getAvailableRoots($resources); |
542
|
|
|
$categoriesTree = $this->Categories->tree($resources); |
543
|
|
|
|
544
|
|
|
$this->set(compact('resources', 'roots', 'categoriesTree')); |
545
|
|
|
$this->set('meta', (array)$response['meta']); |
546
|
|
|
$this->set('links', (array)$response['links']); |
547
|
|
|
$this->set('schema', $this->Schema->getSchema()); |
548
|
|
|
$this->set('properties', $this->Properties->indexList('categories')); |
549
|
|
|
$this->set('filter', $this->Properties->filterList('categories')); |
550
|
|
|
$this->set('object_types', [$this->objectType]); |
551
|
|
|
|
552
|
|
|
return null; |
553
|
|
|
} |
554
|
|
|
|
555
|
|
|
/** |
556
|
|
|
* Save category. |
557
|
|
|
* |
558
|
|
|
* @return \Cake\Http\Response|null |
559
|
|
|
*/ |
560
|
|
|
public function saveCategory(): ?Response |
561
|
|
|
{ |
562
|
|
|
$this->request->allowMethod(['post']); |
563
|
|
|
|
564
|
|
|
try { |
565
|
|
|
$this->Categories->save($this->request->getData()); |
|
|
|
|
566
|
|
|
} catch (BEditaClientException $e) { |
567
|
|
|
$this->log($e, 'error'); |
568
|
|
|
$this->Flash->error($e->getMessage(), ['params' => $e]); |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
return $this->redirect([ |
572
|
|
|
'_name' => 'modules:categories:index', |
573
|
|
|
'object_type' => $this->objectType, |
574
|
|
|
]); |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
/** |
578
|
|
|
* Remove single category. |
579
|
|
|
* |
580
|
|
|
* @param string $id Category ID. |
581
|
|
|
* |
582
|
|
|
* @return \Cake\Http\Response|null |
583
|
|
|
*/ |
584
|
|
|
public function removeCategory(string $id): ?Response |
585
|
|
|
{ |
586
|
|
|
try { |
587
|
|
|
$type = $this->request->getData('object_type_name'); |
588
|
|
|
$this->Categories->delete($id, $type); |
|
|
|
|
589
|
|
|
} catch (BEditaClientException $e) { |
590
|
|
|
$this->log($e, 'error'); |
591
|
|
|
$this->Flash->error($e->getMessage(), ['params' => $e]); |
592
|
|
|
} |
593
|
|
|
|
594
|
|
|
return $this->redirect([ |
595
|
|
|
'_name' => 'modules:categories:index', |
596
|
|
|
'object_type' => $this->objectType, |
597
|
|
|
]); |
598
|
|
|
} |
599
|
|
|
} |
600
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
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.