1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace SilverStripe\Blog\Model; |
4
|
|
|
|
5
|
|
|
use Exception; |
6
|
|
|
use Page; |
7
|
|
|
use SilverStripe\Blog\Admin\GridFieldCategorisationConfig; |
8
|
|
|
use SilverStripe\Blog\Forms\GridField\GridFieldConfigBlogPost; |
9
|
|
|
use SilverStripe\Control\Controller; |
10
|
|
|
use SilverStripe\Core\Convert; |
11
|
|
|
use SilverStripe\Forms\FieldList; |
12
|
|
|
use SilverStripe\Forms\GridField\GridField; |
13
|
|
|
use SilverStripe\Forms\GridField\GridFieldConfig; |
14
|
|
|
use SilverStripe\Forms\ListboxField; |
15
|
|
|
use SilverStripe\Forms\LiteralField; |
16
|
|
|
use SilverStripe\Forms\NumericField; |
17
|
|
|
use SilverStripe\Forms\Tab; |
18
|
|
|
use SilverStripe\Forms\TabSet; |
19
|
|
|
use SilverStripe\ORM\DataList; |
20
|
|
|
use SilverStripe\ORM\DataObject; |
21
|
|
|
use SilverStripe\ORM\DB; |
22
|
|
|
use SilverStripe\ORM\ManyManyList; |
23
|
|
|
use SilverStripe\ORM\SS_List; |
24
|
|
|
use SilverStripe\ORM\UnsavedRelationList; |
25
|
|
|
use SilverStripe\ORM\ValidationException; |
26
|
|
|
use SilverStripe\Security\Group; |
27
|
|
|
use SilverStripe\Security\Member; |
28
|
|
|
use SilverStripe\Security\Permission; |
29
|
|
|
use SilverStripe\Security\PermissionProvider; |
30
|
|
|
use SilverStripe\Security\Security; |
31
|
|
|
use SilverStripe\View\Requirements; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Blog Holder |
35
|
|
|
* |
36
|
|
|
* @property int $PostsPerPage |
37
|
|
|
* @method ManyManyList Editors() List of editors |
38
|
|
|
* @method ManyManyList Writers() List of writers |
39
|
|
|
* @method ManyManyList Contributors() List of contributors |
40
|
|
|
*/ |
41
|
|
|
class Blog extends Page implements PermissionProvider |
42
|
|
|
{ |
43
|
|
|
/** |
44
|
|
|
* Permission for user management. |
45
|
|
|
* |
46
|
|
|
* @var string |
47
|
|
|
*/ |
48
|
|
|
const MANAGE_USERS = 'BLOG_MANAGE_USERS'; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* If true, users assigned as editor, writer, or contributor will be automatically granted |
52
|
|
|
* CMS_ACCESS_CMSMain permission. If false, only users with this permission already may be |
53
|
|
|
* assigned. |
54
|
|
|
* |
55
|
|
|
* @config |
56
|
|
|
* |
57
|
|
|
* @var boolean |
58
|
|
|
*/ |
59
|
|
|
private static $grant_user_access = true; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Permission to either require, or grant to users assigned to work on this blog. |
63
|
|
|
* |
64
|
|
|
* @config |
65
|
|
|
* |
66
|
|
|
* @var string |
67
|
|
|
*/ |
68
|
|
|
private static $grant_user_permission = 'CMS_ACCESS_CMSMain'; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Group code to assign newly granted users to. |
72
|
|
|
* |
73
|
|
|
* @config |
74
|
|
|
* |
75
|
|
|
* @var string |
76
|
|
|
*/ |
77
|
|
|
private static $grant_user_group = 'blog-users'; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* {@inheritDoc} |
81
|
|
|
* @var string |
82
|
|
|
*/ |
83
|
|
|
private static $table_name = 'Blog'; |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* @var array |
87
|
|
|
*/ |
88
|
|
|
private static $db = [ |
89
|
|
|
'PostsPerPage' => 'Int', |
90
|
|
|
]; |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @var array |
94
|
|
|
*/ |
95
|
|
|
private static $many_many = [ |
96
|
|
|
'Editors' => Member::class, |
97
|
|
|
'Writers' => Member::class, |
98
|
|
|
'Contributors' => Member::class, |
99
|
|
|
]; |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @var array |
103
|
|
|
*/ |
104
|
|
|
private static $allowed_children = [ |
105
|
|
|
BlogPost::class, |
106
|
|
|
]; |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @var array |
110
|
|
|
*/ |
111
|
|
|
private static $extensions = [ |
112
|
|
|
BlogFilter::class, |
113
|
|
|
]; |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* @var array |
117
|
|
|
*/ |
118
|
|
|
private static $defaults = [ |
119
|
|
|
'ProvideComments' => false, |
120
|
|
|
'PostsPerPage' => 10 |
121
|
|
|
]; |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* @var string |
125
|
|
|
*/ |
126
|
|
|
private static $description = 'Adds a blog to your website.'; |
127
|
|
|
|
128
|
|
|
private static $icon_class = 'font-icon-p-posts'; |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Gets the list of all tags attached to this blog |
132
|
|
|
* |
133
|
|
|
* @param bool $hideEmpty Set to false to include tags without posts |
134
|
|
|
* @return DataList|BlogTag[] |
135
|
|
|
*/ |
136
|
|
View Code Duplication |
public function Tags($hideEmpty = true) |
|
|
|
|
137
|
|
|
{ |
138
|
|
|
$tags = BlogTag::get()->setDataQueryParam('BlogID', $this->ID); |
139
|
|
|
|
140
|
|
|
// Conditionally hide empty tags |
141
|
|
|
if ($this->ID && $hideEmpty) { |
142
|
|
|
$tags = $tags->filter([ |
143
|
|
|
'BlogPosts.ParentID' => $this->ID, |
144
|
|
|
]); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$this->extend('updateBlogTags', $tags); |
148
|
|
|
return $tags; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* Gets the list of all categories attached to this blog |
153
|
|
|
* |
154
|
|
|
* @param bool $hideEmpty Set to false to include categories without posts |
155
|
|
|
* @return DataList|BlogCategory[] |
156
|
|
|
*/ |
157
|
|
View Code Duplication |
public function Categories($hideEmpty = true) |
|
|
|
|
158
|
|
|
{ |
159
|
|
|
$tags = BlogCategory::get()->setDataQueryParam('BlogID', $this->ID); |
160
|
|
|
|
161
|
|
|
// Conditionally hide empty categories |
162
|
|
|
if ($this->ID && $hideEmpty) { |
163
|
|
|
$tags = $tags->filter([ |
164
|
|
|
'BlogPosts.ParentID' => $this->ID, |
165
|
|
|
]); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
$this->extend('updateBlogCategories', $tags); |
169
|
|
|
return $tags; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* {@inheritdoc} |
174
|
|
|
*/ |
175
|
|
|
public function getCMSFields() |
176
|
|
|
{ |
177
|
|
|
$this->addCMSRequirements(); |
178
|
|
|
|
179
|
|
|
$this->beforeUpdateCMSFields(function (FieldList $fields) { |
180
|
|
|
if (!$this->canEdit()) { |
181
|
|
|
return; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
$categories = GridField::create( |
185
|
|
|
'Categories', |
186
|
|
|
_t(__CLASS__ . '.Categories', 'Categories'), |
187
|
|
|
$this->Categories(false), |
188
|
|
|
GridFieldCategorisationConfig::create( |
189
|
|
|
15, |
190
|
|
|
$this->Categories(false)->sort('Title'), |
191
|
|
|
BlogCategory::class, |
192
|
|
|
'Categories', |
193
|
|
|
'BlogPosts' |
194
|
|
|
) |
195
|
|
|
); |
196
|
|
|
|
197
|
|
|
$tags = GridField::create( |
198
|
|
|
'Tags', |
199
|
|
|
_t(__CLASS__ . '.Tags', 'Tags'), |
200
|
|
|
$this->Tags(false), |
201
|
|
|
GridFieldCategorisationConfig::create( |
202
|
|
|
15, |
203
|
|
|
$this->Tags(false)->sort('Title'), |
204
|
|
|
BlogTag::class, |
205
|
|
|
'Tags', |
206
|
|
|
'BlogPosts' |
207
|
|
|
) |
208
|
|
|
); |
209
|
|
|
|
210
|
|
|
$fields->addFieldToTab( |
211
|
|
|
'Root', |
212
|
|
|
TabSet::create('Categorisation', _t(__CLASS__ . '.Categorisation', 'Categorisation')) |
213
|
|
|
->addExtraClass('blog-cms-categorisation') |
214
|
|
|
); |
215
|
|
|
$fields->addFieldToTab( |
216
|
|
|
'Root.Categorisation', |
217
|
|
|
Tab::create('Categories', _t(__CLASS__ . '.Categories', 'Categories')) |
218
|
|
|
); |
219
|
|
|
$fields->addFieldToTab( |
220
|
|
|
'Root.Categorisation', |
221
|
|
|
Tab::create('Tags', _t(__CLASS__ . '.Tags', 'Tags')) |
222
|
|
|
); |
223
|
|
|
|
224
|
|
|
$fields->addFieldToTab('Root.Categorisation.Categories', $categories); |
225
|
|
|
$fields->addFieldToTab('Root.Categorisation.Tags', $tags); |
226
|
|
|
}); |
227
|
|
|
|
228
|
|
|
return parent::getCMSFields(); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Adds CMS related css and js overrides |
233
|
|
|
*/ |
234
|
|
|
protected function addCMSRequirements() |
235
|
|
|
{ |
236
|
|
|
Requirements::css('silverstripe/blog:client/dist/styles/main.css'); |
237
|
|
|
Requirements::javascript('silverstripe/blog:client/dist/js/main.bundle.js'); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* {@inheritdoc} |
242
|
|
|
*/ |
243
|
|
|
public function canEdit($member = null) |
244
|
|
|
{ |
245
|
|
|
$member = $this->getMember($member); |
246
|
|
|
|
247
|
|
|
if ($this->isEditor($member)) { |
248
|
|
|
return true; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
return parent::canEdit($member); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* @param null|int|Member $member |
256
|
|
|
* |
257
|
|
|
* @return null|Member |
258
|
|
|
*/ |
259
|
|
View Code Duplication |
protected function getMember($member = null) |
|
|
|
|
260
|
|
|
{ |
261
|
|
|
if (!$member) { |
262
|
|
|
$member = Security::getCurrentUser(); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
if (is_numeric($member)) { |
266
|
|
|
$member = Member::get()->byID($member); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
return $member; |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* Check if this member is an editor of the blog. |
274
|
|
|
* |
275
|
|
|
* @param Member $member |
276
|
|
|
* |
277
|
|
|
* @return bool |
278
|
|
|
*/ |
279
|
|
|
public function isEditor($member) |
280
|
|
|
{ |
281
|
|
|
$isEditor = $this->isMemberOf($member, $this->Editors()); |
282
|
|
|
$this->extend('updateIsEditor', $isEditor, $member); |
283
|
|
|
|
284
|
|
|
return $isEditor; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Determine if the given member belongs to the given relation. |
289
|
|
|
* |
290
|
|
|
* @param Member $member |
291
|
|
|
* @param DataList $relation |
292
|
|
|
* |
293
|
|
|
* @return bool |
294
|
|
|
*/ |
295
|
|
View Code Duplication |
protected function isMemberOf($member, $relation) |
|
|
|
|
296
|
|
|
{ |
297
|
|
|
if (!$member || !$member->exists()) { |
298
|
|
|
return false; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
if ($relation instanceof UnsavedRelationList) { |
302
|
|
|
return in_array($member->ID, $relation->getIDList()); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
return $relation->byID($member->ID) !== null; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* Determine the role of the given member. |
310
|
|
|
* |
311
|
|
|
* Call be called via template to determine the current user. |
312
|
|
|
* |
313
|
|
|
* @example "Hello $RoleOf($CurrentMember.ID)" |
314
|
|
|
* |
315
|
|
|
* @param int|Member $member |
316
|
|
|
* |
317
|
|
|
* @return null|string |
318
|
|
|
*/ |
319
|
|
|
public function RoleOf($member) |
320
|
|
|
{ |
321
|
|
|
if (is_numeric($member)) { |
322
|
|
|
$member = Member::get()->byId($member); |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
if (!$member) { |
326
|
|
|
return null; |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
if ($this->isEditor($member)) { |
330
|
|
|
return _t(__CLASS__ . '.EDITOR', 'Editor'); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
if ($this->isWriter($member)) { |
334
|
|
|
return _t(__CLASS__ . '.WRITER', 'Writer'); |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
if ($this->isContributor($member)) { |
338
|
|
|
return _t(__CLASS__ . '.CONTRIBUTOR', 'Contributor'); |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
return null; |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Check if this member is a writer of the blog. |
346
|
|
|
* |
347
|
|
|
* @param Member $member |
348
|
|
|
* |
349
|
|
|
* @return bool |
350
|
|
|
*/ |
351
|
|
|
public function isWriter($member) |
352
|
|
|
{ |
353
|
|
|
$isWriter = $this->isMemberOf($member, $this->Writers()); |
354
|
|
|
$this->extend('updateIsWriter', $isWriter, $member); |
355
|
|
|
|
356
|
|
|
return $isWriter; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* Check if this member is a contributor of the blog. |
361
|
|
|
* |
362
|
|
|
* @param Member $member |
363
|
|
|
* |
364
|
|
|
* @return bool |
365
|
|
|
*/ |
366
|
|
|
public function isContributor($member) |
367
|
|
|
{ |
368
|
|
|
$isContributor = $this->isMemberOf($member, $this->Contributors()); |
369
|
|
|
$this->extend('updateIsContributor', $isContributor, $member); |
370
|
|
|
|
371
|
|
|
return $isContributor; |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* {@inheritdoc} |
376
|
|
|
*/ |
377
|
|
|
public function canAddChildren($member = null) |
378
|
|
|
{ |
379
|
|
|
$member = $this->getMember($member); |
380
|
|
|
|
381
|
|
|
if ($this->isEditor($member) || $this->isWriter($member) || $this->isContributor($member)) { |
382
|
|
|
return true; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
return parent::canAddChildren($member); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
/** |
389
|
|
|
* {@inheritdoc} |
390
|
|
|
*/ |
391
|
|
|
public function getSettingsFields() |
392
|
|
|
{ |
393
|
|
|
$this->addCMSRequirements(); |
394
|
|
|
$fields = parent::getSettingsFields(); |
395
|
|
|
|
396
|
|
|
$fields->addFieldToTab( |
397
|
|
|
'Root.Settings', |
398
|
|
|
NumericField::create('PostsPerPage', _t(__CLASS__ . '.PostsPerPage', 'Posts Per Page')) |
399
|
|
|
); |
400
|
|
|
|
401
|
|
|
$members = $this->getCandidateUsers()->map()->toArray(); |
402
|
|
|
$toggleButton = LiteralField::create( |
403
|
|
|
'ToggleButton', |
404
|
|
|
'<a class="font-icon-info-circled toggle-description"></a>' |
405
|
|
|
); |
406
|
|
|
|
407
|
|
|
$editorField = ListboxField::create('Editors', 'Editors', $members) |
408
|
|
|
->setRightTitle($toggleButton) |
409
|
|
|
->setDescription( |
410
|
|
|
_t( |
411
|
|
|
__CLASS__ . '.UsersEditorsFieldDescription', |
412
|
|
|
'An editor has control over specific Blogs, and all posts included within it. |
413
|
|
|
Short of being able to assign other editors to a blog, they are able to handle most changes to |
414
|
|
|
their assigned blog. <br /><br /> |
415
|
|
|
Editors have these permissions:<br /> |
416
|
|
|
<br /> |
417
|
|
|
Update or publish any BlogPost in their Blog<br /> |
418
|
|
|
Update or publish their Blog<br /> |
419
|
|
|
Assign/unassign writers to their Blog<br /> |
420
|
|
|
Assign/unassign contributors to their Blog<br /> |
421
|
|
|
Assign/unassign any member as an author of a particular BlogPost' |
422
|
|
|
) |
423
|
|
|
); |
424
|
|
|
if (!$this->canEditEditors()) { |
425
|
|
|
$editorField = $editorField->performDisabledTransformation(); |
426
|
|
|
} |
427
|
|
|
$writerField = ListboxField::create('Writers', 'Writers', $members) |
428
|
|
|
->setRightTitle($toggleButton) |
429
|
|
|
->setDescription( |
430
|
|
|
_t( |
431
|
|
|
__CLASS__ . '.UsersWritersFieldDescription', |
432
|
|
|
'A writer has full control over creating, editing and publishing BlogPosts they have authored |
433
|
|
|
or have been assigned to. Writers are unable to edit BlogPosts to which they are not assigned. |
434
|
|
|
<br /><br /> |
435
|
|
|
Writers have these permissions:<br /> |
436
|
|
|
<br /> |
437
|
|
|
Update or publish any BlogPost they have authored or have been assigned to<br /> |
438
|
|
|
Assign/unassign any member as an author of a particular BlogPost they have authored or have been |
439
|
|
|
assigned to' |
440
|
|
|
) |
441
|
|
|
); |
442
|
|
|
|
443
|
|
|
if (!$this->canEditWriters()) { |
444
|
|
|
$writerField = $writerField->performDisabledTransformation(); |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
$contributorField = ListboxField::create('Contributors', 'Contributors', $members) |
448
|
|
|
// ->setMultiple(true) |
449
|
|
|
->setRightTitle($toggleButton) |
450
|
|
|
->setDescription( |
451
|
|
|
_t( |
452
|
|
|
__CLASS__ . '.UsersContributorsFieldDescription', |
453
|
|
|
'Contributors have the ability to create or edit BlogPosts, but are unable to publish without |
454
|
|
|
authorisation of an editor. They are also unable to assign other contributing authors to any of |
455
|
|
|
their BlogPosts.<br /> |
456
|
|
|
<br /> |
457
|
|
|
Contributors have these permissions:<br /> |
458
|
|
|
<br /> |
459
|
|
|
Update any BlogPost they have authored or have been assigned to' |
460
|
|
|
) |
461
|
|
|
); |
462
|
|
|
|
463
|
|
|
if (!$this->canEditContributors()) { |
464
|
|
|
$contributorField = $contributorField->performDisabledTransformation(); |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
$fields->addFieldsToTab( |
468
|
|
|
'Root.Users', |
469
|
|
|
[ |
470
|
|
|
$editorField, |
471
|
|
|
$writerField, |
472
|
|
|
$contributorField |
473
|
|
|
] |
474
|
|
|
); |
475
|
|
|
|
476
|
|
|
return $fields; |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
/** |
480
|
|
|
* Gets the list of user candidates to be assigned to assist with this blog. |
481
|
|
|
* |
482
|
|
|
* @return SS_List |
483
|
|
|
*/ |
484
|
|
|
protected function getCandidateUsers() |
485
|
|
|
{ |
486
|
|
|
if ($this->config()->get('grant_user_access')) { |
487
|
|
|
$list = Member::get(); |
488
|
|
|
$this->extend('updateCandidateUsers', $list); |
489
|
|
|
return $list; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
return Permission::get_members_by_permission( |
493
|
|
|
$this->config()->get('grant_user_permission') |
494
|
|
|
); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* Determine if this user can edit the editors list. |
499
|
|
|
* |
500
|
|
|
* @param int|Member $member |
501
|
|
|
* |
502
|
|
|
* @return bool |
503
|
|
|
*/ |
504
|
|
|
public function canEditEditors($member = null) |
505
|
|
|
{ |
506
|
|
|
$member = $this->getMember($member); |
507
|
|
|
|
508
|
|
|
$extended = $this->extendedCan('canEditEditors', $member); |
509
|
|
|
|
510
|
|
|
if ($extended !== null) { |
511
|
|
|
return $extended; |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
return Permission::checkMember($member, self::MANAGE_USERS); |
|
|
|
|
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
/** |
518
|
|
|
* Determine if this user can edit writers list. |
519
|
|
|
* |
520
|
|
|
* @param int|Member $member |
521
|
|
|
* |
522
|
|
|
* @return boolean |
523
|
|
|
*/ |
524
|
|
View Code Duplication |
public function canEditWriters($member = null) |
|
|
|
|
525
|
|
|
{ |
526
|
|
|
$member = $this->getMember($member); |
527
|
|
|
|
528
|
|
|
$extended = $this->extendedCan('canEditWriters', $member); |
529
|
|
|
|
530
|
|
|
if ($extended !== null) { |
531
|
|
|
return $extended; |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
if ($this->isEditor($member)) { |
535
|
|
|
return true; |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
return Permission::checkMember($member, self::MANAGE_USERS); |
|
|
|
|
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* Determines if this user can edit the contributors list. |
543
|
|
|
* |
544
|
|
|
* @param int|Member $member |
545
|
|
|
* |
546
|
|
|
* @return boolean |
547
|
|
|
*/ |
548
|
|
View Code Duplication |
public function canEditContributors($member = null) |
|
|
|
|
549
|
|
|
{ |
550
|
|
|
$member = $this->getMember($member); |
551
|
|
|
|
552
|
|
|
$extended = $this->extendedCan('canEditContributors', $member); |
553
|
|
|
|
554
|
|
|
if ($extended !== null) { |
555
|
|
|
return $extended; |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
if ($this->isEditor($member)) { |
559
|
|
|
return true; |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
return Permission::checkMember($member, self::MANAGE_USERS); |
|
|
|
|
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
/** |
566
|
|
|
* Returns BlogPosts for a given date period. |
567
|
|
|
* |
568
|
|
|
* @param int $year |
569
|
|
|
* @param null|int $month |
570
|
|
|
* @param null|int $day |
571
|
|
|
* |
572
|
|
|
* @return DataList |
573
|
|
|
*/ |
574
|
|
|
public function getArchivedBlogPosts($year, $month = null, $day = null) |
575
|
|
|
{ |
576
|
|
|
$query = $this->getBlogPosts()->dataQuery(); |
577
|
|
|
|
578
|
|
|
$stage = $query->getQueryParam('Versioned.stage'); |
579
|
|
|
|
580
|
|
|
if ($stage) { |
581
|
|
|
$stage = '_' . $stage; |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
$query->innerJoin( |
585
|
|
|
DataObject::getSchema()->tableName(BlogPost::class), |
586
|
|
|
sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage) |
587
|
|
|
); |
588
|
|
|
|
589
|
|
|
$conn = DB::get_conn(); |
590
|
|
|
|
591
|
|
|
// Filter by year |
592
|
|
|
$yearCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%Y'); |
593
|
|
|
$query->where(sprintf('%s = \'%04d\'', $yearCond, Convert::raw2sql($year))); |
594
|
|
|
|
595
|
|
|
// Filter by month (if given) |
596
|
|
|
if ($month) { |
|
|
|
|
597
|
|
|
$monthCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%m'); |
598
|
|
|
$query->where(sprintf('%s = \'%02d\'', $monthCond, Convert::raw2sql($month))); |
599
|
|
|
|
600
|
|
|
if ($day) { |
|
|
|
|
601
|
|
|
$dayCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%d'); |
602
|
|
|
$query->where(sprintf('%s = \'%02d\'', $dayCond, Convert::raw2sql($day))); |
603
|
|
|
} |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
|
607
|
|
|
return $this->getBlogPosts()->setDataQuery($query); |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
/** |
611
|
|
|
* Return blog posts. |
612
|
|
|
* |
613
|
|
|
* @return DataList of BlogPost objects |
614
|
|
|
*/ |
615
|
|
|
public function getBlogPosts() |
616
|
|
|
{ |
617
|
|
|
$blogPosts = BlogPost::get()->filter('ParentID', $this->ID); |
618
|
|
|
|
619
|
|
|
$this->extend('updateGetBlogPosts', $blogPosts); |
620
|
|
|
|
621
|
|
|
return $blogPosts; |
622
|
|
|
} |
623
|
|
|
|
624
|
|
|
/** |
625
|
|
|
* Get a link to a Member profile. |
626
|
|
|
* |
627
|
|
|
* @param string $urlSegment |
628
|
|
|
* |
629
|
|
|
* @return string |
630
|
|
|
*/ |
631
|
|
|
public function ProfileLink($urlSegment) |
632
|
|
|
{ |
633
|
|
|
return Controller::join_links($this->Link('profile'), $urlSegment); |
634
|
|
|
} |
635
|
|
|
|
636
|
|
|
/** |
637
|
|
|
* This sets the title for our gridfield. |
638
|
|
|
* |
639
|
|
|
* @return string |
640
|
|
|
*/ |
641
|
|
|
public function getLumberjackTitle() |
642
|
|
|
{ |
643
|
|
|
return _t(__CLASS__ . '.LumberjackTitle', 'Blog Posts'); |
644
|
|
|
} |
645
|
|
|
|
646
|
|
|
/** |
647
|
|
|
* This overwrites lumberjacks default gridfield config. |
648
|
|
|
* |
649
|
|
|
* @return GridFieldConfig |
650
|
|
|
*/ |
651
|
|
|
public function getLumberjackGridFieldConfig() |
652
|
|
|
{ |
653
|
|
|
return GridFieldConfigBlogPost::create(); |
654
|
|
|
} |
655
|
|
|
|
656
|
|
|
/** |
657
|
|
|
* {@inheritdoc} |
658
|
|
|
*/ |
659
|
|
|
public function providePermissions() |
660
|
|
|
{ |
661
|
|
|
return [ |
662
|
|
|
Blog::MANAGE_USERS => [ |
663
|
|
|
'name' => _t( |
664
|
|
|
__CLASS__ . '.PERMISSION_MANAGE_USERS_DESCRIPTION', |
665
|
|
|
'Manage users for individual blogs' |
666
|
|
|
), |
667
|
|
|
'help' => _t( |
668
|
|
|
__CLASS__ . '.PERMISSION_MANAGE_USERS_HELP', |
669
|
|
|
'Allow assignment of Editors, Writers, or Contributors to blogs' |
670
|
|
|
), |
671
|
|
|
'category' => _t(__CLASS__ . '.PERMISSIONS_CATEGORY', 'Blog permissions'), |
672
|
|
|
'sort' => 100 |
673
|
|
|
] |
674
|
|
|
]; |
675
|
|
|
} |
676
|
|
|
|
677
|
|
|
/** |
678
|
|
|
* @throws ValidationException |
679
|
|
|
*/ |
680
|
|
|
protected function onBeforeWrite() |
681
|
|
|
{ |
682
|
|
|
parent::onBeforeWrite(); |
683
|
|
|
$this->assignGroup(); |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
/** |
687
|
|
|
* Assign users as necessary to the blog group. |
688
|
|
|
* |
689
|
|
|
* @throws ValidationException |
690
|
|
|
* @throws Exception |
691
|
|
|
*/ |
692
|
|
|
protected function assignGroup() |
693
|
|
|
{ |
694
|
|
|
if (!$this->config()->get('grant_user_access')) { |
695
|
|
|
return; |
696
|
|
|
} |
697
|
|
|
|
698
|
|
|
$group = $this->getUserGroup(); |
699
|
|
|
|
700
|
|
|
// Must check if the method exists or else an error occurs when changing page type |
701
|
|
|
if ($this->hasMethod('Editors')) { |
702
|
|
|
foreach ([$this->Editors(), $this->Writers(), $this->Contributors()] as $levels) { |
703
|
|
|
/** @var Member $user */ |
704
|
|
|
foreach ($levels as $user) { |
705
|
|
|
if (!$user->inGroup($group)) { |
706
|
|
|
$user->Groups()->add($group); |
707
|
|
|
} |
708
|
|
|
} |
709
|
|
|
} |
710
|
|
|
} |
711
|
|
|
} |
712
|
|
|
|
713
|
|
|
/** |
714
|
|
|
* Gets or creates the group used to assign CMS access. |
715
|
|
|
* |
716
|
|
|
* @return Group |
717
|
|
|
* @throws ValidationException |
718
|
|
|
*/ |
719
|
|
|
protected function getUserGroup() |
720
|
|
|
{ |
721
|
|
|
$code = $this->config()->get('grant_user_group'); |
722
|
|
|
|
723
|
|
|
/** @var Group $group */ |
724
|
|
|
$group = Group::get()->filter('Code', $code)->first(); |
725
|
|
|
if ($group) { |
726
|
|
|
return $group; |
727
|
|
|
} |
728
|
|
|
|
729
|
|
|
$group = Group::create(); |
730
|
|
|
$group->Title = 'Blog users'; |
731
|
|
|
$group->Code = $code; |
732
|
|
|
|
733
|
|
|
$group->write(); |
734
|
|
|
|
735
|
|
|
$permission = Permission::create(); |
736
|
|
|
$permission->Code = $this->config()->get('grant_user_permission'); |
737
|
|
|
|
738
|
|
|
$group->Permissions()->add($permission); |
739
|
|
|
|
740
|
|
|
return $group; |
741
|
|
|
} |
742
|
|
|
} |
743
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.