Completed
Push — master ( 9526e1...79bc18 )
by Loz
03:00
created

code/model/Blog.php (3 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
3
/**
4
 * Blog Holder
5
 *
6
 * @package silverstripe
7
 * @subpackage blog
8
 *
9
 * @method HasManyList Tags() List of tags in this blog
10
 * @method HasManyList Categories() List of categories in this blog
11
 * @method ManyManyList Editors() List of editors
12
 * @method ManyManyList Writers() List of writers
13
 * @method ManyManyList Contributors() List of contributors
14
 */
15
class Blog extends Page implements PermissionProvider
16
{
17
    /**
18
     * Permission for user management.
19
     *
20
     * @var string
21
     */
22
    const MANAGE_USERS = 'BLOG_MANAGE_USERS';
23
24
    /**
25
     * If true, users assigned as editor, writer, or contributor will be automatically granted
26
     * CMS_ACCESS_CMSMain permission. If false, only users with this permission already may be
27
     * assigned.
28
     *
29
     * @config
30
     *
31
     * @var boolean
32
     */
33
    private static $grant_user_access = true;
34
35
    /**
36
     * Permission to either require, or grant to users assigned to work on this blog.
37
     *
38
     * @config
39
     *
40
     * @var string
41
     */
42
    private static $grant_user_permission = 'CMS_ACCESS_CMSMain';
43
44
    /**
45
     * Group code to assign newly granted users to.
46
     *
47
     * @config
48
     *
49
     * @var string
50
     */
51
    private static $grant_user_group = 'blog-users';
52
53
    /**
54
     * @var array
55
     */
56
    private static $db = array(
57
        'PostsPerPage' => 'Int',
58
    );
59
60
    /**
61
     * @var array
62
     */
63
    private static $has_many = array(
64
        'Tags' => 'BlogTag',
65
        'Categories' => 'BlogCategory',
66
    );
67
68
    /**
69
     * @var array
70
     */
71
    private static $many_many = array(
72
        'Editors' => 'Member',
73
        'Writers' => 'Member',
74
        'Contributors' => 'Member',
75
    );
76
77
    /**
78
     * @var array
79
     */
80
    private static $allowed_children = array(
81
        'BlogPost',
82
    );
83
84
    /**
85
     * @var array
86
     */
87
    private static $extensions = array(
88
        'BlogFilter',
89
    );
90
91
    /**
92
     * @var array
93
     */
94
    private static $defaults = array(
95
        'ProvideComments' => false,
96
        'PostsPerPage' => 10,
97
    );
98
99
    /**
100
     * @var string
101
     */
102
    private static $description = 'Adds a blog to your website.';
103
104
    private static $icon = 'blog/images/site-tree-icon.png';
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function getCMSFields()
110
    {
111
        Requirements::css(BLOGGER_DIR . '/css/cms.css');
112
        Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
113
114
        $self =& $this;
115
116
        $this->beforeUpdateCMSFields(function ($fields) use ($self) {
117
            if (!$self->canEdit()) {
118
                return;
119
            }
120
121
            $categories = GridField::create(
122
                'Categories',
123
                _t('Blog.Categories', 'Categories'),
124
                $self->Categories(),
125
                GridFieldCategorisationConfig::create(15, $self->Categories()->sort('Title'), 'BlogCategory', 'Categories', 'BlogPosts')
126
            );
127
128
            $tags = GridField::create(
129
                'Tags',
130
                _t('Blog.Tags', 'Tags'),
131
                $self->Tags(),
132
                GridFieldCategorisationConfig::create(15, $self->Tags()->sort('Title'), 'BlogTag', 'Tags', 'BlogPosts')
133
            );
134
135
            /**
136
             * @var FieldList $fields
137
             */
138
            $fields->addFieldsToTab('Root.Categorisation', array(
139
                $categories,
140
                $tags
141
            ));
142
143
            $fields->findOrMakeTab('Root.Categorisation')->addExtraClass('blog-cms-categorisation');
144
        });
145
146
        return parent::getCMSFields();
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function canEdit($member = null)
153
    {
154
        $member = $this->getMember($member);
155
156
        if ($this->isEditor($member)) {
157
            return true;
158
        }
159
160
        return parent::canEdit($member);
161
    }
162
163
    /**
164
     * @param null|int|Member $member
165
     *
166
     * @return null|Member
167
     */
168 View Code Duplication
    protected function getMember($member = null)
169
    {
170
        if (!$member) {
171
            $member = Member::currentUser();
172
        }
173
174
        if (is_numeric($member)) {
175
            $member = Member::get()->byID($member);
176
        }
177
178
        return $member;
179
    }
180
181
    /**
182
     * Check if this member is an editor of the blog.
183
     *
184
     * @param Member $member
185
     *
186
     * @return bool
187
     */
188
    public function isEditor($member)
189
    {
190
        $isEditor = $this->isMemberOf($member, $this->Editors());
191
        $this->extend('updateIsEditor', $isEditor, $member);
192
193
        return $isEditor;
194
    }
195
196
    /**
197
     * Determine if the given member belongs to the given relation.
198
     *
199
     * @param Member $member
200
     * @param DataList $relation
201
     *
202
     * @return bool
203
     */
204 View Code Duplication
    protected function isMemberOf($member, $relation)
205
    {
206
        if (!$member || !$member->exists()) {
207
            return false;
208
        }
209
210
        if ($relation instanceof UnsavedRelationList) {
211
            return in_array($member->ID, $relation->getIDList());
212
        }
213
214
        return $relation->byID($member->ID) !== null;
215
    }
216
217
    /**
218
     * Determine the role of the given member.
219
     *
220
     * Call be called via template to determine the current user.
221
     *
222
     * @example "Hello $RoleOf($CurrentMember.ID)"
223
     *
224
     * @param int|Member $member
225
     *
226
     * @return null|string
227
     */
228
    public function RoleOf($member)
229
    {
230
        if (is_numeric($member)) {
231
            $member = DataObject::get_by_id('Member', $member);
232
        }
233
234
        if (!$member) {
235
            return null;
236
        }
237
238
        if ($this->isEditor($member)) {
239
            return _t('Blog.EDITOR', 'Editor');
240
        }
241
242
        if ($this->isWriter($member)) {
243
            return _t('Blog.WRITER', 'Writer');
244
        }
245
246
        if ($this->isContributor($member)) {
247
            return _t('Blog.CONTRIBUTOR', 'Contributor');
248
        }
249
250
        return null;
251
    }
252
253
    /**
254
     * Check if this member is a writer of the blog.
255
     *
256
     * @param Member $member
257
     *
258
     * @return bool
259
     */
260
    public function isWriter($member)
261
    {
262
        $isWriter = $this->isMemberOf($member, $this->Writers());
263
        $this->extend('updateIsWriter', $isWriter, $member);
264
265
        return $isWriter;
266
    }
267
268
    /**
269
     * Check if this member is a contributor of the blog.
270
     *
271
     * @param Member $member
272
     *
273
     * @return bool
274
     */
275
    public function isContributor($member)
276
    {
277
        $isContributor = $this->isMemberOf($member, $this->Contributors());
278
        $this->extend('updateIsContributor', $isContributor, $member);
279
280
        return $isContributor;
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286
    public function canAddChildren($member = null)
287
    {
288
        $member = $this->getMember($member);
289
290
        if ($this->isEditor($member) || $this->isWriter($member) || $this->isContributor($member)) {
291
            return true;
292
        }
293
294
        return parent::canAddChildren($member);
295
    }
296
297
    /**
298
     * {@inheritdoc}
299
     */
300
    public function getSettingsFields()
301
    {
302
        $fields = parent::getSettingsFields();
303
304
        $fields->addFieldToTab('Root.Settings',
305
            NumericField::create('PostsPerPage', _t('Blog.PostsPerPage', 'Posts Per Page'))
306
        );
307
308
        $members = $this->getCandidateUsers()->map()->toArray();
309
310
        $editorField = ListboxField::create('Editors', 'Editors', $members)
311
            ->setMultiple(true)
312
            ->setRightTitle('<a class="toggle-description">help</a>')
313
            ->setDescription('
314
				An editor has control over specific Blogs, and all posts included within it. Short of being able to assign other editors to a blog, they are able to handle most changes to their assigned blog.<br />
315
				<br />
316
				Editors have these permissions:<br />
317
				<br />
318
				Update or publish any BlogPost in their Blog<br />
319
				Update or publish their Blog<br />
320
				Assign/unassign writers to their Blog<br />
321
				Assign/unassign contributors to their Blog<br />
322
				Assign/unassign any member as an author of a particular BlogPost
323
			');
324
325
        if (!$this->canEditEditors()) {
326
            $editorField = $editorField->performDisabledTransformation();
327
        }
328
329
        $writerField = ListboxField::create('Writers', 'Writers', $members)
330
            ->setMultiple(true)
331
            ->setRightTitle('<a class="toggle-description">help</a>')
332
            ->setDescription('
333
				A writer has full control over creating, editing and publishing BlogPosts they have authored or have been assigned to. Writers are unable to edit BlogPosts to which they are not assigned.<br />
334
				<br />
335
				Writers have these permissions:<br />
336
				<br />
337
				Update or publish any BlogPost they have authored or have been assigned to<br />
338
				Assign/unassign any member as an author of a particular BlogPost they have authored or have been assigned to
339
			');
340
341
        if (!$this->canEditWriters()) {
342
            $writerField = $writerField->performDisabledTransformation();
343
        }
344
345
        $contributorField = ListboxField::create('Contributors', 'Contributors', $members)
346
            ->setMultiple(true)
347
            ->setRightTitle('<a class="toggle-description">help</a>')
348
            ->setDescription('
349
				Contributors have the ability to create or edit BlogPosts, but are unable to publish without authorisation of an editor. They are also unable to assign other contributing authors to any of their BlogPosts.<br />
350
				<br />
351
				Contributors have these permissions:<br />
352
				<br />
353
				Update any BlogPost they have authored or have been assigned to
354
			');
355
356
        if (!$this->canEditContributors()) {
357
            $contributorField = $contributorField->performDisabledTransformation();
358
        }
359
360
        $fields->addFieldsToTab('Root.Users', array(
361
            $editorField,
362
            $writerField,
363
            $contributorField
364
        ));
365
366
        return $fields;
367
    }
368
369
    /**
370
     * Gets the list of user candidates to be assigned to assist with this blog.
371
     *
372
     * @return SS_List
373
     */
374
    protected function getCandidateUsers()
375
    {
376
        if ($this->config()->grant_user_access) {
377
            $list = Member::get();
378
            $this->extend('updateCandidateUsers', $list);
379
            return $list;
380
        } else {
381
            return Permission::get_members_by_permission(
382
                $this->config()->grant_user_permission
383
            );
384
        }
385
    }
386
387
    /**
388
     * Determine if this user can edit the editors list.
389
     *
390
     * @param int|Member $member
391
     *
392
     * @return bool
393
     */
394
    public function canEditEditors($member = null)
395
    {
396
        $member = $this->getMember($member);
397
398
        $extended = $this->extendedCan('canEditEditors', $member);
399
400
        if ($extended !== null) {
401
            return $extended;
402
        }
403
404
        return Permission::checkMember($member, self::MANAGE_USERS);
0 ignored issues
show
Bug Compatibility introduced by
The expression \Permission::checkMember...r, self::MANAGE_USERS); of type boolean|string|null adds the type string to the return on line 404 which is incompatible with the return type documented by Blog::canEditEditors of type boolean.
Loading history...
405
    }
406
407
    /**
408
     * Determine if this user can edit writers list.
409
     *
410
     * @param int|Member $member
411
     *
412
     * @return boolean
413
     */
414 View Code Duplication
    public function canEditWriters($member = null)
415
    {
416
        $member = $this->getMember($member);
417
418
        $extended = $this->extendedCan('canEditWriters', $member);
419
420
        if ($extended !== null) {
421
            return $extended;
422
        }
423
424
        if ($this->isEditor($member)) {
425
            return true;
426
        }
427
428
        return Permission::checkMember($member, self::MANAGE_USERS);
0 ignored issues
show
Bug Compatibility introduced by
The expression \Permission::checkMember...r, self::MANAGE_USERS); of type boolean|string|null adds the type string to the return on line 428 which is incompatible with the return type documented by Blog::canEditWriters of type boolean.
Loading history...
429
    }
430
431
    /**
432
     * Determines if this user can edit the contributors list.
433
     *
434
     * @param int|Member $member
435
     *
436
     * @return boolean
437
     */
438 View Code Duplication
    public function canEditContributors($member = null)
439
    {
440
        $member = $this->getMember($member);
441
442
        $extended = $this->extendedCan('canEditContributors', $member);
443
444
        if ($extended !== null) {
445
            return $extended;
446
        }
447
448
        if ($this->isEditor($member)) {
449
            return true;
450
        }
451
452
        return Permission::checkMember($member, self::MANAGE_USERS);
0 ignored issues
show
Bug Compatibility introduced by
The expression \Permission::checkMember...r, self::MANAGE_USERS); of type boolean|string|null adds the type string to the return on line 452 which is incompatible with the return type documented by Blog::canEditContributors of type boolean.
Loading history...
453
    }
454
455
    /**
456
     * Returns BlogPosts for a given date period.
457
     *
458
     * @param int $year
459
     * @param null|int $month
460
     * @param null|int $day
461
     *
462
     * @return DataList
463
     */
464
    public function getArchivedBlogPosts($year, $month = null, $day = null)
465
    {
466
        $query = $this->getBlogPosts()->dataQuery();
467
468
        $stage = $query->getQueryParam('Versioned.stage');
469
470
        if ($stage) {
471
            $stage = '_' . $stage;
472
        }
473
474
        $query->innerJoin('BlogPost', sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage));
475
476
        $conn = DB::getConn();
477
478
        // Filter by year
479
        $yearCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%Y');
480
        $query->where(sprintf('%s = \'%04d\'', $yearCond, Convert::raw2sql($year)));
481
482
        // Filter by month (if given)
483
        if ($month) {
484
            $monthCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%m');
485
            $query->where(sprintf('%s = \'%02d\'', $monthCond, Convert::raw2sql($month)));
486
487
            if ($day) {
488
                $dayCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%d');
489
                $query->where(sprintf('%s = \'%02d\'', $dayCond, Convert::raw2sql($day)));
490
            }
491
        }
492
493
494
        return $this->getBlogPosts()->setDataQuery($query);
495
    }
496
497
    /**
498
     * Return blog posts.
499
     *
500
     * @return DataList of BlogPost objects
501
     */
502
    public function getBlogPosts()
503
    {
504
        $blogPosts = BlogPost::get()->filter('ParentID', $this->ID);
505
506
        $this->extend('updateGetBlogPosts', $blogPosts);
507
508
        return $blogPosts;
509
    }
510
511
    /**
512
     * Get a link to a Member profile.
513
     *
514
     * @param string $urlSegment
515
     *
516
     * @return string
517
     */
518
    public function ProfileLink($urlSegment)
519
    {
520
        return Controller::join_links($this->Link(), 'profile', $urlSegment);
521
    }
522
523
    /**
524
     * This sets the title for our gridfield.
525
     *
526
     * @return string
527
     */
528
    public function getLumberjackTitle()
529
    {
530
        return _t('Blog.LumberjackTitle', 'Blog Posts');
531
    }
532
533
    /**
534
     * This overwrites lumberjacks default gridfield config.
535
     *
536
     * @return GridFieldConfig
537
     */
538
    public function getLumberjackGridFieldConfig()
539
    {
540
        return GridFieldConfig_BlogPost::create();
541
    }
542
543
    /**
544
     * {@inheritdoc}
545
     */
546
    public function providePermissions()
547
    {
548
        return array(
549
            Blog::MANAGE_USERS => array(
550
                'name' => _t(
551
                    'Blog.PERMISSION_MANAGE_USERS_DESCRIPTION',
552
                    'Manage users for individual blogs'
553
                ),
554
                'help' => _t(
555
                    'Blog.PERMISSION_MANAGE_USERS_HELP',
556
                    'Allow assignment of Editors, Writers, or Contributors to blogs'
557
                ),
558
                'category' => _t('Blog.PERMISSIONS_CATEGORY', 'Blog permissions'),
559
                'sort' => 100
560
            )
561
        );
562
    }
563
564
    /**
565
     * {@inheritdoc}
566
     */
567
    protected function onBeforeWrite()
568
    {
569
        parent::onBeforeWrite();
570
        $this->assignGroup();
571
    }
572
573
    /**
574
     * Assign users as necessary to the blog group.
575
     */
576
    protected function assignGroup()
577
    {
578
        if (!$this->config()->grant_user_access) {
579
            return;
580
        }
581
582
        $group = $this->getUserGroup();
583
584
        // Must check if the method exists or else an error occurs when changing page type
585
        if ($this->hasMethod('Editors')) {
586
            foreach (array($this->Editors(), $this->Writers(), $this->Contributors()) as $levels) {
587
                foreach ($levels as $user) {
588
                    if (!$user->inGroup($group)) {
589
                        $user->Groups()->add($group);
590
                    }
591
                }
592
            }
593
        }
594
    }
595
596
    /**
597
     * Gets or creates the group used to assign CMS access.
598
     *
599
     * @return Group
600
     */
601
    protected function getUserGroup()
602
    {
603
        $code = $this->config()->grant_user_group;
604
605
        $group = Group::get()->filter('Code', $code)->first();
606
607
        if ($group) {
608
            return $group;
609
        }
610
611
        $group = new Group();
612
        $group->Title = 'Blog users';
613
        $group->Code = $code;
614
615
        $group->write();
616
617
        $permission = new Permission();
618
        $permission->Code = $this->config()->grant_user_permission;
619
620
        $group->Permissions()->add($permission);
621
622
        return $group;
623
    }
624
}
625
626
/**
627
 * @package silverstripe
628
 * @subpackage blog
629
 */
630
class Blog_Controller extends Page_Controller
631
{
632
    /**
633
     * @var array
634
     */
635
    private static $allowed_actions = array(
636
        'archive',
637
        'tag',
638
        'category',
639
        'rss',
640
        'profile',
641
    );
642
643
    /**
644
     * @var array
645
     */
646
    private static $url_handlers = array(
647
        'tag/$Tag!' => 'tag',
648
        'category/$Category!' => 'category',
649
        'archive/$Year!/$Month/$Day' => 'archive',
650
        'profile/$URLSegment!' => 'profile',
651
    );
652
653
    /**
654
     * @var array
655
     */
656
    private static $casting = array(
657
        'MetaTitle' => 'Text',
658
        'FilterDescription' => 'Text',
659
    );
660
661
    /**
662
     * The current Blog Post DataList query.
663
     *
664
     * @var DataList
665
     */
666
    protected $blogPosts;
667
668
    /**
669
     * @return string
670
     */
671
    public function index()
672
    {
673
        /**
674
         * @var Blog $dataRecord
675
         */
676
        $dataRecord = $this->dataRecord;
677
678
        $this->blogPosts = $dataRecord->getBlogPosts();
679
680
        return $this->render();
681
    }
682
683
    /**
684
     * Renders a Blog Member's profile.
685
     *
686
     * @return SS_HTTPResponse
687
     */
688
    public function profile()
689
    {
690
        $profile = $this->getCurrentProfile();
691
692
        if (!$profile) {
693
            return $this->httpError(404, 'Not Found');
694
        }
695
696
        $this->blogPosts = $this->getCurrentProfilePosts();
697
698
        return $this->render();
699
    }
700
701
    /**
702
     * Get the Member associated with the current URL segment.
703
     *
704
     * @return null|Member
705
     */
706
    public function getCurrentProfile()
707
    {
708
        $urlSegment = $this->request->param('URLSegment');
709
710
        if ($urlSegment) {
711
            return Member::get()
712
                ->filter('URLSegment', $urlSegment)
713
                ->first();
714
        }
715
716
        return null;
717
    }
718
719
    /**
720
     * Get posts related to the current Member profile.
721
     *
722
     * @return null|DataList
723
     */
724
    public function getCurrentProfilePosts()
725
    {
726
        $profile = $this->getCurrentProfile();
727
728
        if ($profile) {
729
            return $profile->BlogPosts()->filter('ParentID', $this->ID);
730
        }
731
732
        return null;
733
    }
734
735
    /**
736
     * Renders an archive for a specified date. This can be by year or year/month.
737
     *
738
     * @return null|SS_HTTPResponse
739
     */
740
    public function archive()
741
    {
742
        /**
743
         * @var Blog $dataRecord
744
         */
745
        $dataRecord = $this->dataRecord;
746
747
        $year = $this->getArchiveYear();
748
        $month = $this->getArchiveMonth();
749
        $day = $this->getArchiveDay();
750
751
        if ($this->request->param('Month') && !$month) {
752
            $this->httpError(404, 'Not Found');
753
        }
754
755
        if ($month && $this->request->param('Day') && !$day) {
756
            $this->httpError(404, 'Not Found');
757
        }
758
759
        if ($year) {
760
            $this->blogPosts = $dataRecord->getArchivedBlogPosts($year, $month, $day);
761
762
            return $this->render();
763
        }
764
765
        $this->httpError(404, 'Not Found');
766
767
        return null;
768
    }
769
770
    /**
771
     * Fetches the archive year from the url.
772
     *
773
     * @return int
774
     */
775
    public function getArchiveYear()
776
    {
777
        if ($this->request->param('Year')) {
778
            if (preg_match('/^[0-9]{4}$/', $year = $this->request->param('Year'))) {
779
                return (int) $year;
780
            }
781
        } elseif ($this->request->param('Action') == 'archive') {
782
            return SS_Datetime::now()->Year();
783
        }
784
785
        return null;
786
    }
787
788
    /**
789
     * Fetches the archive money from the url.
790
     *
791
     * @return null|int
792
     */
793
    public function getArchiveMonth()
794
    {
795
        $month = $this->request->param('Month');
796
797
        if (preg_match('/^[0-9]{1,2}$/', $month)) {
798
            if ($month > 0 && $month < 13) {
799
                if (checkdate($month, 01, $this->getArchiveYear())) {
800
                    return (int) $month;
801
                }
802
            }
803
        }
804
805
        return null;
806
    }
807
808
    /**
809
     * Fetches the archive day from the url.
810
     *
811
     * @return null|int
812
     */
813
    public function getArchiveDay()
814
    {
815
        $day = $this->request->param('Day');
816
817
        if (preg_match('/^[0-9]{1,2}$/', $day)) {
818
            if (checkdate($this->getArchiveMonth(), $day, $this->getArchiveYear())) {
819
                return (int) $day;
820
            }
821
        }
822
823
        return null;
824
    }
825
826
    /**
827
     * Renders the blog posts for a given tag.
828
     *
829
     * @return null|SS_HTTPResponse
830
     */
831 View Code Duplication
    public function tag()
832
    {
833
        $tag = $this->getCurrentTag();
834
835
        if ($tag) {
836
            $this->blogPosts = $tag->BlogPosts();
837
            return $this->render();
838
        }
839
840
        $this->httpError(404, 'Not Found');
841
842
        return null;
843
    }
844
845
    /**
846
     * Tag Getter for use in templates.
847
     *
848
     * @return null|BlogTag
849
     */
850 View Code Duplication
    public function getCurrentTag()
851
    {
852
        /**
853
         * @var Blog $dataRecord
854
         */
855
        $dataRecord = $this->dataRecord;
856
        $tag = $this->request->param('Tag');
857
        if ($tag) {
858
            return $dataRecord->Tags()
859
                ->filter('URLSegment', array($tag, rawurlencode($tag)))
860
                ->first();
861
        }
862
        return null;
863
    }
864
865
    /**
866
     * Renders the blog posts for a given category.
867
     *
868
     * @return null|SS_HTTPResponse
869
     */
870 View Code Duplication
    public function category()
871
    {
872
        $category = $this->getCurrentCategory();
873
874
        if ($category) {
875
            $this->blogPosts = $category->BlogPosts();
876
877
            return $this->render();
878
        }
879
880
        $this->httpError(404, 'Not Found');
881
882
        return null;
883
    }
884
885
    /**
886
     * Category Getter for use in templates.
887
     *
888
     * @return null|BlogCategory
889
     */
890 View Code Duplication
    public function getCurrentCategory()
891
    {
892
        /**
893
         * @var Blog $dataRecord
894
         */
895
        $dataRecord = $this->dataRecord;
896
        $category = $this->request->param('Category');
897
        if ($category) {
898
            return $dataRecord->Categories()
899
                ->filter('URLSegment', array($category, rawurlencode($category)))
900
                ->first();
901
        }
902
        return null;
903
    }
904
905
    /**
906
     * Get the meta title for the current action.
907
     *
908
     * @return string
909
     */
910
    public function getMetaTitle()
911
    {
912
        $title = $this->data()->getTitle();
913
        $filter = $this->getFilterDescription();
914
915
        if ($filter) {
916
            $title = sprintf('%s - %s', $title, $filter);
917
        }
918
919
        $this->extend('updateMetaTitle', $title);
920
921
        return $title;
922
    }
923
924
    /**
925
     * Returns a description of the current filter.
926
     *
927
     * @return string
928
     */
929
    public function getFilterDescription()
930
    {
931
        $items = array();
932
933
        $list = $this->PaginatedList();
934
        $currentPage = $list->CurrentPage();
935
936
        if ($currentPage > 1) {
937
            $items[] = _t(
938
                'Blog.FILTERDESCRIPTION_PAGE',
939
                'Page {page}',
940
                null,
941
                array(
942
                    'page' => $currentPage,
943
                )
944
            );
945
        }
946
947
        if ($author = $this->getCurrentProfile()) {
948
            $items[] = _t(
949
                'Blog.FILTERDESCRIPTION_AUTHOR',
950
                'By {author}',
951
                null,
952
                array(
953
                    'author' => $author->Title,
954
                )
955
            );
956
        }
957
958
        if ($tag = $this->getCurrentTag()) {
959
            $items[] = _t(
960
                'Blog.FILTERDESCRIPTION_TAG',
961
                'Tagged with {tag}',
962
                null,
963
                array(
964
                    'tag' => $tag->Title,
965
                )
966
            );
967
        }
968
969
        if ($category = $this->getCurrentCategory()) {
970
            $items[] = _t(
971
                'Blog.FILTERDESCRIPTION_CATEGORY',
972
                'In category {category}',
973
                null,
974
                array(
975
                    'category' => $category->Title,
976
                )
977
            );
978
        }
979
980
        if ($this->owner->getArchiveYear()) {
981
            if ($this->owner->getArchiveDay()) {
982
                $date = $this->owner->getArchiveDate()->Nice();
983
            } elseif ($this->owner->getArchiveMonth()) {
984
                $date = $this->owner->getArchiveDate()->format('F, Y');
985
            } else {
986
                $date = $this->owner->getArchiveDate()->format('Y');
987
            }
988
989
            $items[] = _t(
990
                'Blog.FILTERDESCRIPTION_DATE',
991
                'In {date}',
992
                null,
993
                array(
994
                    'date' => $date,
995
                )
996
            );
997
        }
998
999
        $result = '';
1000
1001
        if ($items) {
1002
            $result = implode(', ', $items);
1003
        }
1004
1005
        $this->extend('updateFilterDescription', $result);
1006
1007
        return $result;
1008
    }
1009
1010
    /**
1011
     * Returns a list of paginated blog posts based on the BlogPost dataList.
1012
     *
1013
     * @return PaginatedList
1014
     */
1015
    public function PaginatedList()
1016
    {
1017
        $allPosts = $this->blogPosts ?: new ArrayList();
1018
1019
        $posts = new PaginatedList($allPosts);
1020
1021
        // Set appropriate page size
1022
        if ($this->PostsPerPage > 0) {
1023
            $pageSize = $this->PostsPerPage;
1024
        } elseif ($count = $allPosts->count()) {
1025
            $pageSize = $count;
1026
        } else {
1027
            $pageSize = 99999;
1028
        }
1029
        $posts->setPageLength($pageSize);
1030
1031
        // Set current page
1032
        $start = $this->request->getVar($posts->getPaginationGetVar());
1033
        $posts->setPageStart($start);
1034
1035
        return $posts;
1036
    }
1037
1038
    /**
1039
     * Displays an RSS feed of blog posts.
1040
     *
1041
     * @return string
1042
     */
1043
    public function rss()
1044
    {
1045
        /**
1046
         * @var Blog $dataRecord
1047
         */
1048
        $dataRecord = $this->dataRecord;
1049
1050
        $this->blogPosts = $dataRecord->getBlogPosts();
1051
1052
        $rss = new RSSFeed($this->blogPosts, $this->Link(), $this->MetaTitle, $this->MetaDescription);
1053
1054
        $this->extend('updateRss', $rss);
1055
1056
        return $rss->outputToBrowser();
1057
    }
1058
1059
    /**
1060
     * Returns the current archive date.
1061
     *
1062
     * @return null|Date
1063
     */
1064
    public function getArchiveDate()
1065
    {
1066
        $year = $this->getArchiveYear();
1067
        $month = $this->getArchiveMonth();
1068
        $day = $this->getArchiveDay();
1069
1070
        if ($year) {
1071
            if ($month) {
1072
                $date = sprintf('%s-%s-01', $year, $month);
1073
1074
                if ($day) {
1075
                    $date = sprintf('%s-%s-%s', $year, $month, $day);
1076
                }
1077
            } else {
1078
                $date = sprintf('%s-01-01', $year);
1079
            }
1080
1081
            return DBField::create_field('Date', $date);
1082
        }
1083
1084
        return null;
1085
    }
1086
1087
    /**
1088
     * Returns a link to the RSS feed.
1089
     *
1090
     * @return string
1091
     */
1092
    public function getRSSLink()
1093
    {
1094
        return $this->Link('rss');
1095
    }
1096
}
1097