ManageController::index()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 14
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 20
rs 9.4285
1
<?php
2
/**
3
 * Licensed under The GPL-3.0 License
4
 * For full copyright and license information, please see the LICENSE.txt
5
 * Redistributions of files must retain the above copyright notice.
6
 *
7
 * @since    2.0.0
8
 * @author   Christopher Castro <[email protected]>
9
 * @link     http://www.quickappscms.org
10
 * @license  http://opensource.org/licenses/gpl-3.0.html GPL-3.0 License
11
 */
12
namespace Block\Controller\Admin;
13
14
use Block\Controller\AppController;
15
use Locale\Utility\LocaleToolbox;
16
17
/**
18
 * Block manager controller.
19
 *
20
 * Allow CRUD for blocks.
21
 *
22
 * @property \Block\Model\Table\BlocksTable $Blocks
23
 * @property \Block\Model\Table\BlocksTable $BlockRegions
24
 * @property \Menu\Controller\Component\BreadcrumbComponent $Breadcrumb
25
 */
26
class ManageController extends AppController
27
{
28
29
    /**
30
     * Shows a list of all the blocks & widgets.
31
     *
32
     * @return void
33
     */
34
    public function index()
35
    {
36
        $this->loadModel('Block.Blocks');
37
        if ($this->request->isPost()) {
38
            if ($this->_reorder()) {
39
                $this->Flash->success(__d('block', 'Blocks ordering updated!'));
40
            }
41
            $this->redirect(['plugin' => 'Block', 'controller' => 'manage', 'action' => 'index']);
42
        }
43
44
        $front = $this->Blocks->inFrontTheme();
45
        $back = $this->Blocks->inBackTheme();
46
        $unused = $this->Blocks->unused();
47
48
        $this->set(compact('front', 'back', 'unused'));
49
        $this->title(__d('block', 'Site Blocks'));
50
        $this->Breadcrumb
51
            ->push('/admin/system/structure')
52
            ->push(__d('block', 'Manage Blocks'), '#');
53
    }
54
55
    /**
56
     * Creates a new custom block.
57
     *
58
     * @return void
59
     */
60
    public function add()
61
    {
62
        $this->loadModel('Block.Blocks');
63
        $block = $this->Blocks->newEntity();
64
        $block->set('region', []);
65
66
        if ($this->request->data()) {
67
            $block = $this->_patchEntity($block);
68
69
            if (!$block->errors()) {
70
                if ($this->Blocks->save($block)) {
71
                    $this->Flash->success(__d('block', 'Block created.'));
72
                    $this->redirect(['plugin' => 'Block', 'controller' => 'manage', 'action' => 'edit', $block->id]);
73
                } else {
74
                    $this->Flash->danger(__d('block', 'Block could not be created, please check your information.'));
75
                }
76
            } else {
77
                $this->Flash->danger(__d('block', 'Block could not be created, please check your information.'));
78
            }
79
        }
80
81
        $this->_setLanguages();
82
        $this->_setRoles();
83
        $this->_setRegions();
84
        $this->set('block', $block);
85
        $this->title(__d('block', 'Create New Block'));
86
        $this->Breadcrumb
87
            ->push('/admin/system/structure')
88
            ->push(__d('block', 'Manage Blocks'), ['plugin' => 'Block', 'controller' => 'manage', 'action' => 'index'])
89
            ->push(__d('block', 'Create New Block'), '#');
90
    }
91
92
    /**
93
     * Edits the given block by ID.
94
     *
95
     * The event `Block.<handler>.validate` will be automatically triggered,
96
     * so custom block's (those handled by plugins <> "Block") can be validated
97
     * before persisted.
98
     *
99
     * @param string $id Block's ID
100
     * @return void
101
     * @throws \Cake\ORM\Exception\RecordNotFoundException if no block is not found
102
     */
103
    public function edit($id)
104
    {
105
        $this->loadModel('Block.Blocks');
106
        $block = $this->Blocks->get($id, ['flatten' => true, 'contain' => ['BlockRegions', 'Roles']]);
107
108
        if ($this->request->data()) {
109
            $block->accessible('id', false);
110
            $block->accessible('handler', false);
111
            $block = $this->_patchEntity($block);
112
113
            if (!$block->errors()) {
114
                if ($this->Blocks->save($block)) {
115
                    $this->Flash->success(__d('block', 'Block updated!'));
116
                    $this->redirect($this->referer());
117
                } else {
118
                    $this->Flash->success(__d('block', 'Your information could not be saved, please try again.'));
119
                }
120
            } else {
121
                $this->Flash->danger(__d('block', 'Block could not be updated, please check your information.'));
122
            }
123
        }
124
125
        $this->set(compact('block'));
126
        $this->_setLanguages();
127
        $this->_setRoles();
128
        $this->_setRegions($block);
129
        $this->title(__d('block', 'Editing Block'));
130
        $this->Breadcrumb
131
            ->push('/admin/system/structure')
132
            ->push(__d('block', 'Manage Blocks'), ['plugin' => 'Block', 'controller' => 'manage', 'action' => 'index'])
133
            ->push(__d('block', 'Editing Block'), '#');
134
    }
135
136
    /**
137
     * Deletes the given block by ID.
138
     *
139
     * Only custom blocks can be deleted (those with "Block" has handler).
140
     *
141
     * @param string $id Block's ID
142
     * @return void Redirects to previous page
143
     * @throws \Cake\ORM\Exception\RecordNotFoundException if no record can be found
144
     *  given a primary key value
145
     * @throws \InvalidArgumentException When $primaryKey has an incorrect number
146
     *  of elements
147
     */
148
    public function delete($id)
149
    {
150
        $this->loadModel('Block.Blocks');
151
        $block = $this->Blocks->find()
152
            ->where(['id' => $id])
153
            ->first();
154
155
        if ($block &&
156
            ($block->handler == 'Block' || !empty($block->copy_id))
157
        ) {
158
            if ($this->Blocks->delete($block)) {
159
                $this->Flash->success(__d('block', 'Block was successfully removed!'));
160
            } else {
161
                $this->Flash->danger(__d('block', 'Block could not be removed'));
162
            }
163
        } else {
164
            $this->Flash->warning(__d('block', 'Block not found!'));
165
        }
166
167
        $this->title(__d('block', 'Delete Block'));
168
        $this->redirect($this->referer());
169
    }
170
171
    /**
172
     * Edits the given block by ID.
173
     *
174
     * @param string $id Block's ID
175
     * @return void Redirects to previous page
176
     * @throws \Cake\ORM\Exception\RecordNotFoundException if no block is not found
177
     */
178
    public function duplicate($id)
179
    {
180
        $this->loadModel('Block.Blocks');
181
        $original = $this->Blocks->get((int)$id);
182
        $new = $this->Blocks->newEntity($original->toArray());
183
        $new->set('copy_id', $original->id);
184
        $new->unsetProperty('id');
185
        $new->isNew(true);
186
187
        if ($this->Blocks->save($new)) {
188
            $this->Flash->success(__d('block', 'Block has been duplicated, it can be found under the "Unused or Unassigned" section.'));
189
        } else {
190
            $this->Flash->danger(__d('block', 'Block could not be duplicated, please try again.'));
191
        }
192
193
        $this->title(__d('block', 'Duplicate Block'));
194
        $this->redirect($this->referer() . '#unused-blocks');
195
    }
196
197
    /**
198
     * Reorders blocks based on the order provided via POST.
199
     *
200
     * @return bool True on success, false otherwise
201
     */
202
    protected function _reorder()
203
    {
204
        if (!empty($this->request->data['regions'])) {
205
            foreach ($this->request->data['regions'] as $theme => $regions) {
206
                foreach ($regions as $region => $ids) {
207
                    $ordering = 0;
208
                    foreach ($ids as $id) {
209
                        $blockRegion = $this->Blocks
210
                            ->BlockRegions
211
                            ->newEntity([
212
                                'id' => $id,
213
                                'theme' => $theme,
214
                                'region' => $region,
215
                                'ordering' => $ordering
216
                            ]);
217
                        $blockRegion->isNew(false);
218
                        $this->Blocks->BlockRegions->save($blockRegion);
219
                        $ordering++;
220
                    }
221
                }
222
            }
223
224
            return true;
225
        }
226
227
        return false;
228
    }
229
230
    /**
231
     * Sets "languages" variable for later use in FormHelper.
232
     *
233
     * @return void
234
     */
235
    protected function _setLanguages()
236
    {
237
        $this->set('languages', LocaleToolbox::languagesList());
238
    }
239
240
    /**
241
     * Sets "roles" variable for later use in FormHelper.
242
     *
243
     * @return void
244
     */
245
    protected function _setRoles()
246
    {
247
        $this->loadModel('Block.Blocks');
248
        $roles = $this->Blocks->Roles->find('list');
249
        $this->set('roles', $roles);
250
    }
251
252
    /**
253
     * Sets "regions" variable for later use in FormHelper.
254
     *
255
     * This variable is used to properly fill inputs in the "Theme Region"
256
     * section of the add/edit form.
257
     *
258
     * @param null|\Block\Model\Entity\Block $block If a block entity is provided it
259
     *  will be used to guess which regions has been already selected in each theme,
260
     *  so we can properly show the selectbox in the form with the corrects
261
     *  options selected.
262
     * @return void
263
     */
264
    protected function _setRegions($block = null)
265
    {
266
        $regions = plugin()
267
            ->filter(function ($plugin) {
268
                return $plugin->isTheme;
269
            })
270
            ->map(function ($theme) use ($block) {
271
                $value = '';
272
                if ($block !== null && $block->has('region')) {
273
                    foreach ($block->region as $blockRegion) {
274
                        if ($blockRegion->theme == $theme->name) {
275
                            $value = $blockRegion->region;
276
                            break;
277
                        }
278
                    }
279
                }
280
281
                return [
282
                    'theme_machine_name' => $theme->name,
283
                    'theme_human_name' => $theme->humanName,
284
                    'description' => $theme->composer['description'],
285
                    'regions' => (array)$theme->composer['extra']['regions'],
286
                    'value' => $value,
287
                ];
288
            });
289
        $this->set('regions', $regions);
290
    }
291
292
    /**
293
     * Prepares incoming data from Form's POST and patches the given entity.
294
     *
295
     * @param \Block\Model\Entity\Block $block BLock to patch with incoming
296
     *  POST data
297
     * @return \Cake\Datasource\EntityInterface Patched entity
298
     */
299
    protected function _patchEntity($block)
300
    {
301
        $this->loadModel('Block.Blocks');
302
        $data = ['region' => []];
303
304
        foreach ($this->request->data() as $column => $value) {
305
            if ($column == 'region') {
306
                foreach ($value as $theme => $region) {
307
                    $tmp = ['theme' => $theme, 'region' => $region];
308
                    foreach ((array)$block->region as $blockRegion) {
309
                        if ($blockRegion->theme == $theme) {
310
                            $tmp['id'] = $blockRegion->id;
311
                            break;
312
                        }
313
                    }
314
                    $data[$column][] = $tmp;
315
                }
316
            } else {
317
                $data[$column] = $value;
318
            }
319
        }
320
321
        if ($block->isNew()) {
322
            $data['handler'] = 'Block\Widget\CustomBlockWidget';
323
            $block->set('handler', 'Block\Widget\CustomBlockWidget');
324
        }
325
326
        $validator = $block->isCustom() ? 'custom' : 'widget';
327
328
        return $this->Blocks->patchEntity($block, $data, ['validate' => $validator, 'entity' => $block]);
329
    }
330
}
331