'Int', ]; /** * @var array */ private static $has_many = [ 'Tags' => BlogTag::class, 'Categories' => BlogCategory::class, ]; /** * @var array */ private static $many_many = [ 'Editors' => Member::class, 'Writers' => Member::class, 'Contributors' => Member::class, ]; /** * @var array */ private static $allowed_children = [ BlogPost::class, ]; /** * @var array */ private static $extensions = [ BlogFilter::class, ]; /** * The ProvideComments db column is defined in the silverstripe/comments module * * @var array */ private static $defaults = [ 'ProvideComments' => false, 'PostsPerPage' => 10 ]; /** * @var string */ private static $description = 'Adds a blog to your website.'; private static $icon_class = 'font-icon-p-posts'; /** * {@inheritdoc} */ public function getCMSFields() { $this->addCMSRequirements(); $this->beforeUpdateCMSFields(function ($fields) { if (!$this->canEdit()) { return; } $categories = GridField::create( 'Categories', _t(__CLASS__ . '.Categories', 'Categories'), $this->Categories(), GridFieldCategorisationConfig::create( 15, $this->Categories()->sort('Title'), BlogCategory::class, 'Categories', 'BlogPosts' ) ); $tags = GridField::create( 'Tags', _t(__CLASS__ . '.Tags', 'Tags'), $this->Tags(), GridFieldCategorisationConfig::create( 15, $this->Tags()->sort('Title'), BlogTag::class, 'Tags', 'BlogPosts' ) ); /** * @var FieldList $fields */ $fields->addFieldsToTab( 'Root.Categorisation', [ $categories, $tags ] ); $fields->fieldByName('Root.Categorisation') ->addExtraClass('blog-cms-categorisation') ->setTitle(_t(__CLASS__ . '.Categorisation', 'Categorisation')); }); return parent::getCMSFields(); } /** * Adds CMS related css and js overrides */ protected function addCMSRequirements() { Requirements::css('silverstripe/blog:client/dist/styles/main.css'); Requirements::javascript('silverstripe/blog:client/dist/js/main.bundle.js'); } /** * {@inheritdoc} */ public function canEdit($member = null) { $member = $this->getMember($member); if ($this->isEditor($member)) { return true; } return parent::canEdit($member); } /** * @param null|int|Member $member * * @return null|Member */ protected function getMember($member = null) { if (!$member) { $member = Security::getCurrentUser(); } if (is_numeric($member)) { $member = Member::get()->byID($member); } return $member; } /** * Check if this member is an editor of the blog. * * @param Member $member * * @return bool */ public function isEditor($member) { $isEditor = $this->isMemberOf($member, $this->Editors()); $this->extend('updateIsEditor', $isEditor, $member); return $isEditor; } /** * Determine if the given member belongs to the given relation. * * @param Member $member * @param DataList $relation * * @return bool */ protected function isMemberOf($member, $relation) { if (!$member || !$member->exists()) { return false; } if ($relation instanceof UnsavedRelationList) { return in_array($member->ID, $relation->getIDList()); } return $relation->byID($member->ID) !== null; } /** * Determine the role of the given member. * * Call be called via template to determine the current user. * * @example "Hello $RoleOf($CurrentMember.ID)" * * @param int|Member $member * * @return null|string */ public function RoleOf($member) { if (is_numeric($member)) { $member = Member::get()->byId($member); } if (!$member) { return null; } if ($this->isEditor($member)) { return _t(__CLASS__ . '.EDITOR', 'Editor'); } if ($this->isWriter($member)) { return _t(__CLASS__ . '.WRITER', 'Writer'); } if ($this->isContributor($member)) { return _t(__CLASS__ . '.CONTRIBUTOR', 'Contributor'); } return null; } /** * Check if this member is a writer of the blog. * * @param Member $member * * @return bool */ public function isWriter($member) { $isWriter = $this->isMemberOf($member, $this->Writers()); $this->extend('updateIsWriter', $isWriter, $member); return $isWriter; } /** * Check if this member is a contributor of the blog. * * @param Member $member * * @return bool */ public function isContributor($member) { $isContributor = $this->isMemberOf($member, $this->Contributors()); $this->extend('updateIsContributor', $isContributor, $member); return $isContributor; } /** * {@inheritdoc} */ public function canAddChildren($member = null) { $member = $this->getMember($member); if ($this->isEditor($member) || $this->isWriter($member) || $this->isContributor($member)) { return true; } return parent::canAddChildren($member); } /** * {@inheritdoc} */ public function getSettingsFields() { $this->addCMSRequirements(); $fields = parent::getSettingsFields(); $fields->addFieldToTab( 'Root.Settings', NumericField::create('PostsPerPage', _t(__CLASS__ . '.PostsPerPage', 'Posts Per Page')) ); $members = $this->getCandidateUsers()->map()->toArray(); $toggleButton = LiteralField::create( 'ToggleButton', '' ); $editorField = ListboxField::create('Editors', 'Editors', $members) ->setRightTitle($toggleButton) ->setDescription( _t( __CLASS__ . '.UsersEditorsFieldDescription', '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.

Editors have these permissions:

Update or publish any BlogPost in their Blog
Update or publish their Blog
Assign/unassign writers to their Blog
Assign/unassign contributors to their Blog
Assign/unassign any member as an author of a particular BlogPost' ) ); if (!$this->canEditEditors()) { $editorField = $editorField->performDisabledTransformation(); } $writerField = ListboxField::create('Writers', 'Writers', $members) ->setRightTitle($toggleButton) ->setDescription( _t( __CLASS__ . '.UsersWritersFieldDescription', '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.

Writers have these permissions:

Update or publish any BlogPost they have authored or have been assigned to
Assign/unassign any member as an author of a particular BlogPost they have authored or have been assigned to' ) ); if (!$this->canEditWriters()) { $writerField = $writerField->performDisabledTransformation(); } $contributorField = ListboxField::create('Contributors', 'Contributors', $members) // ->setMultiple(true) ->setRightTitle($toggleButton) ->setDescription( _t( __CLASS__ . '.UsersContributorsFieldDescription', '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.

Contributors have these permissions:

Update any BlogPost they have authored or have been assigned to' ) ); if (!$this->canEditContributors()) { $contributorField = $contributorField->performDisabledTransformation(); } $fields->addFieldsToTab( 'Root.Users', [ $editorField, $writerField, $contributorField ] ); return $fields; } /** * Gets the list of user candidates to be assigned to assist with this blog. * * @return SS_List */ protected function getCandidateUsers() { if ($this->config()->get('grant_user_access')) { $list = Member::get(); $this->extend('updateCandidateUsers', $list); return $list; } return Permission::get_members_by_permission( $this->config()->get('grant_user_permission') ); } /** * Determine if this user can edit the editors list. * * @param int|Member $member * * @return bool */ public function canEditEditors($member = null) { $member = $this->getMember($member); $extended = $this->extendedCan('canEditEditors', $member); if ($extended !== null) { return $extended; } return Permission::checkMember($member, self::MANAGE_USERS); } /** * Determine if this user can edit writers list. * * @param int|Member $member * * @return boolean */ public function canEditWriters($member = null) { $member = $this->getMember($member); $extended = $this->extendedCan('canEditWriters', $member); if ($extended !== null) { return $extended; } if ($this->isEditor($member)) { return true; } return Permission::checkMember($member, self::MANAGE_USERS); } /** * Determines if this user can edit the contributors list. * * @param int|Member $member * * @return boolean */ public function canEditContributors($member = null) { $member = $this->getMember($member); $extended = $this->extendedCan('canEditContributors', $member); if ($extended !== null) { return $extended; } if ($this->isEditor($member)) { return true; } return Permission::checkMember($member, self::MANAGE_USERS); } /** * Returns BlogPosts for a given date period. * * @param int $year * @param null|int $month * @param null|int $day * * @return DataList */ public function getArchivedBlogPosts($year, $month = null, $day = null) { $query = $this->getBlogPosts()->dataQuery(); $stage = $query->getQueryParam('Versioned.stage'); if ($stage) { $stage = '_' . $stage; } $query->innerJoin( DataObject::getSchema()->tableName(BlogPost::class), sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage) ); $conn = DB::get_conn(); // Filter by year $yearCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%Y'); $query->where(sprintf('%s = \'%04d\'', $yearCond, Convert::raw2sql($year))); // Filter by month (if given) if ($month) { $monthCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%m'); $query->where(sprintf('%s = \'%02d\'', $monthCond, Convert::raw2sql($month))); if ($day) { $dayCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%d'); $query->where(sprintf('%s = \'%02d\'', $dayCond, Convert::raw2sql($day))); } } return $this->getBlogPosts()->setDataQuery($query); } /** * Return blog posts. * * @return DataList of BlogPost objects */ public function getBlogPosts() { $blogPosts = BlogPost::get()->filter('ParentID', $this->ID); $this->extend('updateGetBlogPosts', $blogPosts); return $blogPosts; } /** * Get a link to a Member profile. * * @param string $urlSegment * * @return string */ public function ProfileLink($urlSegment) { $baseLink = $this->Link(); if ($baseLink === '/') { // Handle homepage blogs $baseLink = RootURLController::get_homepage_link(); } return Controller::join_links($baseLink, 'profile', $urlSegment); } /** * This sets the title for our gridfield. * * @return string */ public function getLumberjackTitle() { return _t(__CLASS__ . '.LumberjackTitle', 'Blog Posts'); } /** * This overwrites lumberjacks default gridfield config. * * @return GridFieldConfig */ public function getLumberjackGridFieldConfig() { return GridFieldConfigBlogPost::create(); } /** * {@inheritdoc} */ public function providePermissions() { return [ Blog::MANAGE_USERS => [ 'name' => _t( __CLASS__ . '.PERMISSION_MANAGE_USERS_DESCRIPTION', 'Manage users for individual blogs' ), 'help' => _t( __CLASS__ . '.PERMISSION_MANAGE_USERS_HELP', 'Allow assignment of Editors, Writers, or Contributors to blogs' ), 'category' => _t(__CLASS__ . '.PERMISSIONS_CATEGORY', 'Blog permissions'), 'sort' => 100 ] ]; } /** * {@inheritdoc} */ protected function onBeforeWrite() { parent::onBeforeWrite(); $this->assignGroup(); } /** * Assign users as necessary to the blog group. */ protected function assignGroup() { if (!$this->config()->get('grant_user_access')) { return; } $group = $this->getUserGroup(); // Must check if the method exists or else an error occurs when changing page type if ($this->hasMethod('Editors')) { foreach ([$this->Editors(), $this->Writers(), $this->Contributors()] as $levels) { foreach ($levels as $user) { if (!$user->inGroup($group)) { $user->Groups()->add($group); } } } } } /** * Gets or creates the group used to assign CMS access. * * @return Group */ protected function getUserGroup() { $code = $this->config()->get('grant_user_group'); $group = Group::get()->filter('Code', $code)->first(); if ($group) { return $group; } $group = Group::create(); $group->Title = 'Blog users'; $group->Code = $code; $group->write(); $permission = Permission::create(); $permission->Code = $this->config()->get('grant_user_permission'); $group->Permissions()->add($permission); return $group; } }