ManageController::index()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 13
nc 2
nop 0
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
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 Content\Controller\Admin;
13
14
use Cake\ORM\Query;
15
use Content\Controller\AppController;
16
use Content\Error\ContentCreateException;
17
use Content\Error\ContentDeleteException;
18
use Content\Error\ContentEditException;
19
use Content\Error\ContentNotFoundException;
20
use Content\Error\ContentTranslateException;
21
use Content\Error\ContentTypeNotFoundException;
22
use Locale\Utility\LocaleToolbox;
23
24
/**
25
 * Content manager controller.
26
 *
27
 * Provides full CRUD for contents.
28
 *
29
 * @property \Content\Model\Table\ContentsTable $Contents
30
 * @property \Content\Model\Table\ContentTypesTable $ContentTypes
31
 * @property \Content\Model\Table\ContentRevisionsTable $ContentRevisions
32
 */
33
class ManageController extends AppController
34
{
35
36
    /**
37
     * An array containing the names of helpers controllers uses.
38
     *
39
     * @var array
40
     */
41
    public $helpers = ['Paginator'];
42
43
    /**
44
     * Shows a list of all the contents.
45
     *
46
     * @return void
47
     */
48
    public function index()
49
    {
50
        $this->loadModel('Content.Contents');
51
        $this->Contents->CreatedBy->fieldable(false);
52
        $this->Contents->ModifiedBy->fieldable(false);
53
        $contents = $this->Contents
54
            ->find('all', ['fieldable' => false])
55
            ->contain(['ContentTypes', 'CreatedBy', 'ModifiedBy']);
56
57
        if (!empty($this->request->query['filter']) &&
58
            $contents instanceof Query
59
        ) {
60
            $this->Contents->search($this->request->query['filter'], $contents);
61
        }
62
63
        $this->title(__d('content', 'Contents List'));
64
        $this->set('contents', $this->paginate($contents));
65
        $this->Breadcrumb->push('/admin/content/manage');
66
    }
67
68
    /**
69
     * Content-type selection screen.
70
     *
71
     * User must select which content type wish to create.
72
     *
73
     * @return void
74
     */
75 View Code Duplication
    public function create()
76
    {
77
        $this->loadModel('Content.ContentTypes');
78
        $types = $this->ContentTypes->find()
79
            ->select(['id', 'slug', 'name', 'description'])
80
            ->all();
81
82
        $this->title(__d('content', 'Create New Content'));
83
        $this->set('types', $types);
84
        $this->Breadcrumb
85
            ->push('/admin/content/manage')
86
            ->push(__d('content', 'Create new content'), '');
87
    }
88
89
    /**
90
     * Shows the "new content" form.
91
     *
92
     * @param string $typeSlug Content type slug. e.g.: "article", "product-info"
93
     * @return void
94
     * @throws \Content\Error\ContentTypeNotFoundException When content type was not
95
     *  found
96
     * @throws \Content\Error\ContentCreateException When current user is not allowed
97
     *  to create contents of this type
98
     */
99
    public function add($typeSlug)
100
    {
101
        $this->loadModel('Content.ContentTypes');
102
        $this->loadModel('Content.Contents');
103
        $this->Contents->unbindComments();
104
        $type = $this->ContentTypes->find()
105
            ->where(['slug' => $typeSlug])
106
            ->limit(1)
107
            ->first();
108
109
        if (!$type) {
110
            throw new ContentTypeNotFoundException(__d('content', 'The specified content type ({0}) does not exists.', $type));
111
        }
112
113
        if (!$type->userAllowed('create')) {
114
            throw new ContentCreateException(__d('content', 'You are not allowed to create contents of this type ({0}).', $type->name));
115
        }
116
117
        if ($this->request->data()) {
118
            $data = $this->request->data();
119
            $data['content_type_slug'] = $type->slug;
120
            $data['content_type_id'] = $type->id;
121
            $content = $this->Contents->newEntity($data);
122
123
            if ($this->Contents->save($content)) {
124
                if (!$type->userAllowed('publish')) {
125
                    $this->Flash->warning(__d('content', 'Content created, but awaiting moderation before publishing it.'));
126
                } else {
127
                    $this->Flash->success(__d('content', 'Content created!.'));
128
                }
129
                $this->redirect(['plugin' => 'Content', 'controller' => 'manage', 'action' => 'edit', 'prefix' => 'admin', $content->id]);
130
            } else {
131
                $this->Flash->danger(__d('content', 'Something went wrong, please check your information.'));
132
            }
133
        } else {
134
            $content = $this->Contents->newEntity(['content_type_slug' => $type->slug]);
135
            $content->setDefaults($type);
136
        }
137
138
        $content->set('content_type', $type);
139
        $content = $this->Contents->attachFields($content);
140
        $languages = LocaleToolbox::languagesList();
141
        $roles = $this->Contents->Roles->find('list');
142
143
        $this->title(__d('content', 'Create New Content <small>({0})</small>', $type->slug));
144
        $this->set(compact('content', 'type', 'languages', 'roles'));
145
        $this->Breadcrumb
146
            ->push('/admin/content/manage')
147
            ->push(__d('content', 'Create new content'), ['plugin' => 'Content', 'controller' => 'manage', 'action' => 'create'])
148
            ->push($type->name, '');
149
    }
150
151
    /**
152
     * Edit form for the given content.
153
     *
154
     * @param int $id Content's ID
155
     * @param false|int $revisionId Fill form with content's revision information
156
     * @return void
157
     * @throws \Content\Error\ContentNotFoundException When content type, or when
158
     *  content content was not found
159
     * @throws \Content\Error\ContentEditException When user is not allowed to edit
160
     *  contents of this type
161
     */
162
    public function edit($id, $revisionId = false)
163
    {
164
        $this->loadModel('Content.Contents');
165
        $this->Contents->unbindComments();
166
        $content = false;
167
168
        if (intval($revisionId) > 0 && !$this->request->data()) {
169
            $this->loadModel('Content.ContentRevisions');
170
            $revision = $this->ContentRevisions->find()
171
                ->where(['id' => $revisionId, 'content_id' => $id])
172
                ->first();
173
174
            if ($revision) {
175
                $content = $revision->data;
176
177
                if (!empty($content->_fields)) {
178
                    // Merge previous data for each field, we just load the data (metadata keeps to the latests configured).
179
                    $_fieldsRevision = $content->_fields;
180
                    $content = $this->Contents->attachFields($content);
181
                    $content->_fields = $content->_fields->map(function ($field, $key) use ($_fieldsRevision) {
182
                        $fieldRevision = $_fieldsRevision[$field->name];
183
                        if ($fieldRevision) {
184
                            $field->set('value', $fieldRevision->value);
185
                            $field->set('extra', $fieldRevision->extra);
186
                        }
187
188
                        return $field;
189
                    });
190
                }
191
            }
192
        } else {
193
            $content = $this->Contents
194
                ->find()
195
                ->where(['Contents.id' => $id])
196
                ->contain([
197
                    'Roles',
198
                    'Translations',
199
                    'ContentRevisions',
200
                    'ContentTypes',
201
                    'TranslationOf',
202
                ])
203
                ->first();
204
        }
205
206
        if (!$content || empty($content->content_type)) {
207
            throw new ContentNotFoundException(__d('content', 'The requested page was not found.'));
208
        }
209
210
        if (!$content->content_type->userAllowed('edit')) {
211
            throw new ContentEditException(__d('content', 'You are not allowed to create contents of this type ({0}).', $content->content_type->name));
212
        }
213
214
        if (!empty($this->request->data)) {
215 View Code Duplication
            if (empty($this->request->data['regenerate_slug'])) {
216
                $this->Contents->behaviors()->Sluggable->config(['on' => 'create']);
217
            } else {
218
                unset($this->request->data['regenerate_slug']);
219
            }
220
221
            $content->accessible([
222
                'id',
223
                'content_type_id',
224
                'content_type_slug',
225
                'translation_for',
226
                'created_by',
227
            ], false);
228
229
            $content = $this->Contents->patchEntity($content, $this->request->data());
230
            if ($this->Contents->save($content, ['atomic' => true, 'associated' => ['Roles']])) {
231
                $this->Flash->success(__d('content', 'Content updated!'));
232
                $this->redirect("/admin/content/manage/edit/{$id}");
233
            } else {
234
                $this->Flash->danger(__d('content', 'Something went wrong, please check your information.'));
235
            }
236
        }
237
238
        $languages = LocaleToolbox::languagesList();
239
        $roles = $this->Contents->Roles->find('list');
240
241
        $this->title(__d('content', 'Editing Content: {0} <small>({1})</small>', $content->title, $content->content_type_slug));
242
        $this->set(compact('content', 'languages', 'roles'));
243
        $this->Breadcrumb
244
            ->push('/admin/content/manage/index')
245
            ->push(__d('content', 'Editing content'), '#');
246
    }
247
248
    /**
249
     * Translate the given content to a different language.
250
     *
251
     * @param int $contentId Content's ID
252
     * @return void
253
     * @throws \Content\Error\ContentNotFoundException When content type, or when
254
     *  content content was not found
255
     * @throws \Content\Error\ContentTranslateException When user is not allowed to
256
     *  translate contents of this type
257
     */
258
    public function translate($contentId)
259
    {
260
        $this->loadModel('Content.Contents');
261
        $content = $this->Contents->get($contentId, ['contain' => 'ContentTypes']);
262
263
        if (!$content || empty($content->content_type)) {
264
            throw new ContentNotFoundException(__d('content', 'The requested page was not found.'));
265
        }
266
267 View Code Duplication
        if (!$content->content_type->userAllowed('translate')) {
268
            throw new ContentTranslateException(__d('content', 'You are not allowed to translate contents of this type ({0}).', $content->content_type->name));
269
        }
270
271
        if (!$content->language || $content->translation_for) {
272
            $this->Flash->danger(__d('content', 'You cannot translate this content.'));
273
            $this->redirect(['plugin' => 'Content', 'controller' => 'manage', 'action' => 'index']);
274
        }
275
276
        $translations = $this->Contents
277
            ->find()
278
            ->where(['translation_for' => $content->id])
279
            ->all();
280
        $languages = LocaleToolbox::languagesList();
281
        $illegal = array_merge([$content->language], $translations->extract('language')->toArray());
282
283
        foreach ($languages as $code => $name) {
284
            if (in_array($code, $illegal)) {
285
                unset($languages[$code]);
286
            }
287
        }
288
289
        if (!empty($languages) &&
290
            !empty($this->request->data['language']) &&
291
            !empty($this->request->data['title']) &&
292
            $this->request->data['language'] !== $content->language
293
        ) {
294
            $this->Contents->fieldable(false); // fix, wont trigger fields validation
295
            $newContent = $this->Contents->newEntity([
296
                'content_type_id' => $content->get('content_type_id'),
297
                'content_type_slug' => $content->get('content_type_slug'),
298
                'title' => $content->get('title'),
299
                'status' => false,
300
                'title' => $this->request->data['title'],
301
                'translation_for' => $content->id,
302
                'language' => $this->request->data['language'],
303
            ]);
304
305 View Code Duplication
            if ($this->Contents->save($newContent)) {
306
                $this->Flash->success(__d('content', 'Translation successfully created and was marked as unpublished. Complete the translation before publishing.'));
307
                $this->redirect(['plugin' => 'Content', 'controller' => 'manage', 'action' => 'edit', $newContent->id]);
308
            } else {
309
                $this->Flash->set(__d('content', 'Translation could not be created'), [
310
                    'element' => 'System.installer_errors',
311
                    'params' => ['errors' => $newContent->errors()],
312
                ]);
313
            }
314
        }
315
316
        $this->title(__d('content', 'Translate Content'));
317
        $this->set(compact('content', 'translations', 'languages'));
318
        $this->Breadcrumb
319
            ->push('/admin/content/manage')
320
            ->push(__d('content', 'Translating content'), '');
321
    }
322
323
    /**
324
     * Deletes the given content by ID.
325
     *
326
     * @param int $contentId Content's ID
327
     * @return void
328
     */
329
    public function delete($contentId)
330
    {
331
        $this->loadModel('Content.Contents');
332
        $content = $this->Contents->get($contentId, ['contain' => ['ContentTypes']]);
333
334
        if (!$content || empty($content->content_type)) {
335
            throw new ContentNotFoundException(__d('content', 'The requested page was not found.'));
336
        }
337
338 View Code Duplication
        if (!$content->content_type->userAllowed('translate')) {
339
            throw new ContentDeleteException(__d('content', 'You are not allowed to delete contents of this type ({0}).', $content->content_type->name));
340
        }
341
342
        if ($this->Contents->delete($content, ['atomic' => true])) {
343
            $this->Flash->success(__d('content', 'Content was successfully removed!'));
344
        } else {
345
            $this->Flash->danger(__d('content', 'Unable to remove this content, please try again.'));
346
        }
347
348
        $this->title(__d('content', 'Delete Content'));
349
        $this->redirect($this->referer());
350
    }
351
352
    /**
353
     * Removes the given revision of the given content.
354
     *
355
     * @param int $contentId Content's ID
356
     * @param int $revisionId Revision's ID
357
     * @return void Redirects to previous page
358
     */
359 View Code Duplication
    public function deleteRevision($contentId, $revisionId)
360
    {
361
        $this->loadModel('Content.ContentRevisions');
362
        $revision = $this->ContentRevisions->find()
363
            ->where(['id' => $revisionId, 'content_id' => $contentId])
364
            ->first();
365
366
        if ($this->ContentRevisions->delete($revision, ['atomic' => true])) {
367
            $this->Flash->success(__d('content', 'Revision was successfully removed!'));
368
        } else {
369
            $this->Flash->danger(__d('content', 'Unable to remove this revision, please try again.'));
370
        }
371
372
        $this->title(__d('content', 'Editing Content Revision'));
373
        $this->redirect($this->referer());
374
    }
375
}
376