Completed
Push — master ( 9c742a...1858b1 )
by Fèvre
14s
created

src/Controller/BlogController.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace App\Controller;
3
4
use App\Event\Badges;
5
use App\Event\Statistics;
6
use Cake\Core\Configure;
7
use Cake\Event\Event;
8
use Cake\Network\Exception\NotFoundException;
9
use Cake\Routing\Router;
10
11
class BlogController extends AppController
12
{
13
14
    /**
15
     * Initialization hook method.
16
     *
17
     * @return void
18
     */
19
    public function initialize()
20
    {
21
        parent::initialize();
22
23
        $this->loadComponent('RequestHandler');
24
    }
25
26
    /**
27
     * BeforeFilter handle.
28
     *
29
     * @param Event $event The beforeFilter event that was fired.
30
     *
31
     * @return void
32
     */
33
    public function beforeFilter(Event $event)
34
    {
35
        parent::beforeFilter($event);
36
37
        $this->Auth->allow(['index', 'category', 'article', 'go', 'archive', 'search']);
38
    }
39
40
    /**
41
     * Display all Articles.
42
     *
43
     * @return void
44
     */
45 View Code Duplication
    public function index()
46
    {
47
        $this->loadModel('BlogArticles');
48
        $this->paginate = [
49
            'maxLimit' => Configure::read('Blog.article_per_page')
50
        ];
51
52
        $articles = $this->BlogArticles
53
            ->find()
54
            ->contain([
55
                'BlogCategories',
56
                'Users' => function ($q) {
57
                    return $q->find('short');
58
                }
59
            ])
60
            ->order([
61
                'BlogArticles.created' => 'desc'
62
            ])
63
            ->where([
64
                'BlogArticles.is_display' => 1
65
            ]);
66
67
        $articles = $this->paginate($articles);
68
69
        $this->set(compact('articles'));
70
    }
71
72
    /**
73
     * Display a specific category with all its articles.
74
     *
75
     * @return \Cake\Network\Response|void
76
     */
77
    public function category()
78
    {
79
        $this->loadModel('BlogCategories');
80
81
        $category = $this->BlogCategories
82
            ->find()
83
            ->where([
84
                'BlogCategories.id' => $this->request->id
85
            ])
86
            ->contain([
87
                'BlogArticles'
88
            ])
89
            ->first();
90
91
        //Check if the category is found.
92
        if (empty($category)) {
93
            $this->Flash->error(__('This category doesn\'t exist or has been deleted.'));
94
95
            return $this->redirect(['action' => 'index']);
96
        }
97
98
        //Paginate all Articles.
99
        $this->loadModel('BlogArticles');
100
        $this->paginate = [
101
            'maxLimit' => Configure::read('Blog.article_per_page')
102
        ];
103
104
        $articles = $this->BlogArticles
105
            ->find()
106
            ->contain([
107
                'Users' => function ($q) {
108
                    return $q->find('short');
109
                }
110
            ])
111
            ->where([
112
                'BlogArticles.category_id' => $category->id,
113
                'BlogArticles.is_display' => 1
114
            ])
115
            ->order([
116
                'BlogArticles.created' => 'desc'
117
            ]);
118
119
        $articles = $this->paginate($articles);
120
121
        $this->set(compact('category', 'articles'));
122
    }
123
124
    /**
125
     * Display a specific article.
126
     *
127
     * @return \Cake\Network\Response|void
128
     */
129
    public function article()
130
    {
131
        $this->loadModel('BlogArticles');
132
133
        $article = $this->BlogArticles
134
            ->find()
135
            ->where([
136
                'BlogArticles.id' => $this->request->id,
137
                'BlogArticles.is_display' => 1
138
            ])
139
            ->contain([
140
                'BlogCategories',
141
                'BlogAttachments',
142
                'Users' => function ($q) {
143
                        return $q->find('full');
144
                }
145
            ])
146
            ->first();
147
148
        //Check if the article is found.
149
        if (is_null($article)) {
150
            $this->Flash->error(__('This article doesn\'t exist or has been deleted.'));
151
152
            return $this->redirect(['action' => 'index']);
153
        }
154
155
        $this->loadModel('BlogArticlesComments');
156
157
        //A comment has been posted.
158
        if ($this->request->is('post')) {
159
            //Check if the user is connected.
160
            if (!$this->Auth->user()) {
161
                return $this->Flash->error(__('You must be connected to post a comment.'));
162
            }
163
164
            $this->request->data['article_id'] = $article->id;
165
            $this->request->data['user_id'] = $this->Auth->user('id');
166
167
            $newComment = $this->BlogArticlesComments->newEntity($this->request->data, ['validate' => 'create']);
168
169
            //Attach Event.
170
            $this->BlogArticlesComments->eventManager()->attach(new Badges($this));
171
172
            if ($insertComment = $this->BlogArticlesComments->save($newComment)) {
173
                $this->eventManager()->attach(new Statistics());
0 ignored issues
show
Deprecated Code introduced by
The method Cake\Event\EventManager::attach() has been deprecated with message: 3.0.0 Use on() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
174
                $event = new Event('Model.BlogArticlesComments.new');
175
                $this->eventManager()->dispatch($event);
176
177
                $this->Flash->success(__('Your comment has been posted successfully !'));
178
                //Redirect the user to the last page of the article.
179
                $this->redirect([
180
                    'action' => 'go',
181
                    $insertComment->id
182
                ]);
183
            }
184
        }
185
186
        //Paginate all comments related to the article.
187
        $this->paginate = [
188
            'maxLimit' => Configure::read('Blog.comment_per_page')
189
        ];
190
191
        $comments = $this->BlogArticlesComments
192
            ->find()
193
            ->where([
194
                'BlogArticlesComments.article_id' => $article->id
195
            ])
196
            ->contain([
197
                'Users' => function ($q) {
198
                    return $q->find('medium');
199
                }
200
            ])
201
            ->order([
202
                'BlogArticlesComments.created' => 'asc'
203
            ]);
204
205
        $comments = $this->paginate($comments);
206
207
        //Select the like for the current auth user.
208
        $this->loadModel('BlogArticlesLikes');
209
        $like = $this->BlogArticlesLikes
210
            ->find()
211
            ->where([
212
                'user_id' => ($this->Auth->user()) ? $this->Auth->user('id') : null,
213
                'article_id' => $article->id
214
            ])
215
            ->first();
216
217
        //Build the newEntity for the comment form.
218
        $formComments = $this->BlogArticlesComments->newEntity();
219
220
        //Search related articles
221
        $keywords = preg_split("/([\s,\W])+/", $article->title);
222
223
        $articles = $this->BlogArticles
224
            ->find()
225
            ->contain([
226
                'BlogCategories',
227
            ])
228
            ->where([
229
                'BlogArticles.is_display' => 1,
230
                'BlogArticles.id !=' => $article->id
231
            ])
232
            ->andWhere([
233
                'BlogArticles.title RLIKE' => rtrim(implode('|', $keywords), '|')
234
            ]);
235
236
        //Current user.
237
        $this->loadModel('Users');
238
        $currentUser = $this->Users
239
            ->find()
240
            ->contain([
241
                'Groups' => function ($q) {
242
                    return $q->select(['id', 'is_staff']);
243
                }
244
            ])
245
            ->where([
246
                'Users.id' => $this->Auth->user('id')
247
            ])
248
            ->select(['id', 'group_id'])
249
            ->first();
250
251
        $this->set(compact('article', 'formComments', 'comments', 'like', 'articles', 'currentUser'));
252
    }
253
254
    /**
255
     * Quote a message.
256
     *
257
     * @param int $articleId Id of the article where is the message to quote.
258
     * @param int $commentId Id of the message to quote.
259
     *
260
     * @throws \Cake\Network\Exception\NotFoundException
261
     *
262
     * @return mixed
263
     */
264
    public function quote($articleId = null, $commentId = null)
265
    {
266
        if (!$this->request->is('ajax')) {
267
            throw new NotFoundException();
268
        }
269
270
        $this->loadModel('BlogArticlesComments');
271
272
        $comment = $this->BlogArticlesComments
273
            ->find()
274
            ->where([
275
                'BlogArticlesComments.article_id' => $articleId,
276
                'BlogArticlesComments.id' => $commentId
277
            ])
278
            ->contain([
279
                'Users' => function ($q) {
280
                        return $q->find('short');
281
                }
282
            ])
283
            ->first();
284
285
        $json = [];
286
287
        if (!is_null($comment)) {
288
            $comment->toArray();
289
290
            $url = Router::url(['action' => 'go', $comment->id]);
291
            $text = __("has said :");
292
293
            //Build the quote.
294
            $json['comment'] = <<<EOT
295
<div>
296
     <div>
297
        <a href="{$url}">
298
            <strong>{$comment->user->full_name} {$text}</strong>
299
        </a>
300
    </div>
301
    <blockquote>
302
        $comment->content
303
    </blockquote>
304
</div><p>&nbsp;</p><p>&nbsp;</p>
305
EOT;
306
307
            $json['error'] = false;
308
309
            $this->set(compact('json'));
310
        } else {
311
            $json['comment'] = __("This comment doesn't exist.");
312
            $json['error'] = true;
313
314
            $this->set(compact('json'));
315
        }
316
317
        //Send response in JSON.
318
        $this->set('_serialize', 'json');
319
    }
320
321
    /**
322
     * Redirect an user to an article, page and comment.
323
     *
324
     * @param int $commentId Id of the comment.
325
     *
326
     * @return \Cake\Network\Response
327
     */
328 View Code Duplication
    public function go($commentId = null)
329
    {
330
        $this->loadModel('BlogArticlesComments');
331
332
        $comment = $this->BlogArticlesComments
333
            ->find()
334
            ->contain([
335
                'BlogArticles'
336
            ])
337
            ->where([
338
                'BlogArticlesComments.id' => $commentId
339
            ])
340
            ->first();
341
342
        if (is_null($comment)) {
343
            $this->Flash->error(__("This comment doesn't exist or has been deleted."));
344
345
            return $this->redirect(['action' => 'index']);
346
        }
347
348
        $comment->toArray();
349
350
        //Count the number of message before this message.
351
        $messagesBefore = $this->BlogArticlesComments
352
            ->find()
353
            ->where([
354
                'BlogArticlesComments.article_id' => $comment->article_id,
355
                'BlogArticlesComments.created <' => $comment->created
356
            ])
357
            ->count();
358
359
        //Get the number of messages per page.
360
        $messagesPerPage = Configure::read('Blog.comment_per_page');
361
362
        //Calculate the page.
363
        $page = floor($messagesBefore / $messagesPerPage) + 1;
364
365
        $page = ($page > 1) ? $page : 1;
366
367
        //Redirect the user.
368
        return $this->redirect([
369
            '_name' => 'blog-article',
370
            'slug' => $comment->blog_article->title,
371
            'id' => $comment->blog_article->id,
372
            '?' => ['page' => $page],
373
            '#' => 'comment-' . $commentId
374
        ]);
375
    }
376
377
    /**
378
     * Get all articles by a date formatted to "m-Y".
379
     *
380
     * @param string $date The date of the archive.
381
     *
382
     * @return void
383
     */
384
    public function archive($date = null)
385
    {
386
        $this->loadModel('BlogArticles');
387
388
        $this->paginate = [
389
            'maxLimit' => Configure::read('Blog.article_per_page')
390
        ];
391
392
        $archives = $this->BlogArticles
393
            ->find()
394
            ->where([
395
                'DATE_FORMAT(BlogArticles.created,\'%m-%Y\')' => $date,
396
                'BlogArticles.is_display' => 1
397
            ])
398
            ->contain([
399
                'BlogCategories',
400
                'Users' => function ($q) {
401
                        return $q->find('short');
402
                }
403
            ])
404
            ->order([
405
                'BlogArticles.created' => 'desc'
406
            ]);
407
408
        $articles = $this->paginate($archives);
409
410
        $this->set(compact('articles', 'date'));
411
    }
412
413
    /**
414
     * Search articles.
415
     *
416
     * @return void
417
     */
418
    public function search()
419
    {
420
        $this->loadModel('BlogArticles');
421
422
        //Check the keyword to search. (For pagination)
423 View Code Duplication
        if (!empty($this->request->data['search'])) {
424
            $keyword = $this->request->data['search'];
425
            $this->request->session()->write('Search.Blog.Keyword', $keyword);
426
        } else {
427
            if ($this->request->session()->read('Search.Blog.Keyword')) {
428
                $keyword = $this->request->session()->read('Search.Blog.Keyword');
429
            } else {
430
                $keyword = '';
431
            }
432
        }
433
434
        //Pagination
435
        $this->paginate = [
436
            'maxLimit' => Configure::read('Blog.article_per_page')
437
        ];
438
439
        $articles = $this->BlogArticles
440
            ->find()
441
            ->contain([
442
                'Users' => function ($q) {
443
                    return $q->find('short');
444
                }
445
            ])
446
            ->where([
447
                'BlogArticles.is_display' => 1
448
            ])
449
            ->andWhere(function ($q) use ($keyword) {
450
                return $q
451
                    ->like('title', "%$keyword%");
452
            })
453
            ->order([
454
                'BlogArticles.created' => 'desc'
455
            ]);
456
457
        $articles = $this->paginate($articles);
458
459
        $this->set(compact('articles', 'keyword'));
460
    }
461
462
    /**
463
     * Like an article.
464
     *
465
     * @param int $articleId Id of the article to like.
466
     *
467
     * @throws \Cake\Network\Exception\NotFoundException When it's not an AJAX request.
468
     *
469
     * @return void
470
     */
471
    public function articleLike($articleId = null)
472
    {
473
        if (!$this->request->is('ajax')) {
474
            throw new NotFoundException();
475
        }
476
477
        //Check if the user hasn't already liked this article.
478
        $this->loadModel('BlogArticlesLikes');
479
        $checkLike = $this->BlogArticlesLikes
480
            ->find()
481
            ->where([
482
                'BlogArticlesLikes.user_id' => $this->Auth->user('id'),
483
                'BlogArticlesLikes.article_id' => $articleId
484
            ])
485
            ->first();
486
487
        $json = [];
488
489
        if (!is_null($checkLike)) {
490
            $json['message'] = __('You already like this article !');
491
            $json['error'] = true;
492
493
            $this->set(compact('json'));
494
495
            $this->set('_serialize', 'json');
496
        }
497
498
        //Check if the article exist.
499
        $this->loadModel('BlogArticles');
500
        $checkArticle = $this->BlogArticles
501
            ->find()
502
            ->where([
503
                'BlogArticles.id' => $articleId,
504
                'BlogArticles.is_display' => 1
505
            ])
506
            ->first();
507
508
        if (is_null($checkArticle)) {
509
            $json['message'] = __("This article doesn't exist !");
510
            $json['error'] = true;
511
512
            $this->set(compact('json'));
513
514
            $this->set('_serialize', 'json');
515
        }
516
517
        //Prepare data to be saved.
518
        $data = [];
519
        $data['BlogArticlesLikes']['user_id'] = $this->Auth->user('id');
520
        $data['BlogArticlesLikes']['article_id'] = $articleId;
521
522
        $like = $this->BlogArticlesLikes->newEntity($data);
523
524
        if ($this->BlogArticlesLikes->save($like)) {
525
            //Update the Statistics
526
            $this->eventManager()->attach(new Statistics());
0 ignored issues
show
Deprecated Code introduced by
The method Cake\Event\EventManager::attach() has been deprecated with message: 3.0.0 Use on() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
527
            $event = new Event('Model.BlogArticlesLikes.new');
528
            $this->eventManager()->dispatch($event);
529
530
            $json['message'] = __('Thanks for {0} this article ! ', "<i class='fa fa-heart text-danger'></i>");
531
            $json['title'] = __('You {0} this article.', "<i class='fa fa-heart text-danger'></i>");
532
            $json['url'] = Router::url(
533
                [
534
                    'action' => 'articleUnlike',
535
                    $articleId
536
                ]
537
            );
538
            $json['error'] = false;
539
        } else {
540
            $json['message'] = __('An error occurred, please try again later.');
541
            $json['error'] = true;
542
        }
543
544
        $this->set(compact('json'));
545
546
        $this->set('_serialize', 'json');
547
    }
548
549
    /**
550
     * Unlike an article.
551
     *
552
     * @param int|null $articleId Id of the article to like.
553
     *
554
     * @throws \Cake\Network\Exception\NotFoundException When it's not an AJAX request.
555
     *
556
     * @return void
557
     */
558
    public function articleUnlike($articleId = null)
559
    {
560
        if (!$this->request->is('ajax')) {
561
            throw new NotFoundException();
562
        }
563
564
        //Check if the user like this article.
565
        $this->loadModel('BlogArticlesLikes');
566
        $like = $this->BlogArticlesLikes
567
            ->find()
568
            ->contain([
569
                'BlogArticles'
570
            ])
571
            ->where([
572
                'BlogArticlesLikes.user_id' => $this->Auth->user('id'),
573
                'BlogArticlesLikes.article_id' => $articleId,
574
                'BlogArticles.is_display' => 1
575
            ])
576
            ->first();
577
578
        $json = [];
579
580
        if (is_null($like)) {
581
            $json['message'] = __("You don't like this article !");
582
            $json['error'] = true;
583
584
            $this->set(compact('json'));
585
586
            $this->set('_serialize', 'json');
587
        }
588
589
        if ($this->BlogArticlesLikes->delete($like)) {
590
            //Update the Statistics
591
            $this->eventManager()->attach(new Statistics());
0 ignored issues
show
Deprecated Code introduced by
The method Cake\Event\EventManager::attach() has been deprecated with message: 3.0.0 Use on() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
592
            $event = new Event('Model.BlogArticlesLikes.new');
593
            $this->eventManager()->dispatch($event);
594
595
            $json['url'] = Router::url([
596
                                'action' => 'articleLike',
597
                                $articleId
598
                            ]);
599
            $json['title'] = __('Like {0}', "<i class='fa fa-heart text-danger'></i>");
600
            $json['error'] = false;
601
        } else {
602
            $json['message'] = __('An error occurred, please try again later.');
603
            $json['error'] = true;
604
        }
605
606
        $this->set(compact('json'));
607
608
        $this->set('_serialize', 'json');
609
    }
610
611
    /**
612
     * Delete a comment.
613
     *
614
     * @param int $id Id of the comment to delete.
615
     *
616
     * @return \Cake\Network\Response
617
     */
618
    public function deleteComment($id = null)
619
    {
620
        $this->loadModel('BlogArticlesComments');
621
622
        $comment = $this->BlogArticlesComments
623
            ->find()
624
            ->contain([
625
                'BlogArticles'
626
            ])
627
            ->where([
628
                'BlogArticlesComments.id' => $id
629
            ])
630
            ->first();
631
632
        if (is_null($comment)) {
633
            $this->Flash->error(__("This comment doesn't exist or has been deleted !"));
634
635
            return $this->redirect($this->referer());
636
        }
637
638
        //Current user.
639
        $this->loadModel('Users');
640
        $currentUser = $this->Users
641
            ->find()
642
            ->contain([
643
                'Groups' => function ($q) {
644
                    return $q->select(['id', 'is_staff']);
645
                }
646
            ])
647
            ->where([
648
                'Users.id' => $this->Auth->user('id')
649
            ])
650
            ->select(['id', 'group_id'])
651
            ->first();
652
653
        if ($comment->user_id != $this->Auth->user('id') && !$currentUser->group->is_staff) {
654
            $this->Flash->error(__("You don't have the authorization to delete this comment !"));
655
656
            return $this->redirect($this->referer());
657
        }
658
659
        if ($this->BlogArticlesComments->delete($comment)) {
660
            $this->eventManager()->attach(new Statistics());
0 ignored issues
show
Deprecated Code introduced by
The method Cake\Event\EventManager::attach() has been deprecated with message: 3.0.0 Use on() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
661
            $event = new Event('Model.BlogArticlesComments.new');
662
            $this->eventManager()->dispatch($event);
663
664
            $this->Flash->success(__("This comment has been deleted successfully !"));
665
        }
666
667
        return $this->redirect(['_name' => 'blog-article', 'slug' => $comment->blog_article->title, 'id' => $comment->blog_article->id, '?' => ['page' => $comment->blog_article->last_page]]);
668
    }
669
670
    /**
671
     * Get the form to edit a comment.
672
     *
673
     * @throws \Cake\Network\Exception\NotFoundException When it's not an AJAX request.
674
     *
675
     * @return void
676
     */
677
    public function getEditComment()
678
    {
679
        if (!$this->request->is('ajax')) {
680
            throw new NotFoundException();
681
        }
682
683
        $this->loadModel('BlogArticlesComments');
684
        $comment = $this->BlogArticlesComments
685
            ->find()
686
            ->where([
687
                'BlogArticlesComments.id' => $this->request->data['id']
688
            ])
689
            ->first();
690
691
        $json = [
692
            'error' => false,
693
            'errorMessage' => ''
694
        ];
695
696
        if (is_null($comment)) {
697
            $json['error'] = true;
698
            $json['errorMessage'] = __("This comment doesn't exist or has been deleted !");
699
700
            $this->set(compact('json'));
701
702
            return;
703
        }
704
705
        //Current user.
706
        $this->loadModel('Users');
707
        $currentUser = $this->Users
708
            ->find()
709
            ->contain([
710
                'Groups' => function ($q) {
711
                    return $q->select(['id', 'is_staff']);
712
                }
713
            ])
714
            ->where([
715
                'Users.id' => $this->Auth->user('id')
716
            ])
717
            ->select(['id', 'group_id'])
718
            ->first();
719
720
        if ($comment->user_id != $this->Auth->user('id') && !$currentUser->group->is_staff) {
721
            $json['error'] = true;
722
            $json['errorMessage'] = __("You don't have the authorization to edit this comment !");
723
724
            $this->set(compact('json'));
725
726
            return;
727
        }
728
729
        $this->set(compact('json', 'comment'));
730
    }
731
732
    /**
733
     * Edit a comment.
734
     *
735
     * @param int $id Id of the comment.
736
     *
737
     * @return \Cake\Network\Response
738
     */
739
    public function editComment($id = null)
740
    {
741
        $this->loadModel('BlogArticlesComments');
742
743
        $comment = $this->BlogArticlesComments
744
            ->find()
745
            ->contain([
746
                'BlogArticles'
747
            ])
748
            ->where([
749
                'BlogArticlesComments.id' => $id
750
            ])
751
            ->first();
752
753
        if (is_null($comment)) {
754
            $this->Flash->error(__("This comment doesn't exist or has been deleted !"));
755
756
            return $this->redirect($this->referer());
757
        }
758
759
        //Current user.
760
        $this->loadModel('Users');
761
        $currentUser = $this->Users
762
            ->find()
763
            ->contain([
764
                'Groups' => function ($q) {
765
                    return $q->select(['id', 'is_staff']);
766
                }
767
            ])
768
            ->where([
769
                'Users.id' => $this->Auth->user('id')
770
            ])
771
            ->select(['id', 'group_id'])
772
            ->first();
773
774
        if ($comment->user_id != $this->Auth->user('id') && !$currentUser->group->is_staff) {
775
            $this->Flash->error(__("You don't have the authorization to edit this comment !"));
776
777
            return $this->redirect($this->referer());
778
        }
779
780
        $this->BlogArticlesComments->patchEntity($comment, $this->request->data());
781
        if ($this->BlogArticlesComments->save($comment)) {
782
            $this->Flash->success(__("This comment has been edited successfully !"));
783
        }
784
785
        return $this->redirect(['action' => 'go', $comment->id]);
786
    }
787
}
788