silverstripe-blog/src/Model/BlogObject.php

248 lines
6.2 KiB
PHP

<?php
namespace SilverStripe\Blog\Model;
use SilverStripe\Control\Controller;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\TabSet;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Member;
use SilverStripe\Security\Permission;
use SilverStripe\View\Parsers\URLSegmentFilter;
/**
* An object shared by BlogTag and BlogCategory.
*
*/
trait BlogObject
{
/**
* @param int|array|null $id Optional ID(s) for parent of this relation, if not the current record
* @return DataList
*/
public function BlogPosts($id = null)
{
$blogPosts = parent::BlogPosts($id);
$this->extend('updateGetBlogPosts', $blogPosts);
return $blogPosts;
}
/**
* {@inheritdoc}
*/
public function getCMSFields()
{
$fields = TabSet::create(
'Root',
Tab::create(
'Main',
TextField::create('Title', _t(__CLASS__ . '.Title', 'Title'))
)
);
$fields = FieldList::create($fields);
$this->extend('updateCMSFields', $fields);
return $fields;
}
/**
* {@inheritdoc}
* @return ValidationResult
*/
public function validate()
{
/** @var ValidationResult $validation */
$validation = parent::validate();
if (!$validation->isValid()) {
return $validation;
}
$blog = $this->Blog();
if (!$blog || !$blog->exists()) {
return $validation;
}
if ($this->getDuplicatesByField('Title')->count() > 0) {
$validation->addError($this->getDuplicateError(), self::DUPLICATE_EXCEPTION);
}
return $validation;
}
/**
* Returns a relative link to this category.
*
* @return string
*/
public function getLink()
{
return Controller::join_links(
$this->Blog()->Link(),
$this->getListUrlSegment(),
$this->URLSegment
);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param null|Member $member
*
* @return bool
*/
public function canView($member = null)
{
$extended = $this->extendedCan(__FUNCTION__, $member);
if ($extended !== null) {
return $extended;
}
return $this->Blog()->canView($member);
}
/**
* {@inheritdoc}
*/
public function canCreate($member = null, $context = [])
{
$extended = $this->extendedCan(__FUNCTION__, $member);
if ($extended !== null) {
return $extended;
}
$permission = Blog::config()->grant_user_permission;
return Permission::checkMember($member, $permission);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param null|Member $member
*
* @return bool
*/
public function canDelete($member = null)
{
$extended = $this->extendedCan(__FUNCTION__, $member);
if ($extended !== null) {
return $extended;
}
return $this->Blog()->canDelete($member);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param null|Member $member
*
* @return bool
*/
public function canEdit($member = null)
{
$extended = $this->extendedCan(__FUNCTION__, $member);
if ($extended !== null) {
return $extended;
}
return $this->Blog()->canEdit($member);
}
/**
* {@inheritdoc}
*/
protected function onBeforeWrite()
{
parent::onBeforeWrite();
if ($this->exists() || empty($this->URLSegment)) {
return $this->generateURLSegment();
}
}
/**
* Generates a unique URLSegment from the title.
*
* @param int $increment
*
* @return string
*/
public function generateURLSegment($increment = 0)
{
$increment = (int) $increment;
$filter = URLSegmentFilter::create();
// Setting this to on. Because of the UI flow, it would be quite a lot of work
// to support turning this off. (ie. the add by title flow would not work).
// If this becomes a problem we can approach it then.
// @see https://github.com/silverstripe/silverstripe-blog/issues/376
$filter->setAllowMultibyte(true);
$this->URLSegment = $filter->filter($this->Title);
if ($increment > 0) {
$this->URLSegment .= '-' . $increment;
}
if ($this->getDuplicatesByField('URLSegment')->count() > 0) {
$this->generateURLSegment($increment + 1);
}
return $this->URLSegment;
}
/**
* Looks for objects o the same type and the same value by the given Field
*
* @param string $field E.g. URLSegment or Title
* @return DataList
*/
protected function getDuplicatesByField($field)
{
$duplicates = DataList::create(self::class)
->filter(
[
$field => $this->$field,
'BlogID' => (int) $this->BlogID
]
);
if ($this->ID) {
$duplicates = $duplicates->exclude('ID', $this->ID);
}
return $duplicates;
}
/**
* This returns the url segment for the listing page.
* eg. 'categories' in /my-blog/categories/category-url
*
* This is not editable at the moment, but a method is being used incase we want
* to make it editable in the future. We can use this method to provide logic
* without replacing multiple areas of the code base. We're also not being opinionated
* about how the segment should be obtained at the moment and allowing for the
* implementation to decide.
*
* @return string
*/
abstract protected function getListUrlSegment();
/**
* Returns an error message for this object when it tries to write a duplicate.
*
* @return string
*/
abstract protected function getDuplicateError();
}