Completed
Push — master ( 7790d6...5fbdff )
by Alberto
24s queued 16s
created

TrashController::index()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 19
nc 2
nop 0
dl 0
loc 28
rs 9.6333
c 0
b 0
f 0
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\EventInterface;
17
use Cake\Http\Response;
18
use Cake\Utility\Hash;
19
use Psr\Log\LogLevel;
20
21
/**
22
 * Trash can controller: list, restore & remove permanently objects
23
 *
24
 * @property \App\Controller\Component\PropertiesComponent $Properties
25
 */
26
class TrashController extends AppController
27
{
28
    /**
29
     * {@inheritDoc}
30
     *
31
     * @codeCoverageIgnore
32
     */
33
    public function initialize(): void
34
    {
35
        parent::initialize();
36
37
        $this->loadComponent('Properties');
38
39
        $this->Modules->setConfig('currentModuleName', 'trash');
40
    }
41
42
    /**
43
     * {@inheritDoc}
44
     *
45
     * @codeCoverageIgnore
46
     */
47
    public function beforeRender(EventInterface $event): ?Response
48
    {
49
        $this->set('moduleLink', ['_name' => 'trash:list']);
50
51
        return parent::beforeRender($event);
52
    }
53
54
    /**
55
     * Display deleted resources list.
56
     *
57
     * @return \Cake\Http\Response|null
58
     * @codeCoverageIgnore
59
     */
60
    public function index(): ?Response
61
    {
62
        $this->getRequest()->allowMethod(['get']);
63
64
        try {
65
            $response = $this->apiClient->getObjects('trash', $this->getRequest()->getQueryParams());
66
        } catch (BEditaClientException $e) {
67
            // Error! Back to dashboard.
68
            $this->log($e->getMessage(), LogLevel::ERROR);
69
            $this->Flash->error($e->getMessage(), ['params' => $e]);
70
71
            return $this->redirect(['_name' => 'dashboard']);
72
        }
73
74
        $this->set('objects', (array)$response['data']);
75
        $this->set('meta', (array)$response['meta']);
76
        $this->set('links', (array)$response['links']);
77
        $this->set('types', ['right' => $this->Modules->objectTypes(false)]);
78
        $this->set('properties', $this->Properties->indexList('trash'));
79
        $this->set('schema', ['properties' => [
80
            'title' => ['type' => 'string'],
81
            'type' => ['type' => 'string'],
82
            'status' => ['type' => 'string'],
83
            'modified' => ['type' => 'date-time'],
84
            'id' => ['type' => 'integer'],
85
        ]]);
86
87
        return null;
88
    }
89
90
    /**
91
     * View single deleted resource.
92
     *
93
     * @param mixed $id Resource ID.
94
     * @return \Cake\Http\Response|null
95
     * @codeCoverageIgnore
96
     */
97
    public function view($id): ?Response
98
    {
99
        $this->getRequest()->allowMethod(['get']);
100
101
        try {
102
            $response = $this->apiClient->getObject($id, 'trash');
103
        } catch (BEditaClientException $e) {
104
            // Error! Back to index.
105
            $this->log($e->getMessage(), LogLevel::ERROR);
106
            $this->Flash->error($e->getMessage(), ['params' => $e]);
107
108
            return $this->redirect(['_name' => 'trash:list']);
109
        }
110
111
        $object = $response['data'];
112
        $schema = $this->Schema->getSchema($object['type']);
113
114
        $this->set(compact('object', 'schema'));
115
        $this->set('properties', $this->Properties->viewGroups($object, $object['type']));
116
117
        return null;
118
    }
119
120
    /**
121
     * Restore resource.
122
     *
123
     * @return \Cake\Http\Response|null
124
     */
125
    public function restore(): ?Response
126
    {
127
        $this->getRequest()->allowMethod(['post']);
128
        $ids = [];
129
        if (!empty($this->getRequest()->getData('ids'))) {
130
            $ids = $this->getRequest()->getData('ids');
131
            if (is_string($ids)) {
132
                $ids = explode(',', (string)$this->getRequest()->getData('ids'));
133
            }
134
        } else {
135
            $ids = [$this->getRequest()->getData('id')];
136
        }
137
        foreach ($ids as $id) {
138
            try {
139
                $this->apiClient->restoreObject($id, 'objects');
140
            } catch (BEditaClientException $e) {
141
                // Error! Back to object view.
142
                $this->log($e->getMessage(), LogLevel::ERROR);
143
                $this->Flash->error($e->getMessage(), ['params' => $e]);
144
145
                if (!empty($this->getRequest()->getData('ids'))) {
146
                    return $this->redirect(['_name' => 'trash:list'] + $this->listQuery());
147
                }
148
149
                return $this->redirect(['_name' => 'trash:view', 'id' => $id]);
150
            }
151
        }
152
153
        return $this->redirect(['_name' => 'trash:list'] + $this->listQuery());
154
    }
155
156
    /**
157
     * Permanently delete resource.
158
     *
159
     * @return \Cake\Http\Response|null
160
     */
161
    public function delete(): ?Response
162
    {
163
        $this->getRequest()->allowMethod(['post']);
164
        $ids = [];
165
        if (!empty($this->getRequest()->getData('ids'))) {
166
            $ids = $this->getRequest()->getData('ids');
167
            if (is_string($ids)) {
168
                $ids = explode(',', (string)$this->getRequest()->getData('ids'));
169
            }
170
        } else {
171
            $ids = [$this->getRequest()->getData('id')];
172
        }
173
        foreach ($ids as $id) {
174
            try {
175
                $this->deleteData($id);
176
            } catch (BEditaClientException $e) {
177
                // Error! Back to object view.
178
                $this->log($e->getMessage(), LogLevel::ERROR);
179
                $this->Flash->error($e->getMessage(), ['params' => $e]);
180
181
                if (!empty($this->getRequest()->getData('ids'))) {
182
                    return $this->redirect(['_name' => 'trash:list'] + $this->listQuery());
183
                }
184
185
                return $this->redirect(['_name' => 'trash:view', 'id' => $id]);
186
            }
187
        }
188
189
        $this->Flash->success(__('Object(s) deleted from trash'));
190
191
        return $this->redirect(['_name' => 'trash:list'] + $this->listQuery());
192
    }
193
194
    /**
195
     * Return query filter array from request to be used in redirects
196
     *
197
     * @return array
198
     */
199
    protected function listQuery(): array
200
    {
201
        $query = $this->getRequest()->getData('query');
202
        if (empty($query)) {
203
            return [];
204
        }
205
        $query = htmlspecialchars_decode($query);
206
207
        return (array)unserialize($query);
208
    }
209
210
    /**
211
     * Permanently delete multiple data.
212
     * If filter type is active, empty trash by type
213
     *
214
     * @return \Cake\Http\Response|null
215
     */
216
    public function emptyTrash(): ?Response
217
    {
218
        $this->getRequest()->allowMethod(['post']);
219
220
        $query = array_filter(array_intersect_key($this->listQuery(), ['filter' => '']));
221
        // cycle over trash results
222
        $response = $this->apiClient->getObjects('trash', $query);
223
        $counter = 0;
224
        while (Hash::get($response, 'meta.pagination.count', 0) > 0) {
225
            foreach ($response['data'] as $data) {
226
                try {
227
                    $this->deleteData($data['id']);
228
                    $counter++;
229
                } catch (BEditaClientException $e) {
230
                    // Error! Back to trash index.
231
                    $this->log($e->getMessage(), LogLevel::ERROR);
232
                    $this->Flash->error($e->getMessage(), ['params' => $e]);
233
234
                    return $this->redirect(['_name' => 'trash:list'] + $this->listQuery());
235
                }
236
            }
237
            $response = $this->apiClient->getObjects('trash', $query);
238
        }
239
        $this->Flash->success(__(sprintf('%d objects deleted from trash', $counter)));
240
241
        return $this->redirect(['_name' => 'trash:list'] + $this->listQuery());
242
    }
243
244
    /**
245
     * Delete data and related streams, if any.
246
     *
247
     * @param string $id Object ID
248
     * @return void
249
     */
250
    public function deleteData(string $id): void
251
    {
252
        $response = $this->apiClient->get('/streams', ['filter' => ['object_id' => $id]]);
253
        $streams = (array)Hash::get($response, 'data');
254
        $this->apiClient->remove($id);
255
        foreach ($streams as $stream) {
256
            $this->apiClient->delete(sprintf('/streams/%s', $stream['id']));
257
        }
258
    }
259
}
260