This commit is contained in:
Christopher Pitt 2015-05-10 02:33:12 +12:00
parent e72905c023
commit 787c02a19d
34 changed files with 2249 additions and 1606 deletions

View File

@ -11,20 +11,23 @@ class GridFieldCategorisationConfig extends GridFieldConfig_RecordEditor {
public function __construct($itemsPerPage = 15, $mergeRecords, $parentType, $parentMethod, $childMethod) {
parent::__construct($itemsPerPage);
$this->removeComponentsByType("GridFieldAddNewButton");
$this->removeComponentsByType('GridFieldAddNewButton');
$this->addComponent(
new GridFieldAddByDBField("buttons-before-left")
new GridFieldAddByDBField('buttons-before-left')
);
$this->addComponent(
new GridFieldMergeAction($mergeRecords, $parentType, $parentMethod, $childMethod)
);
/**
* @var GridFieldDataColumns $columns
*/
$columns = $this->getComponentByType('GridFieldDataColumns');
$columns->setFieldFormatting(array(
'BlogPostsCount' => function($value, &$item) {
'BlogPostsCount' => function ($value, CategorisationObject $item) {
return $item->BlogPosts()->Count();
}
));

View File

@ -16,8 +16,7 @@ class GridFieldFormAction extends GridField_FormAction {
/**
* @return array
*/
public function getAttributes()
{
public function getAttributes() {
$attributes = parent::getAttributes();
return array_merge(

View File

@ -66,7 +66,7 @@ class GridFieldMergeAction implements GridField_ColumnProvider, GridField_Action
public function getColumnContent($gridField, $record, $columnName) {
if($columnName === 'MergeAction' && $record->{$this->childMethod}()->Count() > 0) {
$dropdown = new DropdownField('Target', 'Target', $this->records->exclude('ID', $record->ID)->map());
$prefix = strtolower($this->parentMethod . '-' . $this->childMethod);
$action = GridFieldFormAction::create(
@ -129,7 +129,7 @@ class GridFieldMergeAction implements GridField_ColumnProvider, GridField_Action
$posts = $fromParent->{$this->childMethod}();
foreach ($posts as $post) {
foreach($posts as $post) {
$relationship = $post->{$this->parentMethod}();
$relationship->remove($fromParent);

View File

@ -2,59 +2,82 @@
/**
* @deprecated since version 2.0
*
* @property int $ParentID
* @property string $Date
* @property string $PublishDate
* @property string $Tags
*/
class BlogEntry extends BlogPost implements MigratableObject {
/**
* @var string
*/
private static $hide_ancestor = 'BlogEntry';
/**
* @var array
*/
private static $db = array(
"Date" => "SS_Datetime",
"Author" => "Text",
"Tags" => "Text"
'Date' => 'SS_Datetime',
'Author' => 'Text',
'Tags' => 'Text',
);
/**
* Safely split and parse all distinct tags assigned to this BlogEntry
*
* @return array Associative array of lowercase tag to native case tags
* @deprecated since version 2.0
* {@inheritdoc}
*/
public function TagNames() {
$tags = preg_split("/\s*,\s*/", trim($this->Tags));
$results = array();
foreach($tags as $tag) {
if($tag) $results[mb_strtolower($tag)] = $tag;
}
return $results;
}
public function canCreate($member = null) {
// Deprecated
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
// Migrate tags
foreach($this->TagNames() as $tag) {
// Skip if tag already assigned
if($this->Tags()->filter('Title', $tag)->count()) continue;
if($this->Tags()->filter('Title', $tag)->count()) {
continue;
}
// Create tag
$tagObject = new BlogTag();
$tagObject->Title = $tag;
$tagObject->BlogID = $this->ParentID;
$tagObject->write();
$this->Tags()->add($tagObject);
}
// Update fields
$this->PublishDate = $this->Date;
if($this->ClassName === 'BlogEntry') {
$this->ClassName = 'BlogPost';
$this->write();
}
}
/**
* Safely split and parse all distinct tags assigned to this BlogEntry.
*
* @deprecated since version 2.0
*
* @return array
*/
public function TagNames() {
$tags = preg_split('/\s*,\s*/', trim($this->Tags));
$results = array();
foreach($tags as $tag) {
if($tag) $results[mb_strtolower($tag)] = $tag;
}
return $results;
}
/**
* {@inheritdoc}
*/
public function requireDefaultRecords() {
parent::requireDefaultRecords();
@ -69,4 +92,5 @@ class BlogEntry extends BlogPost implements MigratableObject {
* @deprecated since version 2.0
*/
class BlogEntry_Controller extends BlogPost_Controller {
}

View File

@ -4,23 +4,36 @@
* @deprecated since version 2.0
*/
class BlogHolder extends BlogTree implements MigratableObject {
/**
* @var string
*/
private static $hide_ancestor = 'BlogHolder';
/**
* @var array
*/
private static $db = array(
'AllowCustomAuthors' => 'Boolean',
'ShowFullEntry' => 'Boolean',
);
/**
* @var array
*/
private static $has_one = array(
'Owner' => 'Member',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
// Deprecated
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
if($this->ClassName === 'BlogHolder') {
$this->ClassName = 'Blog';
@ -33,5 +46,5 @@ class BlogHolder extends BlogTree implements MigratableObject {
* @deprecated since version 2.0
*/
class BlogHolder_Controller extends BlogTree_Controller {
}
}

View File

@ -4,19 +4,29 @@
* @deprecated since version 2.0
*/
class BlogTree extends Page implements MigratableObject {
/**
* @var string
*/
private static $hide_ancestor = 'BlogTree';
/**
* @var array
*/
private static $db = array(
'Name' => 'Varchar(255)',
'LandingPageFreshness' => 'Varchar',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
// Deprecated
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
if($this->ClassName === 'BlogTree') {
$this->ClassName = 'Page';
@ -29,4 +39,5 @@ class BlogTree extends Page implements MigratableObject {
* @deprecated since version 2.0
*/
class BlogTree_Controller extends Page_Controller {
}
}

View File

@ -1,34 +1,24 @@
<?php
/**
* Description of BlogMigrationTask
*
* @author dmooyman
*/
class BlogMigrationTask extends MigrationTask {
/**
* Should this task be invoked automatically via dev/build?
*
* @config
* @var boolean
*
* @var bool
*/
private static $run_during_dev_build = true;
protected function message($text) {
if(Controller::curr() instanceof DatabaseAdmin) {
DB::alteration_message($text, 'obsolete');
} else {
Debug::message($text);
}
}
/**
* {@inheritdoc}
*/
public function up() {
$classes = ClassInfo::implementorsOf('MigratableObject');
$this->message('Migrating legacy blog records');
foreach($classes as $class) {
// migrate objects in each stage
if(is_subclass_of($class, 'SiteTree')) {
foreach(array('Stage', 'Live') as $stage) {
$oldMode = Versioned::get_reading_mode();
@ -37,40 +27,66 @@ class BlogMigrationTask extends MigrationTask {
Versioned::set_reading_mode($oldMode);
}
} else {
// Migrate object
$this->upClass($class);
}
}
}
public function down() {
$this->message('BlogMigrationTask::down() not implemented');
/**
* @param string $text
*/
protected function message($text) {
if(Controller::curr() instanceof DatabaseAdmin) {
DB::alteration_message($text, 'obsolete');
} else {
Debug::message($text);
}
}
/**
* Migrate records of a single class
*
* @param type $class
* @param type $stage
* @param string $class
* @param null|string $stage
*/
protected function upClass($class, $stage = null) {
if(!class_exists($class)) return;
if(!class_exists($class)) {
return;
}
// Migrate all records
$items = $class::get();
if($count = $items->count()) {
$stageMessage = " in stage {$stage}";
$this->message("Migrating {$count} legacy {$class} records{$stageMessage}.");
$this->message(
sprintf(
'Migrating %s legacy %s records in stage %s.',
$count,
$class,
$stage
)
);
foreach($items as $item) {
// Cancel if onBeforeUp returns false
$cancel = $item->extend('onBeforeUp');
if($cancel && min($cancel) === false) continue;
// Up
if($cancel && min($cancel) === false) {
continue;
}
/**
* @var MigratableObject $item
*/
$item->up();
// Post extensions
$item->extend('onAfterUp');
}
}
}
/**
* {@inheritdoc}
*/
public function down() {
$this->message('BlogMigrationTask::down() not implemented');
}
}

View File

@ -1,9 +1,8 @@
<?php
interface MigratableObject {
/**
* Migrate the object up to the current version
* Migrate the object up to the current version.
*/
public function up();
}

View File

@ -1,27 +1,49 @@
<?php
if(!class_exists('Widget')) return;
if(!class_exists('Widget')) {
return;
}
/**
* @deprecated since version 2.0
*
* @property string $DisplayMode
* @property string $ArchiveType
*/
class ArchiveWidget extends BlogArchiveWidget implements MigratableObject {
/**
* @var array
*/
private static $db = array(
'DisplayMode' => 'Varchar'
'DisplayMode' => 'Varchar',
);
private static $only_available_in = array('none');
/**
* @var array
*/
private static $only_available_in = array(
'none',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
// Deprecated
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
if($this->DisplayMode) {
$this->ArchiveType = ($this->DisplayMode === 'year') ? 'Yearly' : 'Monthly';
$this->ArchiveType = 'Monthly';
if($this->DisplayMode === 'year') {
$this->ArchiveType = 'Yearly';
}
}
$this->ClassName = 'BlogArchiveWidget';
$this->write();
}

View File

@ -1,29 +1,43 @@
<?php
if(! class_exists('Widget')) return;
if(!class_exists('Widget')) {
return;
}
/**
* A list of tags associated with blog posts
* A list of tags associated with blog posts.
*
* @package blog
*/
class TagCloudWidget extends BlogTagsWidget implements MigratableObject {
/**
* @var array
*/
private static $db = array(
"Title" => "Varchar",
"Limit" => "Int",
"Sortby" => "Varchar"
'Title' => 'Varchar',
'Limit' => 'Int',
'Sortby' => 'Varchar',
);
private static $only_available_in = array('none');
/**
* @var array
*/
private static $only_available_in = array(
'none',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
// Deprecated
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
$this->ClassName = 'BlogTagsWidget';
$this->write();
}
}
}

View File

@ -1,23 +1,23 @@
<?php
/**
* Adds Blog specific behaviour to Comment
* Extends {@see Comment}
* Adds Blog specific behaviour to Comment.
*/
class BlogCommentExtension extends DataExtension {
/**
* Extra CSS classes for styling different comment types.
*
* @return string
*/
public function getExtraClass() {
$blogPost = $this->owner->getParent();
// Make sure we're dealing with a BlogPost.
if ( ($blogPost instanceof BlogPost)
&& $blogPost->isAuthor($this->owner->Author())
) {
return 'author-comment';
if($blogPost instanceof BlogPost) {
if($blogPost->isAuthor($this->owner->Author())) {
return 'author-comment';
}
}
return '';
}
}

View File

@ -1,89 +1,106 @@
<?php
/**
* This class is responsible for filtering the SiteTree when necessary and also
* overlaps into filtering only published posts.
* This class is responsible for filtering the SiteTree when necessary and also overlaps into
* filtering only published posts.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
*
**/
*/
class BlogFilter extends Lumberjack {
/**
* Augments (@link Hierarchy::stageChildren()}
*
* @param $staged DataList
* @param $showAll boolean
**/
* {@inheritdoc}
*/
public function stageChildren($showAll = false) {
$staged = parent::stageChildren($showAll);
if(!$this->shouldFilter()
&& in_array(get_class($this->owner), ClassInfo::subClassesFor("Blog"))
&& !Permission::check("VIEW_DRAFT_CONTENT")
) {
// Get the current stage.
if(!$this->shouldFilter() && $this->subclassForBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
$stage = Versioned::current_stage();
if($stage == "Stage") $stage = "";
elseif($stage) $stage = "_{$stage}";
// Filter published posts
if($stage == 'Stage') {
$stage = '';
} elseif($stage) {
$stage = '_' . $stage;
}
$dataQuery = $staged->dataQuery()
->innerJoin("BlogPost", '"BlogPost' . $stage . '"."ID" = "SiteTree' . $stage . '"."ID"')
->where('"PublishDate" < \'' . Convert::raw2sql(SS_Datetime::now()) . '\'');
->innerJoin('BlogPost', sprintf('BlogPost%s.ID = SiteTree%s.ID', $stage, $stage))
->where(sprintf('PublishDate < \'%s\'', Convert::raw2sql(SS_Datetime::now())));
$staged = $staged->setDataQuery($dataQuery);
}
return $staged;
}
/**
* @return bool
*/
protected function subclassForBlog() {
return in_array(get_class($this->owner), ClassInfo::subClassesFor('Blog'));
}
/**
* {@inheritdoc}
*/
public function liveChildren($showAll = false, $onlyDeletedFromStage = false) {
$staged = parent::liveChildren($showAll, $onlyDeletedFromStage);
if(!$this->shouldFilter()
&& $this->owner instanceof Blog
&& !Permission::check("VIEW_DRAFT_CONTENT")
) {
// Filter publish posts
if(!$this->shouldFilter() && $this->isBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
$dataQuery = $staged->dataQuery()
->innerJoin("BlogPost", '"BlogPost_Live"."ID" = "SiteTree_Live"."ID"')
->where('"BlogPost"."PublishDate" < \'' . Convert::raw2sql(SS_Datetime::now()->getValue()) . '\'');
->innerJoin('BlogPost', 'BlogPost_Live.ID = SiteTree_Live.ID')
->where(sprintf('PublishDate < \'%s\'', Convert::raw2sql(SS_Datetime::now())));
$staged = $staged->setDataQuery($dataQuery);
}
return $staged;
}
/**
* @return bool
*/
protected function isBlog() {
return $this->owner instanceof Blog;
}
/**
* {@inheritdoc}
*/
public function updateCMSFields(FieldList $fields) {
$excluded = $this->owner->getExcludedSiteTreeClassNames();
if(!empty($excluded)) {
$pages = SiteTree::get()->filter(array(
'ParentID' => $this->owner->ID,
'ClassName' => $excluded
))->sort('"SiteTree"."Created" DESC');
))->sort('SiteTree.Created DESC');
$gridField = new BlogFilter_GridField(
"ChildPages",
'ChildPages',
$this->getLumberjackTitle(),
$pages,
$this->getLumberjackGridFieldConfig()
);
$tab = new Tab('ChildPages', $this->getLumberjackTitle(), $gridField);
$fields->insertBefore($tab, 'Main');
}
}
}
/**
* Enables children of non-editable pages to be edited
* Enables children of non-editable pages to be edited.
*/
class BlogFilter_GridField extends GridField {
public function transform(FormTransformation $trans) {
// Don't allow parent object transformations to propegate automatically to child records
/**
* @param FormTransformation $transformation
*
* @return $this
*/
public function transform(FormTransformation $transformation) {
return $this;
}
}

View File

@ -5,25 +5,34 @@
*
* @package silverstripe
* @subpackage blog
*
**/
*/
class BlogMemberExtension extends DataExtension {
/**
* @var array
*/
private static $db = array(
'URLSegment' => 'Varchar',
'BlogProfileSummary' => 'Text'
'BlogProfileSummary' => 'Text',
);
/**
* @var array
*/
private static $has_one = array(
'BlogProfileImage' => 'Image'
'BlogProfileImage' => 'Image',
);
/**
* @var array
*/
private static $belongs_many_many = array(
'AuthoredPosts' => 'BlogPost'
'AuthoredPosts' => 'BlogPost',
);
/**
* {@inheritdoc}
*/
public function onBeforeWrite() {
// Generate a unique URL segment for the Member.
$count = 1;
$this->owner->URLSegment = $this->generateURLSegment();
@ -34,45 +43,45 @@ class BlogMemberExtension extends DataExtension {
}
}
public function updateCMSFields(FieldList $fields) {
$fields->removeByName('URLSegment');
return $fields;
}
/**
* Generate a unique URL segment based on the Member's name.
*
* @return string Generated URL segment.
*
* @return string
*/
public function generateURLSegment() {
$filter = URLSegmentFilter::create();
$name = $this->owner->FirstName . ' ' . $this->owner->Surname;
$urlSegment = $filter->filter($name);
// Fallback to generic profile name if path is empty (= no valid, convertable characters)
if(!$urlSegment || $urlSegment == '-' || $urlSegment == '-1') {
$urlSegment = "profile-".$this->owner->ID;
$urlSegment = 'profile-' . $this->owner->ID;
}
return $urlSegment;
}
/**
* Returns TRUE if this object has a URL segment value that does not conflict with any other objects.
*
* Returns TRUE if this object has a URL segment value that does not conflict with any other
* objects.
*
* @return bool
*/
public function validURLSegment() {
public function validURLSegment() {
$conflict = Member::get()->filter('URLSegment', $this->owner->URLSegment);
// If the Member we're checking against is saved, exclude them from the check.
// i.e. don't conflict against yourself.
if ($this->owner->ID) {
if($this->owner->ID) {
$conflict = $conflict->exclude('ID', $this->owner->ID);
}
return $conflict->count() == 0;
}
/**
* {@inheritdoc}
*/
public function updateCMSFields(FieldList $fields) {
$fields->removeByName('URLSegment');
return $fields;
}
}

View File

@ -1,36 +1,38 @@
<?php
/**
* This is responsible for filtering only published posts to users who do not have
* permission to view non-published posts.
* This is responsible for filtering only published posts to users who do not have permission to
* view non-published posts.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
*/
class BlogPostFilter extends DataExtension {
/**
* Augment queries so that we don't fetch unpublished articles.
**/
*
* @param SQLQuery $query
*/
public function augmentSQL(SQLQuery &$query) {
$stage = Versioned::current_stage();
if($stage == 'Live' || !Permission::check("VIEW_DRAFT_CONTENT")) {
$query->addWhere("PublishDate < '" . Convert::raw2sql(SS_Datetime::now()) . "'");
if($stage == 'Live' || !Permission::check('VIEW_DRAFT_CONTENT')) {
$query->addWhere(sprintf('PublishDate < \'%s\'', Convert::raw2sql(SS_Datetime::now())));
}
}
/**
* This is a fix so that when we try to fetch subclasses of BlogPost,
* lazy loading includes the BlogPost table in its query. Leaving this table out
* means the default sort order column PublishDate causes an error.
* This is a fix so that when we try to fetch subclasses of BlogPost, lazy loading includes the
* BlogPost table in its query. Leaving this table out means the default sort order column
* PublishDate causes an error.
*
* @see https://github.com/silverstripe/silverstripe-framework/issues/1682
**/
*
* @param SQLQuery $query
* @param mixed $dataQuery
* @param mixed $parent
*/
public function augmentLoadLazyFields(SQLQuery &$query, &$dataQuery, $parent) {
// Ensures that we're joining the BlogPost table which holds required db fields.
$dataQuery->innerJoin("BlogPost", "`SiteTree`.`ID` = `BlogPost`.`ID`");
$dataQuery->innerJoin('BlogPost', 'SiteTree.ID = BlogPost.ID');
}
}
}

View File

@ -1,30 +1,29 @@
<?php
/**
* Customise blog post to support comment notifications
* Extends {@see BlogPost} with extensions to {@see CommentNotifiable}
* Customise blog post to support comment notifications.
*
* Extends {@see BlogPost} with extensions to {@see CommentNotifiable}.
*/
class BlogPostNotifications extends DataExtension {
/**
* Notify all authors of notifications
* Notify all authors of notifications.
*
* @param type $list
* @param type $comment
* @param SS_List $list
* @param mixed $comment
*/
public function updateNotificationRecipients(&$list, &$comment) {
// Notify all authors
$list = $this->owner->Authors();
}
/**
* Update comment to include the page title
* Update comment to include the page title.
*
* @param string $subject
* @param Comment $comment
* @param Member|string $recipient
*/
public function updateNotificationSubject(&$subject, &$comment, &$recipient) {
$subject = "A new comment has been posted on " . $this->owner->Title;
$subject = sprintf('A new comment has been posted on ', $this->owner->Title);
}
}

View File

@ -1,48 +1,61 @@
<?php
/**
* Adds URLSegment functionality to Tags & Categories
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
class URLSegmentExtension extends DataExtension {
private static $db = array(
"URLSegment" => "Varchar(255)"
);
public function onBeforeWrite() {
$this->owner->generateURLSegment();
}
/**
* Generates a unique URLSegment from the title.
*
* @param $increment
*
* @return string URLSegment
**/
public function generateURLSegment($increment = null) {
$filter = new URLSegmentFilter();
$this->owner->URLSegment = $filter->filter($this->owner->Title);
if(is_int($increment)) $this->owner->URLSegment .= '-' . $increment;
// Check to see if the URLSegment already exists
$duplicate = DataList::create($this->owner->ClassName)->filter(array(
"URLSegment" => $this->owner->URLSegment,
"BlogID" => $this->owner->BlogID
));
if($this->owner->ID) $duplicate = $duplicate->exclude("ID", $this->owner->ID);
if($duplicate->count() > 0) {
$increment = is_int($increment) ? $increment + 1 : 0;
$this->owner->generateURLSegment((int) $increment);
}
return $this->owner->URLSegment;
}
}
<?php
/**
* Adds URLSegment functionality to Tags & Categories.
*
* @package silverstripe
* @subpackage blog
*/
class URLSegmentExtension extends DataExtension {
/**
* @var array
*/
private static $db = array(
'URLSegment' => 'Varchar(255)',
);
/**
* {@inheritdoc}
*/
public function onBeforeWrite() {
$this->owner->generateURLSegment();
}
/**
* Generates a unique URLSegment from the title.
*
* @param int $increment
*
* @return string
*/
public function generateURLSegment($increment = null) {
$filter = new URLSegmentFilter();
$this->owner->URLSegment = $filter->filter($this->owner->Title);
if(is_int($increment)) {
$this->owner->URLSegment .= '-' . $increment;
}
$duplicate = DataList::create($this->owner->ClassName)->filter(array(
'URLSegment' => $this->owner->URLSegment,
'BlogID' => $this->owner->BlogID,
));
if($this->owner->ID) {
$duplicate = $duplicate->exclude('ID', $this->owner->ID);
}
if($duplicate->count() > 0) {
if(is_int($increment)) {
$increment += 1;
} else {
$increment = 0;
}
$this->owner->generateURLSegment((int) $increment);
}
return $this->owner->URLSegment;
}
}

View File

@ -1,13 +1,16 @@
<?php
class BlogAdminSidebar extends FieldGroup {
/**
* @return bool
*/
public function isOpen() {
$sidebar = Cookie::get('blog-admin-sidebar');
if($sidebar == 1 || is_null($sidebar)) {
return true;
}
return false;
}
}
}

View File

@ -5,168 +5,181 @@
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
*/
class GridFieldAddByDBField implements GridField_ActionProvider, GridField_HTMLProvider {
/**
* HTML Fragment to render the field.
*
* @var string
**/
*/
protected $targetFragment;
/**
* Default field to create the dataobject by should be Title.
* Default field to create the DataObject by should be Title.
*
* @var string
**/
protected $dataObjectField = "Title";
*/
protected $dataObjectField = 'Title';
/**
* Creates a text field and add button which allows the user to directly create a new
* DataObject by just entering the title.
*
* @param $targetFragment string
**/
public function __construct($targetFragment = 'before', $dataObjectField = "Title") {
* @param string $targetFragment
* @param string $dataObjectField
*/
public function __construct($targetFragment = 'before', $dataObjectField = 'Title') {
$this->targetFragment = $targetFragment;
$this->dataObjectField = (string) $dataObjectField;
}
/**
* Provide actions to this component.
*
* @param $gridField GridField
* @param GridField $gridField
*
* @return array
**/
*/
public function getActions($gridField) {
return array("add");
return array(
'add',
);
}
/**
* Handles the add action for the given DataObject
* Handles the add action for the given DataObject.
*
* @param $gridFIeld GridFIeld
* @param $gridField GridField
* @param $actionName string
* @param $arguments mixed
* @param $data array
**/
*
* @return null|SS_HTTPResponse
*
* @throws UnexpectedValueException
*/
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName == "add") {
if($actionName == 'add') {
$dbField = $this->getDataObjectField();
$objClass = $gridField->getModelClass();
$obj = new $objClass();
if($obj->hasField($dbField)) {
$obj->setCastedField($dbField, $data['gridfieldaddbydbfield'][$obj->ClassName][$dbField]);
if($obj->canCreate()) {
$id = $gridField->getList()->add($obj);
if(!$id) {
$gridField->setError(_t(
"GridFieldAddByDBField.AddFail",
"Unable to save {class} to the database.",
"Unable to add the DataObject.",
array(
"class" => get_class($obj)
)),
"error"
$gridField->setError(
_t(
'GridFieldAddByDBField.AddFail',
'Unable to save {class} to the database.',
'Unable to add the DataObject.',
array(
'class' => get_class($obj),
)
),
'error'
);
}
} else {
return Security::permissionFailure(
Controller::curr(),
_t(
"GridFieldAddByDBField.PermissionFail",
"You don't have permission to create a {class}.",
"Unable to add the DataObject.",
'GridFieldAddByDBField.PermissionFail',
'You don\'t have permission to create a {class}.',
'Unable to add the DataObject.',
array(
"class" => get_class($obj)
'class' => get_class($obj)
)
)
);
}
} else {
throw new UnexpectedValueException("Invalid field (" . $dbField . ") on " . $obj->ClassName . ".");
throw new UnexpectedValueException(
sprintf(
'Invalid field (%s) on %s.',
$dbField,
$obj->ClassName
)
);
}
}
return null;
}
/**
* Renders the TextField and add button to the GridField.
*
* @param $girdField GridField
*
* @return string HTML
**/
public function getHTMLFragments($gridField) {
$dataClass = $gridField->getList()->dataClass();
$obj = singleton($dataClass);
if(!$obj->canCreate()) return "";
$dbField = $this->getDataObjectField();
$textField = TextField::create(
"gridfieldaddbydbfield[" . $obj->ClassName . "][" . Convert::raw2htmlatt($dbField) . "]"
)->setAttribute("placeholder", $obj->fieldLabel($dbField))
->addExtraClass("no-change-track");
$addAction = new GridField_FormAction($gridField,
'add',
_t('GridFieldAddByDBField.Add',
"Add {name}", "Add button text",
array("name" => $obj->i18n_singular_name())
),
'add',
'add'
);
$addAction->setAttribute('data-icon', 'add');
// Start thinking about rending this back to the GF
$forTemplate = new ArrayData(array());
$forTemplate->Fields = new ArrayList();
$forTemplate->Fields->push($textField);
$forTemplate->Fields->push($addAction);
return array(
$this->targetFragment => $forTemplate->renderWith("GridFieldAddByDBField")
);
}
/**
* Returns the database field for which we'll add the new data object.
*
* @return string
**/
*/
public function getDataObjectField() {
return $this->dataObjectField;
}
/**
* Set the database field.
*
* @param $field string
**/
*/
public function setDataObjectField($field) {
$this->dataObjectField = (string) $field;
}
}
/**
* Renders the TextField and add button to the GridField.
*
* @param $gridField GridField
*
* @return string
*/
public function getHTMLFragments($gridField) {
$dataClass = $gridField->getList()->dataClass();
$obj = singleton($dataClass);
if(!$obj->canCreate()) {
return "";
}
$dbField = $this->getDataObjectField();
$textField = TextField::create(
sprintf(
"gridfieldaddbydbfield[%s][%s]",
$obj->ClassName,
Convert::raw2htmlatt($dbField)
)
)
->setAttribute('placeholder', $obj->fieldLabel($dbField))
->addExtraClass('no-change-track');
$addAction = new GridField_FormAction(
$gridField,
'add',
_t('GridFieldAddByDBField.Add',
'Add {name}', "Add button text",
array(
'name' => $obj->i18n_singular_name(),
)
),
'add',
'add'
);
$addAction->setAttribute('data-icon', 'add');
$forTemplate = new ArrayData(array());
$forTemplate->Fields = new ArrayList();
$forTemplate->Fields->push($textField);
$forTemplate->Fields->push($addAction);
return array(
$this->targetFragment => $forTemplate->renderWith('GridFieldAddByDBField')
);
}
}

View File

@ -1,74 +1,85 @@
<?php
/**
* Provides a component to the {@link GridField} which tells the user whether or not a
* blog post has been published and when.
* Provides a component to the {@link GridField} which tells the user whether or not a blog post
* has been published and when.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
*/
class GridFieldBlogPostState extends GridFieldSiteTreeState {
/**
* {@inheritdoc}
*/
public function getColumnContent($gridField, $record, $columnName) {
if($columnName == "State") {
if($columnName == 'State') {
Requirements::css(BLOGGER_DIR . '/css/cms.css');
if($record->hasMethod("isPublished")) {
$modifiedLabel = "";
if($record->hasMethod('isPublished')) {
$modifiedLabel = '';
if($record->isModifiedOnStage) {
$modifiedLabel = "<span class='modified'>" . _t("GridFieldBlogPostState.Modified") . "</span>";
$modifiedLabel = '<span class="modified">' . _t('GridFieldBlogPostState.Modified') . '</span>';
}
$published = $record->isPublished();
if(!$published) {
if(!$record->isPublished()) {
return _t(
"GridFieldBlogPostState.Draft",
'GridFieldBlogPostState.Draft',
'<i class="btn-icon gridfield-icon btn-icon-pencil"></i> Saved as Draft on {date}',
"State for when a post is saved.",
'State for when a post is saved.',
array(
"date" => $record->dbObject("LastEdited")->Nice()
'date' => $record->dbObject('LastEdited')->Nice(),
)
);
} else if (strtotime($record->PublishDate) > time()) {
}
if(strtotime($record->PublishDate) > time()) {
return _t(
"GridFieldBlogPostState.Timer",
'GridFieldBlogPostState.Timer',
'<i class="gridfield-icon blog-icon-timer"></i> Publish at {date}',
"State for when a post is published.",
'State for when a post is published.',
array(
"date" => $record->dbObject("PublishDate")->Nice()
)
) . $modifiedLabel;
} else {
return _t(
"GridFieldBlogPostState.Published",
'<i class="btn-icon gridfield-icon btn-icon-accept"></i> Published on {date}',
"State for when a post is published.",
array(
"date" => $record->dbObject("PublishDate")->Nice()
'date' => $record->dbObject('PublishDate')->Nice(),
)
) . $modifiedLabel;
}
return _t(
'GridFieldBlogPostState.Published',
'<i class="btn-icon gridfield-icon btn-icon-accept"></i> Published on {date}',
'State for when a post is published.',
array(
'date' => $record->dbObject('PublishDate')->Nice(),
)
) . $modifiedLabel;
}
}
return '';
}
/**
* {@inheritdoc}
*/
public function getColumnAttributes($gridField, $record, $columnName) {
if($columnName == "State") {
if($record->hasMethod("isPublished")) {
if($columnName == 'State') {
if($record->hasMethod('isPublished')) {
$published = $record->isPublished();
if(!$published) {
$class = "gridfield-icon draft";
} else if (strtotime($record->PublishDate) > time()) {
$class = "gridfield-icon timer";
$class = 'gridfield-icon draft';
} else if(strtotime($record->PublishDate) > time()) {
$class = 'gridfield-icon timer';
} else {
$class = "gridfield-icon published";
$class = 'gridfield-icon published';
}
return array("class" => $class);
return array(
'class' => $class,
);
}
}
return array();
}
}
}

View File

@ -5,15 +5,15 @@
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <mstrong@silverstripe.org>
**/
*/
class GridFieldConfig_BlogPost extends GridFieldConfig_Lumberjack {
/**
* @param null|int $itemsPerPage
*/
public function __construct($itemsPerPage = null) {
parent::__construct($itemsPerPage);
$this->removeComponentsByType('GridFieldSiteTreeState');
$this->addComponent(new GridFieldBlogPostState());
}
}
}

View File

@ -11,73 +11,97 @@
* @method ManyManyList Editors() List of editors
* @method ManyManyList Writers() List of writers
* @method ManyManyList Contributors() List of contributors
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
*/
class Blog extends Page implements PermissionProvider {
/**
* Permission for user management
* Permission for user management.
*
* @var string
*/
const MANAGE_USERS = 'BLOG_MANAGE_USERS';
/**
* If true, users assigned as editor, writer, or contributor will be automatically
* granted CMS_ACCESS_CMSMain permission. If false, only users with this permission
* already may be assigned.
* If true, users assigned as editor, writer, or contributor will be automatically granted
* CMS_ACCESS_CMSMain permission. If false, only users with this permission already may be
* assigned.
*
* @config
*
* @var boolean
* @config
*/
private static $grant_user_access = true;
/**
* Permission to either require, or grant to users assigned to work on this blog
* Permission to either require, or grant to users assigned to work on this blog.
*
* @config
*
* @var string
* @config
*/
private static $grant_user_permission = 'CMS_ACCESS_CMSMain';
/**
* Group code to assign newly granted users toh
* Group code to assign newly granted users to.
*
* @config
*
* @var string
* @config
*/
private static $grant_user_group = 'blog-users';
/**
* @var array
*/
private static $db = array(
"PostsPerPage" => "Int",
'PostsPerPage' => 'Int',
);
/**
* @var array
*/
private static $has_many = array(
"Tags" => "BlogTag",
"Categories" => "BlogCategory",
'Tags' => 'BlogTag',
'Categories' => 'BlogCategory',
);
/**
* @var array
*/
private static $many_many = array(
'Editors' => 'Member',
'Writers' => 'Member',
'Contributors' => 'Member',
);
/**
* @var array
*/
private static $allowed_children = array(
"BlogPost",
'BlogPost',
);
/**
* @var array
*/
private static $extensions = array(
"BlogFilter",
'BlogFilter',
);
/**
* @var array
*/
private static $defaults = array(
"ProvideComments" => false,
'ProvideComments' => false,
);
/**
* @var string
*/
private static $description = 'Adds a blog to your website.';
/**
* {@inheritdoc}
*/
public function getCMSFields() {
Requirements::css(BLOGGER_DIR . '/css/cms.css');
Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
@ -90,183 +114,163 @@ class Blog extends Page implements PermissionProvider {
}
$categories = GridField::create(
"Categories",
_t("Blog.Categories", "Categories"),
'Categories',
_t('Blog.Categories', 'Categories'),
$self->Categories(),
GridFieldCategorisationConfig::create(15, $self->Categories(), 'BlogCategory', 'Categories', 'BlogPosts')
);
$tags = GridField::create(
"Tags",
_t("Blog.Tags", "Tags"),
'Tags',
_t('Blog.Tags', 'Tags'),
$self->Tags(),
GridFieldCategorisationConfig::create(15, $self->Tags(), 'BlogTag', 'Tags', 'BlogPosts')
);
$fields->addFieldsToTab("Root.Categorisation", array(
$fields->addFieldsToTab('Root.Categorisation', array(
$categories,
$tags
));
$fields->findOrMakeTab("Root.Categorisation")->addExtraClass('blog-cms-categorisation');
$fields->findOrMakeTab('Root.Categorisation')->addExtraClass('blog-cms-categorisation');
});
$fields = parent::getCMSFields();
return $fields;
return parent::getCMSFields();
}
/**
* Check if this member is an editor of the blog
*
* @param Member $member
*
* @return boolean
* {@inheritdoc}
*/
public function isEditor($member) {
$isEditor = $this->isMemberOf($member, $this->Editors());
$this->extend('updateIsEditor', $isEditor, $member);
return $isEditor;
}
/**
* Check if this member is a writer of the blog
*
* @param Member $member
*
* @return boolean
*/
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 boolean
*/
public function isContributor($member) {
$isContributor = $this->isMemberOf($member, $this->Contributors());
$this->extend('updateIsContributor', $isContributor, $member);
return $isContributor;
}
/**
* Determine the role of the given member
* Call be called via template to determine the current user
*
* E.g. `Hello $RoleOf($CurrentMember.ID)`
*
* @param Member|integer $member
*
* @return string|null Author, Editor, Writer, Contributor, or null if no role
*/
public function RoleOf($member) {
if(is_numeric($member)) $member = DataObject::get_by_id('Member', $member);
if(!$member) return null;
// Check each role
if($this->isEditor($member)) return _t('Blog.EDITOR', 'Editor');
if($this->isWriter($member)) return _t('Blog.WRITER', 'Writer');
if($this->isContributor($member)) return _t('Blog.CONTRIBUTOR', 'Contributor');
}
/**
* Determine if the given member belongs to the given subrelation
*
* @param Member $member
* @param DataList $list Relation to check
*
* @return boolean
*/
protected function isMemberOf($member, $list) {
if(!$member || !$member->exists()) return false;
if($list instanceof UnsavedRelationList) {
return in_array($member->ID, $list->getIDList());
}
return $list->byID($member->ID) !== null;
}
public function canEdit($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
$member = $this->getMember($member);
// Allow editors to edit this page
if($this->isEditor($member)) return true;
if($this->isEditor($member)) {
return true;
}
return parent::canEdit($member);
}
/**
* Determine if this user can edit the editors list
* @param null|int|Member $member
*
* @param Member $member
*
* @return boolean
* @return null|Member
*/
public function canEditEditors($member = null) {
$member = $member ?: Member::currentUser();
protected function getMember($member = null) {
if(!$member) {
$member = Member::currentUser();
}
$extended = $this->extendedCan('canEditEditors', $member);
if($extended !== null) return $extended;
if(is_int($member)) {
$member = Member::get()->byID($member);
}
// Check permission
return Permission::checkMember($member, self::MANAGE_USERS);
return $member;
}
/**
* Determine if this user can edit writers list
* Check if this member is an editor of the blog.
*
* @param Member $member
*
* @return boolean
* @return bool
*/
public function canEditWriters($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
public function isEditor($member) {
$isEditor = $this->isMemberOf($member, $this->Editors());
$this->extend('updateIsEditor', $isEditor, $member);
$extended = $this->extendedCan('canEditWriters', $member);
if($extended !== null) return $extended;
// Editors can edit writers
if($this->isEditor($member)) return true;
// Check permission
return Permission::checkMember($member, self::MANAGE_USERS);
return $isEditor;
}
/**
* Determines if this user can edit the contributors list
* Determine if the given member belongs to the given relation.
*
* @param type $member
* @param Member $member
* @param DataList $relation
*
* @return boolean
* @return bool
*/
public function canEditContributors($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
protected function isMemberOf($member, $relation) {
if(!$member || !$member->exists()) {
return false;
}
$extended = $this->extendedCan('canEditContributors', $member);
if($extended !== null) return $extended;
if($relation instanceof UnsavedRelationList) {
return in_array($member->ID, $relation->getIDList());
}
// Editors can edit writers
if($this->isEditor($member)) return true;
// Check permission
return Permission::checkMember($member, self::MANAGE_USERS);
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 = DataObject::get_by_id('Member', $member);
}
if(!$member) {
return null;
}
if($this->isEditor($member)) {
return _t('Blog.EDITOR', 'Editor');
}
if($this->isWriter($member)) {
return _t('Blog.WRITER', 'Writer');
}
if($this->isContributor($member)) {
return _t('Blog.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 = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
$member = $this->getMember($member);
// Editors, Writers and Contributors can add children
if($this->isEditor($member) || $this->isWriter($member) || $this->isContributor($member)) {
return true;
}
@ -274,17 +278,18 @@ class Blog extends Page implements PermissionProvider {
return parent::canAddChildren($member);
}
/**
* {@inheritdoc}
*/
public function getSettingsFields() {
$fields = parent::getSettingsFields();
$fields->addFieldToTab("Root.Settings",
NumericField::create("PostsPerPage", _t("Blog.PostsPerPage", "Posts Per Page"))
$fields->addFieldToTab('Root.Settings',
NumericField::create('PostsPerPage', _t('Blog.PostsPerPage', 'Posts Per Page'))
);
// Roles and Permissions
$members = $this->getCandidateUsers()->map()->toArray();
// Editors
$editorField = ListboxField::create('Editors', 'Editors', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
@ -304,7 +309,6 @@ class Blog extends Page implements PermissionProvider {
$editorField = $editorField->performDisabledTransformation();
}
// Writers
$writerField = ListboxField::create('Writers', 'Writers', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
@ -321,7 +325,6 @@ class Blog extends Page implements PermissionProvider {
$writerField = $writerField->performDisabledTransformation();
}
// Contributors
$contributorField = ListboxField::create('Contributors', 'Contributors', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
@ -346,62 +349,145 @@ class Blog extends Page implements PermissionProvider {
return $fields;
}
/**
* Return blog posts
* Gets the list of user candidates to be assigned to assist with this blog.
*
* @return DataList of BlogPost objects
**/
public function getBlogPosts() {
$blogPosts = BlogPost::get()->filter("ParentID", $this->ID);
//Allow decorators to manipulate list
$this->extend('updateGetBlogPosts', $blogPosts);
return $blogPosts;
* @return SS_List
*/
protected function getCandidateUsers() {
if($this->config()->grant_user_access) {
return Member::get();
} else {
return Permission::get_members_by_permission(
$this->config()->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);
}
/**
* Returns blogs posts for a given date period.
* Determine if this user can edit writers list.
*
* @param $year int
* @param $month int
* @param $day int
* @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 = '_' . Convert::raw2sql($stage);
$stage = $query->getQueryParam('Versioned.stage');
if ($stage) {
$stage = '_' . $stage;
}
$query->innerJoin('BlogPost', sprintf('SiteTree%s.ID = BlogPost%s.ID', $stage, $stage));
$query->where(sprintf('YEAR(PublishDate) = \'%s\'', Convert::raw2sql($year)));
$query->innerJoin("BlogPost", "`SiteTree" . $stage . "`.`ID` = `BlogPost" . $stage . "`.`ID`");
$query->where("YEAR(PublishDate) = '" . Convert::raw2sql($year) . "'");
if($month) {
$query->where("MONTH(PublishDate) = '" . Convert::raw2sql($month) . "'");
$query->where(sprintf('MONTH(PublishDate) = \'%s\'', Convert::raw2sql($month)));
if($day) {
$query->where("DAY(PublishDate) = '" . Convert::raw2sql($day) . "'");
$query->where(sprintf('DAY(PublishDate) = \'%s\'', 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 urlSegment
* @param string $urlSegment
*
* @return String
* @return string
*/
public function ProfileLink($urlSegment) {
return Controller::join_links($this->Link(), 'profile', $urlSegment);
}
/**
* This sets the title for our gridfield
* This sets the title for our gridfield.
*
* @return string
*/
@ -409,7 +495,6 @@ class Blog extends Page implements PermissionProvider {
return _t('Blog.LumberjackTitle', 'Blog Posts');
}
/**
* This overwrites lumberjacks default gridfield config.
*
@ -419,6 +504,9 @@ class Blog extends Page implements PermissionProvider {
return GridFieldConfig_BlogPost::create();
}
/**
* {@inheritdoc}
*/
public function providePermissions() {
return array(
Blog::MANAGE_USERS => array(
@ -437,112 +525,109 @@ class Blog extends Page implements PermissionProvider {
}
/**
* Gets the list of user candidates to be assigned to assist with this blog
*
* @return SS_List
* {@inheritdoc}
*/
protected function getCandidateUsers() {
if($this->config()->grant_user_access) {
// If we are allowed to grant CMS access, all users are candidates
return Member::get();
} else {
// If access cannot be granted, limit users to those who can access the CMS
// This is useful for more secure sites
$permission = $this->config()->grant_user_permission;
return Permission::get_members_by_permission($permission);
}
}
/**
* Gets or creates the group used to assign CMS access
*
* @return Group
*/
protected function getUserGroup() {
$code = $this->config()->grant_user_group;
$group = Group::get()->filter('Code', $code)->first();
if($group) return $group;
// Create new group
$group = new Group();
$group->Title = 'Blog users';
$group->Code = $code;
$group->write();
// Add permission
$permission = new Permission();
$permission->Code = $this->config()->grant_user_permission;
$group->Permissions()->add($permission);
return $group;
}
protected function onBeforeWrite() {
parent::onBeforeWrite();
$this->assignGroup();
}
/**
* Assign users as necessary to the blog group
* Assign users as necessary to the blog group.
*/
protected function assignGroup() {
// Ensure that any user granted editor, writer, or contributor have CMS_ACCESS_CMSMain access
if(!$this->config()->grant_user_access) return;
if(!$this->config()->grant_user_access) {
return;
}
// Generate or retrieve the group
$group = $this->getUserGroup();
foreach(array($this->Editors(), $this->Writers(), $this->Contributors()) as $userlist) {
foreach($userlist as $user) {
// Ensure user exists in the group
if(!$user->inGroup($group)) $user->Groups()->add($group);
foreach(array($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()->grant_user_group;
$group = Group::get()->filter('Code', $code)->first();
if($group) {
return $group;
}
$group = new Group();
$group->Title = 'Blog users';
$group->Code = $code;
$group->write();
$permission = new Permission();
$permission->Code = $this->config()->grant_user_permission;
$group->Permissions()->add($permission);
return $group;
}
}
/**
* Blog Controller
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
*/
class Blog_Controller extends Page_Controller {
/**
* @var array
*/
private static $allowed_actions = array(
'archive',
'tag',
'category',
'rss',
'profile'
'profile',
);
/**
* @var array
*/
private static $url_handlers = array(
'tag/$Tag!' => 'tag',
'category/$Category!' => 'category',
'archive/$Year!/$Month/$Day' => 'archive',
'profile/$URLSegment!' => 'profile'
'profile/$URLSegment!' => 'profile',
);
/**
* @var array
*/
private static $casting = array(
'MetaTitle' => 'Text',
'FilterDescription' => 'Text'
'FilterDescription' => 'Text',
);
/**
* The current Blog Post DataList query.
*
* @var DataList
**/
*/
protected $blogPosts;
/**
* @return string
*/
public function index() {
$this->blogPosts = $this->getBlogPosts();
return $this->render();
}
@ -550,7 +635,7 @@ class Blog_Controller extends Page_Controller {
* Renders a Blog Member's profile.
*
* @return SS_HTTPResponse
**/
*/
public function profile() {
$profile = $this->getCurrentProfile();
@ -566,8 +651,8 @@ class Blog_Controller extends Page_Controller {
/**
* Get the Member associated with the current URL segment.
*
* @return Member|null
**/
* @return null|Member
*/
public function getCurrentProfile() {
$urlSegment = $this->request->param('URLSegment');
@ -581,10 +666,10 @@ class Blog_Controller extends Page_Controller {
}
/**
* Get posts related to the current Member profile
* Get posts related to the current Member profile.
*
* @return DataList|null
**/
* @return null|DataList
*/
public function getCurrentProfilePosts() {
$profile = $this->getCurrentProfile();
@ -596,279 +681,297 @@ class Blog_Controller extends Page_Controller {
}
/**
* Renders an archive for a specificed date. This can be by year or year/month
* Renders an archive for a specified date. This can be by year or year/month.
*
* @return SS_HTTPResponse
**/
*/
public function archive() {
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
$day = $this->getArchiveDay();
// If an invalid month has been passed, we can return a 404.
if($this->request->param("Month") && !$month) {
return $this->httpError(404, "Not Found");
if($this->request->param('Month') && !$month) {
return $this->httpError(404, 'Not Found');
}
// Check for valid day
if($month && $this->request->param("Day") && !$day) {
return $this->httpError(404, "Not Found");
if($month && $this->request->param('Day') && !$day) {
return $this->httpError(404, 'Not Found');
}
if($year) {
$this->blogPosts = $this->getArchivedBlogPosts($year, $month, $day);
return $this->render();
}
return $this->httpError(404, "Not Found");
return $this->httpError(404, 'Not Found');
}
/**
* Fetches the archive year from the url.
*
* @return null|int
*/
public function getArchiveYear() {
$year = $this->request->param('Year');
if(preg_match('/^[0-9]{4}$/', $year)) {
return (int) $year;
}
return null;
}
/**
* Fetches the archive money from the url.
*
* @return null|int
*/
public function getArchiveMonth() {
$month = $this->request->param('Month');
if(preg_match('/^[0-9]{1,2}$/', $month)) {
if($month > 0 && $month < 13) {
if(checkdate($month, 01, $this->getArchiveYear())) {
return (int) $month;
}
}
}
return null;
}
/**
* Fetches the archive day from the url.
*
* @return null|int
*/
public function getArchiveDay() {
$day = $this->request->param('Day');
if(preg_match('/^[0-9]{1,2}$/', $day)) {
if(checkdate($this->getArchiveMonth(), $day, $this->getArchiveYear())) {
return (int) $day;
}
}
return null;
}
/**
* Renders the blog posts for a given tag.
*
* @return SS_HTTPResponse
**/
*/
public function tag() {
$tag = $this->getCurrentTag();
if($tag) {
$this->blogPosts = $tag->BlogPosts();
return $this->render();
}
return $this->httpError(404, "Not Found");
return $this->httpError(404, 'Not Found');
}
/**
* Tag Getter for use in templates.
*
* @return null|BlogTag
*/
public function getCurrentTag() {
$tag = $this->request->param('Tag');
if($tag) {
return $this->dataRecord->Tags()
->filter('URLSegment', $tag)
->first();
}
return null;
}
/**
* Renders the blog posts for a given category
* Renders the blog posts for a given category.
*
* @return SS_HTTPResponse
**/
*/
public function category() {
$category = $this->getCurrentCategory();
if($category) {
$this->blogPosts = $category->BlogPosts();
return $this->render();
}
return $this->httpError(404, "Not Found");
return $this->httpError(404, 'Not Found');
}
/**
* Get the meta title for the current action
* Category Getter for use in templates.
*
* @return null|BlogCategory
*/
public function getCurrentCategory() {
$category = $this->request->param('Category');
if($category) {
return $this->dataRecord->Categories()
->filter('URLSegment', $category)
->first();
}
return null;
}
/**
* Get the meta title for the current action.
*
* @return string
*/
public function getMetaTitle() {
$title = $this->data()->getTitle();
$filter = $this->getFilterDescription();
if($filter) {
$title = "{$title} - {$filter}";
$title = sprintf('%s - $s', $title, $filter);
}
$this->extend('updateMetaTitle', $title);
return $title;
}
/**
* Returns a description of the current filter
* Returns a description of the current filter.
*
* @return string
*/
public function getFilterDescription() {
$items = array();
// Check current page
$list = $this->PaginatedList();
$currentPage = $list->CurrentPage();
// Build title
if($currentPage > 1) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_PAGE',
"Page {page}",
'Page {page}',
null,
array('page' => $currentPage)
array(
'page' => $currentPage,
)
);
}
// Check author
if($author = $this->getCurrentProfile()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_AUTHOR',
"By {author}",
'By {author}',
null,
array('author' => $author->Title)
array(
'author' => $author->Title,
)
);
}
// Check tag
if($tag = $this->getCurrentTag()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_TAG',
"Tagged with {tag}",
'Tagged with {tag}',
null,
array('tag' => $tag->Title)
array(
'tag' => $tag->Title,
)
);
}
// Check category
if($category = $this->getCurrentCategory()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_CATEGORY',
"In category {category}",
'In category {category}',
null,
array('category' => $category->Title)
array(
'category' => $category->Title,
)
);
}
// Check archive
if($this->owner->getArchiveYear()) {
if($this->owner->getArchiveDay()) {
$date = $this->owner->getArchiveDate()->Nice();
} elseif($this->owner->getArchiveMonth()) {
$date = $this->owner->getArchiveDate()->format("F, Y");
$date = $this->owner->getArchiveDate()->format('F, Y');
} else {
$date = $this->owner->getArchiveDate()->format("Y");
$date = $this->owner->getArchiveDate()->format('Y');
}
$items[] = _t(
'Blog.FILTERDESCRIPTION_DATE',
"In {date}",
'In {date}',
null,
array('date' => $date)
array(
'date' => $date,
)
);
}
$result = '';
if($items) $result = implode(', ', $items);
// Allow extension
if($items) {
$result = implode(', ', $items);
}
$this->extend('updateFilterDescription', $result);
return $result;
}
/**
* Displays an RSS feed of blog posts
*
* @return string HTML
**/
public function rss() {
$rss = new RSSFeed($this->getBlogPosts(), $this->Link(), $this->MetaTitle, $this->MetaDescription);
$this->extend('updateRss', $rss);
return $rss->outputToBrowser();
}
/**
* Returns a list of paginated blog posts based on the blogPost dataList
* Returns a list of paginated blog posts based on the BlogPost dataList.
*
* @return PaginatedList
**/
*/
public function PaginatedList() {
$posts = new PaginatedList($this->blogPosts);
// If pagination is set to '0' then no pagination will be shown.
if($this->PostsPerPage > 0) {
$posts->setPageLength($this->PostsPerPage);
} else {
$pageSize = $this->getBlogPosts()->count() ?: 99999;
$pageSize = 99999;
if($count = $this->getBlogPosts()->count()) {
$pageSize = $count;
}
$posts->setPageLength($pageSize);
}
$start = $this->request->getVar($posts->getPaginationGetVar());
$posts->setPageStart($start);
return $posts;
}
/**
* Tag Getter for use in templates.
* Displays an RSS feed of blog posts.
*
* @return BlogTag|null
**/
public function getCurrentTag() {
$tag = $this->request->param("Tag");
if($tag) {
return $this->dataRecord->Tags()
->filter("URLSegment", $tag)
->first();
}
return null;
* @return string
*/
public function rss() {
$rss = new RSSFeed($this->getBlogPosts(), $this->Link(), $this->MetaTitle, $this->MetaDescription);
$this->extend('updateRss', $rss);
return $rss->outputToBrowser();
}
/**
* Category Getter for use in templates.
*
* @return BlogCategory|null
**/
public function getCurrentCategory() {
$category = $this->request->param("Category");
if($category) {
return $this->dataRecord->Categories()
->filter("URLSegment", $category)
->first();
}
return null;
}
/**
* Fetches the archive year from the url
*
* @return int|null
**/
public function getArchiveYear() {
$year = $this->request->param("Year");
if(preg_match("/^[0-9]{4}$/", $year)) {
return (int) $year;
}
return null;
}
/**
* Fetches the archive money from the url.
*
* @return int|null
**/
public function getArchiveMonth() {
$month = $this->request->param("Month");
if(preg_match("/^[0-9]{1,2}$/", $month)) {
if($month > 0 && $month < 13) {
// Check that we have a valid date.
if(checkdate($month, 01, $this->getArchiveYear())) {
return (int) $month;
}
}
}
return null;
}
/**
* Fetches the archive day from the url
*
* @return int|null
**/
public function getArchiveDay() {
$day = $this->request->param("Day");
if(preg_match("/^[0-9]{1,2}$/", $day)) {
// Check that we have a valid date
if(checkdate($this->getArchiveMonth(), $day, $this->getArchiveYear())) {
return (int) $day;
}
}
return null;
}
/**
* Returns the current archive date.
*
* @return Date
**/
* @return null|Date
*/
public function getArchiveDate() {
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
@ -876,25 +979,27 @@ class Blog_Controller extends Page_Controller {
if($year) {
if($month) {
$date = $year . '-' . $month . '-01';
$date = sprintf('%s-%s-01', $year, $month);
if($day) {
$date = $year . '-' . $month . '-' . $day;
$date = sprintf('%s-%s-%s', $year, $month, $day);
}
} else {
$date = $year . '-01-01';
$date = sprintf('%s-01-01', $year);
}
return DBField::create_field("Date", $date);
}
}
return DBField::create_field('Date', $date);
}
return null;
}
/**
* Returns a link to the RSS feed.
*
* @return string URL
**/
* @return string
*/
public function getRSSLink() {
return $this->Link("rss");
return $this->Link('rss');
}
}

View File

@ -1,127 +1,135 @@
<?php
/**
* A blog category fo generalising blog posts.
* A blog category for generalising blog posts.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
class BlogCategory extends DataObject {
* @method Blog Blog()
* @method ManyManyList BlogPosts()
*
* @property string $URLSegment
* @property int $BlogID
*/
class BlogCategory extends DataObject implements CategorisationObject {
/**
* @var array
*/
private static $db = array(
"Title" => "Varchar(255)",
'Title' => 'Varchar(255)',
);
/**
* @var array
*/
private static $has_one = array(
"Blog" => "Blog",
'Blog' => 'Blog',
);
/**
* @var array
*/
private static $belongs_many_many = array(
"BlogPosts" => "BlogPost",
'BlogPosts' => 'BlogPost',
);
/**
* @var array
*/
private static $extensions = array(
"URLSegmentExtension",
'URLSegmentExtension',
);
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$fields = new FieldList(
TextField::create("Title", _t("BlogCategory.Title", "Title"))
TextField::create('Title', _t('BlogCategory.Title', 'Title'))
);
$this->extend("updateCMSFields", $fields);
$this->extend('updateCMSFields', $fields);
return $fields;
}
/**
* Returns a relative link to this category.
*
* @return string URL
**/
* @return string
*/
public function getLink() {
return Controller::join_links($this->Blog()->Link(), "category", $this->URLSegment);
return Controller::join_links($this->Blog()->Link(), 'category', $this->URLSegment);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param $member Member
* @param null|Member $member
*
* @return boolean
* @return bool
*/
public function canView($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
return $this->Blog()->canView($member);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param $member Member
* @param null|Member $member
*
* @return boolean
* @return bool
*/
public function canCreate($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
// Since there is no parent yet, need to make a best guess
$permission = Blog::config()->grant_user_permission;
return Permission::checkMember($member, $permission);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param $member Member
* @param null|Member $member
*
* @return boolean
* @return bool
*/
public function canDelete($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
return $this->Blog()->canEdit($member);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param $member Member
* @param null|Member $member
*
* @return boolean
* @return bool
*/
public function canEdit($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
return $this->Blog()->canEdit($member);
}
}

View File

@ -1,7 +1,7 @@
<?php
/**
* An indivisual blog post.
* An individual blog post.
*
* @package silverstripe
* @subpackage blog
@ -9,74 +9,145 @@
* @method ManyManyList Categories()
* @method ManyManyList Tags()
* @method ManyManyList Authors()
* @method Blog Parent()
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
* @property string $PublishDate
* @property string $AuthorNames
* @property int $ParentID
*/
class BlogPost extends Page {
/**
* @var array
*/
private static $db = array(
"PublishDate" => "SS_Datetime",
"AuthorNames" => "Varchar(1024)",
"Summary" => "HTMLText",
'PublishDate' => 'SS_Datetime',
'AuthorNames' => 'Varchar(1024)',
'Summary' => 'HTMLText',
);
/**
* @var array
*/
private static $has_one = array(
"FeaturedImage" => "Image",
'FeaturedImage' => 'Image',
);
/**
* @var array
*/
private static $many_many = array(
"Categories" => "BlogCategory",
"Tags" => "BlogTag",
"Authors" => "Member",
'Categories' => 'BlogCategory',
'Tags' => 'BlogTag',
'Authors' => 'Member',
);
/**
* @var array
*/
private static $defaults = array(
"ShowInMenus" => false,
"InheritSideBar" => true, // Support for widgets
"ProvideComments" => true, // Support for comments
'ShowInMenus' => false,
'InheritSideBar' => true,
'ProvideComments' => true,
);
/**
* @var array
*/
private static $extensions = array(
"BlogPostFilter",
'BlogPostFilter',
);
/**
* @var array
*/
private static $searchable_fields = array(
"Title",
'Title',
);
/**
* @var array
*/
private static $summary_fields = array(
"Title",
'Title',
);
/**
* @var array
*/
private static $casting = array(
'Excerpt' => 'Text'
'Excerpt' => 'Text',
);
/**
* @var array
*/
private static $allowed_children = array();
private static $default_sort = "PublishDate DESC";
/**
* @var string
*/
private static $default_sort = 'PublishDate DESC';
/**
* @var bool
*/
private static $can_be_root = false;
/**
* This will display or hide the current class from the SiteTree. This
* variable can be configured using YAML.
* This will display or hide the current class from the SiteTree. This variable can be
* configured using YAML.
*
* @var boolean
**/
* @var bool
*/
private static $show_in_sitetree = false;
/**
* Determine the role of the given member.
*
* Call be called via template to determine the current user.
*
* @example "Hello $RoleOf($CurrentMember.ID)"
*
* @param null|int|Member $member
*
* @return null|string
*/
public function RoleOf($member = null) {
if(is_int($member)) {
$member = DataObject::get_by_id('Member', $member);
}
if(!$member) {
return null;
}
if($this->isAuthor($member)) {
return _t('BlogPost.AUTHOR', 'Author');
}
$parent = $this->Parent();
if($parent instanceof Blog) {
return $parent->RoleOf($member);
}
return null;
}
/**
* Determine if the given member is an author of this post
* Determine if the given member is an author of this post.
*
* @param Member $member
* @return boolean
* @param null|Member $member
*
* @return bool
*/
public function isAuthor($member) {
if(!$member || !$member->exists()) return false;
public function isAuthor($member = null) {
if(!$member || !$member->exists()) {
return false;
}
$list = $this->Authors();
if($list instanceof UnsavedRelationList) {
return in_array($member->ID, $list->getIDList());
}
@ -85,92 +156,80 @@ class BlogPost extends Page {
}
/**
* Determine the role of the given member
* Call be called via template to determine the current user
*
* E.g. `Hello $RoleOf($CurrentMember.ID)`
*
* @param Member|integer $member
* @return string|null Author, Editor, Writer, Contributor, or null if no role
* {@inheritdoc}
*/
public function RoleOf($member) {
if(is_numeric($member)) $member = DataObject::get_by_id('Member', $member);
if(!$member) return null;
// Check if this member is an author
if($this->isAuthor($member)) return _t("BlogPost.AUTHOR", "Author");
// Check parent role
$parent = $this->Parent();
if($parent instanceof Blog) return $parent->RoleOf($member);
}
public function getCMSFields() {
Requirements::css(BLOGGER_DIR . '/css/cms.css');
Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
$self =& $this;
$this->beforeUpdateCMSFields(function($fields) use ($self) {
// Add blog summary
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
/**
* @var FieldList $fields
*/
$summary = HtmlEditorField::create('Summary', false);
$summary->setRows(5);
$summary->setDescription(_t(
'BlogPost.SUMMARY_DESCRIPTION',
'If no summary is specified the first 30 words will be used.'
));
$summaryHolder = ToggleCompositeField::create(
'CustomSummary',
_t('BlogPost.CUSTOMSUMMARY', 'Add A Custom Summary'),
array(
$summary = HtmlEditorField::create("Summary", false)
$summary,
)
)
->setHeadingLevel(4)
->addExtraClass('custom-summary');
$summary->setRows(5);
$summary->setDescription(_t(
'BlogPost.SUMMARY_DESCRIPTION',
"If no summary is specified the first 30 words will be used."
));
);
$summaryHolder->setHeadingLevel(4);
$summaryHolder->addExtraClass('custom-summary');
$fields->insertBefore($summaryHolder, 'Content');
// Add featured image
$fields->insertAfter(
$uploadField = UploadField::create("FeaturedImage", _t("BlogPost.FeaturedImage", "Featured Image")),
"Content"
);
$uploadField = UploadField::create('FeaturedImage', _t('BlogPost.FeaturedImage', 'Featured Image'));
$uploadField->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif'));
// We're going to hide MenuTitle - Its not needed in blog posts.
$fields->insertAfter(
$uploadField,
'Content'
);
$fields->push(HiddenField::create('MenuTitle'));
// We're going to add the url segment to sidebar so we're making it a little lighter
$urlSegment = $fields->dataFieldByName('URLSegment');
$urlSegment->setURLPrefix($self->Parent()->RelativeLink());
// Remove the MenuTitle and URLSegment from the main tab
$fields->removeFieldsFromTab('Root.Main', array(
'MenuTitle',
'URLSegment',
));
// Author field
$authorField = ListboxField::create(
"Authors",
_t("BlogPost.Authors", "Authors"),
'Authors',
_t('BlogPost.Authors', 'Authors'),
Member::get()->map()->toArray()
)->setMultiple(true);
$authorNames = TextField::create(
"AuthorNames",
_t("BlogPost.AdditionalCredits", "Additional Credits"),
'AuthorNames',
_t('BlogPost.AdditionalCredits', 'Additional Credits'),
null,
1024
)->setDescription('If some authors of this post don\'t have CMS access, enter their name(s) here. You can separate multiple names with a comma.');
);
$authorNames->setDescription('If some authors of this post don\'t have CMS access, enter their name(s) here. You can separate multiple names with a comma.');
if(!$self->canEditAuthors()) {
$authorField = $authorField->performDisabledTransformation();
$authorNames = $authorNames->performDisabledTransformation();
}
// Build up our sidebar
$publishDate = DatetimeField::create('PublishDate', _t('BlogPost.PublishDate', 'Publish Date'));
$publishDate->getDateField()->setConfig('showcalendar', true);
$options = BlogAdminSidebar::create(
$publishDate = DatetimeField::create("PublishDate", _t("BlogPost.PublishDate", "Publish Date")),
$publishDate,
$urlSegment,
TagField::create(
'Categories',
@ -189,36 +248,84 @@ class BlogPost extends Page {
$authorField,
$authorNames
)->setTitle('Post Options');
$publishDate->getDateField()->setConfig("showcalendar", true);
// Insert it before the TabSet
$fields->insertBefore($options, 'Root');
});
$fields = parent::getCMSFields();
// We need to render an outer template to deal with our custom layout
$fields->fieldByName('Root')->setTemplate('TabSet_holder');
return $fields;
}
/**
* Determine if this user can edit the authors list.
*
* @param null|int|Member $member
*
* @return bool
*/
public function canEditAuthors($member = null) {
$member = $this->getMember($member);
$extended = $this->extendedCan('canEditAuthors', $member);
if($extended !== null) {
return $extended;
}
$parent = $this->Parent();
if($parent instanceof Blog && $parent->exists()) {
if($parent->isEditor($member)) {
return true;
}
if($parent->isWriter($member) && $this->isAuthor($member)) {
return true;
}
}
return Permission::checkMember($member, Blog::MANAGE_USERS);
}
/**
* @param null|int|Member $member
*
* @return null|Member
*/
protected function getMember($member = null) {
if(!$member) {
$member = Member::currentUser();
}
if(is_int($member)) {
$member = Member::get()->byID($member);
}
return $member;
}
/**
* Determine whether user can create new categories.
*
* @param int|Member|null $member
* @param null|int|Member $member
*
* @return bool
*/
public function canCreateCategories($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
$member = $member = $this->getMember($member);
$parent = $this->Parent();
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) return false;
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) {
return false;
}
if($parent->isEditor($member)) return true;
if($parent->isEditor($member)) {
return true;
}
return Permission::checkMember($member, 'ADMIN');
}
@ -226,212 +333,214 @@ class BlogPost extends Page {
/**
* Determine whether user can create new tags.
*
* @param int|Member|null $member
* @param null|int|Member $member
*
* @return bool
*/
public function canCreateTags($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
$member = $member = $this->getMember($member);
$parent = $this->Parent();
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) return false;
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) {
return false;
}
if($parent->isEditor($member)) return true;
if($parent->isEditor($member)) {
return true;
}
if($parent->isWriter($member)) return true;
if($parent->isWriter($member)) {
return true;
}
return Permission::checkMember($member, 'ADMIN');
}
protected function onBeforeWrite() {
parent::onBeforeWrite();
// If no publish date is set, set the date to now.
if(!$this->PublishDate) $this->PublishDate = SS_Datetime::now()->getValue();
// If creating a new entry, assign the current member as an author
// This allows writers and contributors to then edit their new post
if(!$this->exists() && ($member = Member::currentUser())) {
$this->Authors()->add($member);
}
}
/**
* Update the PublishDate to now, if being published for the first time, and the date hasn't been set to the future.
**/
* {@inheritdoc}
*
* Update the PublishDate to now, if being published for the first time, and the date hasn't
* been set to the future.
*/
public function onBeforePublish() {
if ($this->dbObject('PublishDate')->InPast() && !$this->isPublished()) {
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
if($publishDate->InPast() && !$this->isPublished()) {
$this->PublishDate = SS_Datetime::now()->getValue();
$this->write();
}
}
/**
* Sets blog relationship on all categories and tags assigned to this post.
* {@inheritdoc}
*
* @throws ValidationException
* Sets blog relationship on all categories and tags assigned to this post.
*/
public function onAfterWrite()
{
public function onAfterWrite() {
parent::onAfterWrite();
foreach ($this->Categories() as $category) {
foreach($this->Categories() as $category) {
/**
* @var BlogCategory $category
*/
$category->BlogID = $this->ParentID;
$category->write();
}
foreach ($this->Tags() as $tag) {
foreach($this->Tags() as $tag) {
/**
* @var BlogTag $tag
*/
$tag->BlogID = $this->ParentID;
$tag->write();
}
}
/**
* Checks the publish date to see if the blog post has actually been published.
*
* @param $member Member|null
*
* @return boolean
**/
* {@inheritdoc}
*/
public function canView($member = null) {
if(!parent::canView($member)) return false;
if(!parent::canView($member)) {
return false;
}
if($this->PublishDate) {
$publishDate = $this->dbObject("PublishDate");
if($publishDate->InFuture() && !Permission::checkMember($member, "VIEW_DRAFT_CONTENT")) {
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
if($publishDate->InFuture() && !Permission::checkMember($member, 'VIEW_DRAFT_CONTENT')) {
return false;
}
}
return true;
}
public function canEdit($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
/**
* {@inheritdoc}
*/
public function canPublish($member = null) {
$member = $this->getMember($member);
// Inherit permission
if(parent::canEdit($member)) return true;
if(Permission::checkMember($member, 'ADMIN')) {
return true;
}
$extended = $this->extendedCan('canPublish', $member);
if($extended !== null) {
return $extended;
}
// Check if assigned to a blog
$parent = $this->Parent();
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) return false;
// Editors have full control
if($parent->isEditor($member)) return true;
if($parent instanceof Blog && $parent->exists()) {
if($parent->isEditor($member)) {
return true;
}
// Only writers or contributors can edit
if(!$parent->isWriter($member) && !$parent->isContributor($member)) return false;
if($parent->isWriter($member) && $this->isAuthor($member)) {
return true;
}
if($parent->isContributor($member)) {
return parent::canEdit($member);
}
}
return $this->canEdit($member);
}
/**
* {@inheritdoc}
*/
public function canEdit($member = null) {
$member = $this->getMember($member);
if(parent::canEdit($member)) {
return true;
}
$parent = $this->Parent();
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) {
return false;
}
if($parent->isEditor($member)) {
return true;
}
if(!$parent->isWriter($member) && !$parent->isContributor($member)) {
return false;
}
// And only if they are also authors
return $this->isAuthor($member);
}
/**
* Determine if this user can edit the authors list
*
* @param Member $member
* @return boolean
*/
public function canEditAuthors($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
$extended = $this->extendedCan('canEditAuthors', $member);
if($extended !== null) return $extended;
// Check blog roles
$parent = $this->Parent();
if($parent instanceof Blog && $parent->exists()) {
// Editors can do anything
if($parent->isEditor($member)) return true;
// Writers who are also authors can edit authors
if($parent->isWriter($member) && $this->isAuthor($member)) return true;
}
// Check permission
return Permission::checkMember($member, Blog::MANAGE_USERS);
}
public function canPublish($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
if(Permission::checkMember($member, "ADMIN")) return true;
// Standard mechanism for accepting permission changes from extensions
$extended = $this->extendedCan('canPublish', $member);
if($extended !== null) return $extended;
// Check blog roles
$parent = $this->Parent();
if($parent instanceof Blog && $parent->exists()) {
// Editors can do anything
if($parent->isEditor($member)) return true;
// Writers who are also authors can edit authors
if($parent->isWriter($member) && $this->isAuthor($member)) return true;
// Contributors can ONLY publish this page if they somehow have global publish permissions
// In this case defer to old canEdit implementation
if($parent->isContributor($member)) return parent::canEdit($member);
}
// Normal case - fail over to canEdit()
return $this->canEdit($member);
}
/**
* Returns the post excerpt.
*
* @param $wordCount int - number of words to display
* @param int $wordsToDisplay
*
* @return string
**/
public function Excerpt($wordCount = 30) {
return $this->dbObject("Content")->LimitWordCount($wordCount);
*/
public function Excerpt($wordsToDisplay = 30) {
/**
* @var Text $content
*/
$content = $this->dbObject('Content');
return $content->LimitWordCount($wordsToDisplay);
}
/**
* Returns a monthly archive link for the current blog post.
*
* @param $type string day|month|year
* @param string $type
*
* @return string URL
**/
public function getMonthlyArchiveLink($type = "day") {
$date = $this->dbObject("PublishDate");
if($type != "year") {
if($type == "day") {
* @return string
*/
public function getMonthlyArchiveLink($type = 'day') {
/**
* @var SS_Datetime $date
*/
$date = $this->dbObject('PublishDate');
if($type != 'year') {
if($type == 'day') {
return Controller::join_links(
$this->Parent()->Link("archive"),
$date->format("Y"),
$date->format("m"),
$date->format("d")
$this->Parent()->Link('archive'),
$date->format('Y'),
$date->format('m'),
$date->format('d')
);
}
return Controller::join_links($this->Parent()->Link("archive"), $date->format("Y"), $date->format("m"));
return Controller::join_links($this->Parent()->Link('archive'), $date->format('Y'), $date->format('m'));
}
return Controller::join_links($this->Parent()->Link("archive"), $date->format("Y"));
return Controller::join_links($this->Parent()->Link('archive'), $date->format('Y'));
}
/**
* Returns a yearly archive link for the current blog post.
*
* @return string URL
**/
* @return string
*/
public function getYearlyArchiveLink() {
$date = $this->dbObject("PublishDate");
return Controller::join_links($this->Parent()->Link("archive"), $date->format("Y"));
/**
* @var SS_Datetime $date
*/
$date = $this->dbObject('PublishDate');
return Controller::join_links($this->Parent()->Link('archive'), $date->format('Y'));
}
/**
@ -439,8 +548,7 @@ class BlogPost extends Page {
*
* @return ArrayList
*/
public function getCredits()
{
public function getCredits() {
$list = new ArrayList();
$list->merge($this->getDynamicCredits());
@ -454,8 +562,7 @@ class BlogPost extends Page {
*
* @return ArrayList
*/
protected function getDynamicCredits()
{
protected function getDynamicCredits() {
$items = new ArrayList();
foreach($this->Authors() as $author) {
@ -474,13 +581,12 @@ class BlogPost extends Page {
*
* @return ArrayList
*/
protected function getStaticCredits()
{
protected function getStaticCredits() {
$items = new ArrayList();
$authors = array_filter(preg_split('/\s*,\s*/', $this->AuthorNames));
foreach ($authors as $author) {
foreach($authors as $author) {
$item = new ArrayData(array(
'Name' => $author,
));
@ -492,27 +598,40 @@ class BlogPost extends Page {
}
/**
* Sets the label for BlogPost.Title to 'Post Title' (Rather than 'Page name')
* Sets the label for BlogPost.Title to 'Post Title' (Rather than 'Page name').
*
* @param bool $includeRelations
*
* @return array
**/
public function fieldLabels($includerelations = true) {
$labels = parent::fieldLabels($includerelations);
$labels['Title'] = _t('BlogPost.PageTitleLabel', "Post Title");
*/
public function fieldLabels($includeRelations = true) {
$labels = parent::fieldLabels($includeRelations);
$labels['Title'] = _t('BlogPost.PageTitleLabel', "Post Title");
return $labels;
}
}
/**
* {@inheritdoc}
*/
protected function onBeforeWrite() {
parent::onBeforeWrite();
if(!$this->PublishDate) {
$this->PublishDate = SS_Datetime::now()->getValue();
}
if(!$this->exists() && ($member = Member::currentUser())) {
$this->Authors()->add($member);
}
}
}
/**
* Blog Post controller
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
*/
class BlogPost_Controller extends Page_Controller {
}

View File

@ -1,119 +1,136 @@
<?php
/**
* A blog tag for keyword descriptions of a Blog post
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <github@michaelstrong.co.uk>
**/
class BlogTag extends DataObject {
private static $db = array(
"Title" => "Varchar(255)",
);
private static $has_one = array(
"Blog" => "Blog",
);
private static $belongs_many_many = array(
"BlogPosts" => "BlogPost",
);
private static $extensions = array(
"URLSegmentExtension",
);
public function getCMSFields() {
$fields = new FieldList(
TextField::create("Title", _t("BlogTag.Title", "Title"))
);
$this->extend("updateCMSFields", $fields);
return $fields;
}
/**
* Returns a relative URL for the tag link.
*
* @return string URL
**/
public function getLink() {
return Controller::join_links($this->Blog()->Link(), "tag", $this->URLSegment);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
*
* @param $member Member
*
* @return boolean
*/
public function canView($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
return $this->Blog()->canView($member);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
*
* @param $member Member
*
* @return boolean
*/
public function canCreate($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
// Since there is no parent yet, need to make a best guess
$permission = Blog::config()->grant_user_permission;
return Permission::checkMember($member, $permission);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
*
* @param $member Member
*
* @return boolean
*/
public function canDelete($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
return $this->Blog()->canEdit($member);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension
*
* @param $member Member
*
* @return boolean
*/
public function canEdit($member = null) {
$extended = $this->extendedCan(__FUNCTION__, $member);
if($extended !== null) {
return $extended;
}
return $this->Blog()->canEdit($member);
}
}
<?php
/**
* A blog tag for keyword descriptions of a blog post.
*
* @package silverstripe
* @subpackage blog
*
* @method Blog Blog()
* @method ManyManyList BlogPosts
*
* @property string $Title
* @property string $URLSegment
* @property int $BlogID
*/
class BlogTag extends DataObject implements CategorisationObject {
/**
* @var array
*/
private static $db = array(
'Title' => 'Varchar(255)',
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* @var array
*/
private static $belongs_many_many = array(
'BlogPosts' => 'BlogPost',
);
/**
* @var array
*/
private static $extensions = array(
'URLSegmentExtension',
);
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$fields = new FieldList(
TextField::create('Title', _t('BlogTag.Title', 'Title'))
);
$this->extend('updateCMSFields', $fields);
return $fields;
}
/**
* Returns a relative URL for the tag link.
*
* @return string
*/
public function getLink() {
return Controller::join_links($this->Blog()->Link(), 'tag', $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);
}
/**
* Inherits from the parent blog or can be overwritten using a DataExtension.
*
* @param null|Member $member
*
* @return bool
*/
public function canCreate($member = null) {
$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()->canEdit($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);
}
}

View File

@ -0,0 +1,8 @@
<?php
/**
* @method ManyManyList BlogPosts
*/
interface CategorisationObject {
}

View File

@ -1,88 +1,125 @@
<?php
if(class_exists("Widget")) {
if(!class_exists('Widget')) {
return;
}
class BlogArchiveWidget extends Widget {
private static $title = "Archive";
/**
* @method Blog Blog()
*
* @property string $ArchiveType
* @property int $NumberToDisplay
*/
class BlogArchiveWidget extends Widget {
/**
* @var string
*/
private static $title = 'Archive';
private static $cmsTitle = "Archive";
/**
* @var string
*/
private static $cmsTitle = 'Archive';
private static $description = "Displays an archive list of posts.";
/**
* @var string
*/
private static $description = 'Displays an archive list of posts.';
private static $db = array(
"NumberToDisplay" => "Int",
"ArchiveType" => "Enum('Monthly,Yearly', 'Monthly')"
);
/**
* @var array
*/
private static $db = array(
'NumberToDisplay' => 'Int',
'ArchiveType' => 'Enum("Monthly,Yearly", "Monthly")',
);
private static $defaults = array(
"NumberOfMonths" => 12
);
/**
* @var array
*/
private static $defaults = array(
'NumberOfMonths' => 12,
);
private static $has_one = array(
"Blog" => "Blog",
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
public function getCMSFields() {
$self = $this;
$this->beforeUpdateCMSFields(function($fields) use ($self) {
$type = $self->dbObject("ArchiveType")->enumValues();
foreach($type as $k => $v) {
$type[$k] = _t("BlogArchiveWidget." . ucfirst(strtolower($v)), $v);
}
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$self = &$this;
$fields->merge(array(
DropdownField::create("BlogID", _t("BlogArchiveWidget.Blog", "Blog"), Blog::get()->map()),
DropdownField::create("ArchiveType", _t("BlogArchiveWidget.ArchiveType", "ArchiveType"), $type),
NumericField::create("NumberToDisplay", _t("BlogArchiveWidget.NumberToDisplay", "No. to Display"))
));
});
return parent::getCMSFields();
}
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
$type = $self->dbObject('ArchiveType')->enumValues();
/**
* Returns a list of months where blog posts are present.
*
* @return DataList
**/
public function getArchive() {
$query = $this->Blog()->getBlogPosts()->dataQuery();
if($this->ArchiveType == "Yearly") {
$query->groupBy("DATE_FORMAT(PublishDate, '%Y')");
} else {
$query->groupBy("DATE_FORMAT(PublishDate, '%Y-%M')");
foreach($type as $k => $v) {
$type[$k] = _t('BlogArchiveWidget.' . ucfirst(strtolower($v)), $v);
}
$articles = $this->Blog()->getBlogPosts()->setDataQuery($query);
if($this->NumberToDisplay > 0) $articles = $articles->limit($this->NumberToDisplay);
$archive = new ArrayList();
if($articles->count() > 0) {
foreach($articles as $article) {
if($this->ArchiveType == "Yearly") {
$year = date('Y', strtotime($article->PublishDate));
$month = null;
$title = $year;
} else {
$year = date('Y', strtotime($article->PublishDate));
$month = date('m', strtotime($article->PublishDate));
$title = date('F Y', strtotime($article->PublishDate));
}
$archive->push(new ArrayData(array(
"Title" => $title,
"Link" => Controller::join_links($this->Blog()->Link("archive"), $year, $month)
)));
}
}
return $archive;
$fields->merge(array(
DropdownField::create('BlogID', _t('BlogArchiveWidget.Blog', 'Blog'), Blog::get()->map()),
DropdownField::create('ArchiveType', _t('BlogArchiveWidget.ArchiveType', 'ArchiveType'), $type),
NumericField::create('NumberToDisplay', _t('BlogArchiveWidget.NumberToDisplay', 'No. to Display'))
));
});
return parent::getCMSFields();
}
/**
* Returns a list of months where blog posts are present.
*
* @return DataList
*/
public function getArchive() {
$query = $this->Blog()->getBlogPosts()->dataQuery();
if($this->ArchiveType == 'Yearly') {
$query->groupBy('DATE_FORMAT(PublishDate, "%Y")');
} else {
$query->groupBy('DATE_FORMAT(PublishDate, "%Y-%M")');
}
}
$posts = $this->Blog()->getBlogPosts()->setDataQuery($query);
class BlogArchiveWidget_Controller extends Widget_Controller {
if($this->NumberToDisplay > 0) {
$posts = $posts->limit($this->NumberToDisplay);
}
$archive = new ArrayList();
if($posts->count() > 0) {
foreach($posts as $post) {
/**
* @var BlogPost $post
*/
if($this->ArchiveType == 'Yearly') {
$year = date('Y', strtotime($post->PublishDate));
$month = null;
$title = $year;
} else {
$year = date('Y', strtotime($post->PublishDate));
$month = date('m', strtotime($post->PublishDate));
$title = date('F Y', strtotime($post->PublishDate));
}
$archive->push(new ArrayData(array(
'Title' => $title,
'Link' => Controller::join_links($this->Blog()->Link('archive'), $year, $month)
)));
}
}
return $archive;
}
}
class BlogArchiveWidget_Controller extends Widget_Controller {
}

View File

@ -1,42 +1,67 @@
<?php
if(class_exists("Widget")) {
if(!class_exists("Widget")) {
return;
}
class BlogCategoriesWidget extends Widget {
private static $title = "Categories";
/**
* @method Blog Blog()
*/
class BlogCategoriesWidget extends Widget {
/**
* @var string
*/
private static $title = 'Categories';
private static $cmsTitle = "Blog Categories";
/**
* @var string
*/
private static $cmsTitle = 'Blog Categories';
private static $description = "Displays a list of blog categories.";
/**
* @var string
*/
private static $description = 'Displays a list of blog categories.';
private static $db = array();
/**
* @var array
*/
private static $db = array();
private static $has_one = array(
"Blog" => "Blog",
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
public function getCMSFields() {
$this->beforeUpdateCMSFields(function($fields) {
$fields->push(
DropdownField::create("BlogID", _t("BlogCategoriesWidget.Blog", "Blog"), Blog::get()->map())
);
});
return parent::getCMSFields();
}
public function getCategories() {
$blog = $this->Blog();
if($blog) {
return $blog->Categories();
}
return array();
}
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$this->beforeUpdateCMSFields(function ($fields) {
$fields->push(
DropdownField::create('BlogID', _t('BlogCategoriesWidget.Blog', 'Blog'), Blog::get()->map())
);
});
return parent::getCMSFields();
}
class BlogCategoriesWidget_Controller extends Widget_Controller {
/**
* @return array
*/
public function getCategories() {
$blog = $this->Blog();
if($blog) {
return $blog->Categories();
}
return array();
}
}
class BlogCategoriesWidget_Controller extends Widget_Controller {
}

View File

@ -1,47 +1,74 @@
<?php
if(class_exists("Widget")) {
if(!class_exists("Widget")) {
return;
}
class BlogRecentPostsWidget extends Widget {
private static $title = "Recent Posts";
/**
* @method Blog Blog()
*
* @property int $NumberOfPosts
*/
class BlogRecentPostsWidget extends Widget {
/**
* @var string
*/
private static $title = 'Recent Posts';
private static $cmsTitle = "Recent Posts";
/**
* @var string
*/
private static $cmsTitle = 'Recent Posts';
private static $description = "Displays a list of recent blog posts.";
/**
* @var string
*/
private static $description = 'Displays a list of recent blog posts.';
private static $db = array(
"NumberOfPosts" => "Int",
);
/**
* @var array
*/
private static $db = array(
'NumberOfPosts' => 'Int',
);
private static $has_one = array(
"Blog" => "Blog",
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
public function getCMSFields() {
$this->beforeUpdateCMSFields(function($fields) {
$fields->merge(array(
DropdownField::create("BlogID", _t("BlogRecentPostsWidget.Blog", "Blog"), Blog::get()->map()),
NumericField::create("NumberOfPosts", _t("BlogRecentPostsWidget.NumberOfPosts", "Number of Posts"))
));
});
return parent::getCMSFields();
}
public function getPosts() {
$blog = $this->Blog();
if($blog) {
return $blog->getBlogPosts()
->sort("PublishDate DESC")
->limit($this->NumberOfPosts);
}
return array();
}
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$this->beforeUpdateCMSFields(function ($fields) {
$fields->merge(array(
DropdownField::create('BlogID', _t('BlogRecentPostsWidget.Blog', 'Blog'), Blog::get()->map()),
NumericField::create('NumberOfPosts', _t('BlogRecentPostsWidget.NumberOfPosts', 'Number of Posts'))
));
});
return parent::getCMSFields();
}
class BlogRecentPostsWidget_Controller extends Widget_Controller {
}
/**
* @return array
*/
public function getPosts() {
$blog = $this->Blog();
}
if($blog) {
return $blog->getBlogPosts()
->sort('PublishDate DESC')
->limit($this->NumberOfPosts);
}
return array();
}
}
class BlogRecentPostsWidget_Controller extends Widget_Controller {
}

View File

@ -1,40 +1,65 @@
<?php
if(class_exists("Widget")) {
if(!class_exists("Widget")) {
return;
}
class BlogTagsWidget extends Widget {
private static $title = "Tags";
/**
* @method Blog Blog()
*/
class BlogTagsWidget extends Widget {
/**
* @var string
*/
private static $title = 'Tags';
private static $cmsTitle = "Blog Tags";
/**
* @var string
*/
private static $cmsTitle = 'Blog Tags';
private static $description = "Displays a list of blog tags.";
/**
* @var string
*/
private static $description = 'Displays a list of blog tags.';
private static $db = array();
/**
* @var array
*/
private static $db = array();
private static $has_one = array(
"Blog" => "Blog",
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
public function getCMSFields() {
$this->beforeUpdateCMSFields(function($fields) {
$fields->push(DropdownField::create("BlogID", _t("BlogTagsWidget.Blog", "Blog"), Blog::get()->map()));
});
return parent::getCMSFields();
}
public function getTags() {
$blog = $this->Blog();
if($blog) {
return $blog->Tags();
}
return array();
}
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$this->beforeUpdateCMSFields(function ($fields) {
$fields->push(DropdownField::create('BlogID', _t('BlogTagsWidget.Blog', 'Blog'), Blog::get()->map()));
});
return parent::getCMSFields();
}
class BlogTagsWidget_Controller extends Widget_Controller {
}
/**
* @return array
*/
public function getTags() {
$blog = $this->Blog();
}
if($blog) {
return $blog->Tags();
}
return array();
}
}
class BlogTagsWidget_Controller extends Widget_Controller {
}

View File

@ -1,107 +1,118 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class BlogCategoryTest extends FunctionalTest {
static $fixture_file = "blog.yml";
/**
* @var string
*/
static $fixture_file = 'blog.yml';
/**
* {@inheritdoc}
*/
public function setUp() {
SS_Datetime::set_mock_now("2013-10-10 20:00:00");
parent::setUp();
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
}
/**
* {@inheritdoc}
*/
public function tearDown() {
SS_Datetime::clear_mock_now();
parent::tearDown();
}
/**
* Tests that any blog posts returned from $category->BlogPosts() many_many are published,
* both by normal 'save & publish' functionality and by publish date.
**/
*/
public function testBlogPosts() {
// Ensure the user is not logged in as admin (or anybody)
$member = Member::currentUser();
if($member) $member->logout();
$post = $this->objFromFixture("BlogPost", "blogpost1");
$category = $this->objFromFixture("BlogCategory", "firstcategory");
$this->assertEquals(1, $category->BlogPosts()->count(), "Category blog post count");
if($member) {
$member->logout();
}
$this->objFromFixture('BlogPost', 'FirstBlogPost');
/**
* @var BlogCategory $category
*/
$category = $this->objFromFixture('BlogCategory', 'FirstCategory');
$this->assertEquals(1, $category->BlogPosts()->count(), 'Category blog post count');
}
public function testCanView() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$this->objFromFixture('Member', 'Admin');
// The first blog can bew viewed by anybody
// $category = $this->objFromFixture("BlogCategory", "firstcategory");
// $this->assertTrue($category->canView($admin), "Admin should be able to view category.");
// $this->assertTrue($category->canView($editor), "Editor should be able to view category.");
$editor = $this->objFromFixture('Member', 'Editor');
$category = $this->objFromFixture('BlogCategory', 'SecondCategory');
$category = $this->objFromFixture("BlogCategory", "secondcategory");
// $this->assertTrue($category->canView($admin), "Admin should be able to view category.");
$this->assertFalse($category->canView($editor), "Editor should not be able to view category.");
$this->assertFalse($category->canView($editor), 'Editor should not be able to view category.');
}
/**
* The first blog can be viewed by anybody.
*/
public function testCanEdit() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$admin = $this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
// The first blog can bew viewed by anybody
$category = $this->objFromFixture("BlogCategory", "firstcategory");
$this->assertTrue($category->canEdit($admin), "Admin should be able to edit category.");
$this->assertTrue($category->canEdit($editor), "Editor should be able to edit category.");
$category = $this->objFromFixture('BlogCategory', 'FirstCategory');
$category = $this->objFromFixture("BlogCategory", "secondcategory");
$this->assertTrue($category->canEdit($admin), "Admin should be able to edit category.");
$this->assertFalse($category->canEdit($editor), "Editor should not be able to edit category.");
$this->assertTrue($category->canEdit($admin), 'Admin should be able to edit category.');
$this->assertTrue($category->canEdit($editor), 'Editor should be able to edit category.');
$category = $this->objFromFixture("BlogCategory", "thirdcategory");
$this->assertTrue($category->canEdit($admin), "Admin should always be able to edit category.");
$this->assertTrue($category->canEdit($editor), "Editor should be able to edit category.");
$category = $this->objFromFixture('BlogCategory', 'SecondCategory');
$this->assertTrue($category->canEdit($admin), 'Admin should be able to edit category.');
$this->assertFalse($category->canEdit($editor), 'Editor should not be able to edit category.');
$category = $this->objFromFixture('BlogCategory', 'ThirdCategory');
$this->assertTrue($category->canEdit($admin), 'Admin should always be able to edit category.');
$this->assertTrue($category->canEdit($editor), 'Editor should be able to edit category.');
}
public function testCanCreate() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$admin = $this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
// The first blog can bew viewed by anybody
$category = singleton('BlogCategory');
$this->assertTrue($category->canCreate($admin), "Admin should be able to create category.");
$this->assertTrue($category->canCreate($editor), "Editor should be able to create category.");
$this->assertTrue($category->canCreate($admin), 'Admin should be able to create category.');
$this->assertTrue($category->canCreate($editor), 'Editor should be able to create category.');
}
public function testCanDelete() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$admin = $this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
// The first blog can bew viewed by anybody
$category = $this->objFromFixture("BlogCategory", "firstcategory");
$this->assertTrue($category->canDelete($admin), "Admin should be able to delete category.");
$this->assertTrue($category->canDelete($editor), "Editor should be able to category category.");
$category = $this->objFromFixture('BlogCategory', 'FirstCategory');
$category = $this->objFromFixture("BlogCategory", "secondcategory");
$this->assertTrue($category->canDelete($admin), "Admin should be able to delete category.");
$this->assertFalse($category->canDelete($editor), "Editor should not be able to delete category.");
$this->assertTrue($category->canDelete($admin), 'Admin should be able to delete category.');
$this->assertTrue($category->canDelete($editor), 'Editor should be able to category category.');
$category = $this->objFromFixture("BlogCategory", "thirdcategory");
$this->assertTrue($category->canDelete($admin), "Admin should always be able to delete category.");
$this->assertTrue($category->canDelete($editor), "Editor should be able to delete category.");
$category = $this->objFromFixture('BlogCategory', 'SecondCategory');
$this->assertTrue($category->canDelete($admin), 'Admin should be able to delete category.');
$this->assertFalse($category->canDelete($editor), 'Editor should not be able to delete category.');
$category = $this->objFromFixture('BlogCategory', 'ThirdCategory');
$this->assertTrue($category->canDelete($admin), 'Admin should always be able to delete category.');
$this->assertTrue($category->canDelete($editor), 'Editor should be able to delete category.');
}
}

View File

@ -1,31 +1,42 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class BlogPostFilterTest extends SapphireTest {
static $fixture_file = "blog.yml";
/**
* @var string
*/
static $fixture_file = 'blog.yml';
public function setUp() {
SS_Datetime::set_mock_now("2013-10-10 20:00:00");
parent::setUp();
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
}
public function tearDown() {
SS_Datetime::clear_mock_now();
parent::tearDown();
}
public function testFilter() {
$member = Member::currentUser();
if($member) $member->logout();
$blog = $this->objFromFixture('Blog', 'firstblog');
if($member) {
$member->logout();
}
$count = $blog->AllChildren()->Count();
$this->assertEquals(3, $count, "Filtered blog posts");
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
SS_Datetime::set_mock_now("2020-01-01 00:00:00");
$count = $blog->AllChildren()->Count();
$this->assertEquals(5, $count, "Unfiltered blog posts");
$this->assertEquals(3, $blog->AllChildren()->Count(), 'Filtered blog posts');
SS_Datetime::set_mock_now('2020-01-01 00:00:00');
$this->assertEquals(5, $blog->AllChildren()->Count(), 'Unfiltered blog posts');
}
}

View File

@ -1,107 +1,126 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class BlogTagTest extends FunctionalTest {
static $fixture_file = "blog.yml";
/**
* @var string
*/
static $fixture_file = 'blog.yml';
/**
* {@inheritdoc}
*/
public function setUp() {
SS_Datetime::set_mock_now("2013-10-10 20:00:00");
parent::setUp();
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
}
/**
* {@inheritdoc}
*/
public function tearDown() {
SS_Datetime::clear_mock_now();
parent::tearDown();
}
/**
* Tests that any blog posts returned from $tag->BlogPosts() many_many are published,
* both by normal 'save & publish' functionality and by publish date.
**/
* Tests that any blog posts returned from $tag->BlogPosts() many_many are published, both by
* normal 'save & publish' functionality and by publish date.
*/
public function testBlogPosts() {
// Ensure the user is not logged in as admin (or anybody)
$member = Member::currentUser();
if($member) $member->logout();
$post = $this->objFromFixture("BlogPost", "blogpost1");
$tag = $this->objFromFixture("BlogTag", "firsttag");
$this->assertEquals(1, $tag->BlogPosts()->count(), "Tag blog post count");
if($member) {
$member->logout();
}
$this->objFromFixture('BlogPost', 'FirstBlogPost');
/**
* @var BlogTag $tag
*/
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$this->assertEquals(1, $tag->BlogPosts()->count(), 'Tag blog post count');
}
/**
* The first blog can be viewed by anybody.
*/
public function testCanView() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$admin = $this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
// The first blog can bew viewed by anybody
$tag = $this->objFromFixture("BlogTag", "firsttag");
$this->assertTrue($tag->canView($admin), "Admin should be able to view tag.");
$this->assertTrue($tag->canView($editor), "Editor should be able to view tag.");
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$tag = $this->objFromFixture("BlogTag", "secondtag");
$this->assertTrue($tag->canView($admin), "Admin should be able to view tag.");
$this->assertFalse($tag->canView($editor), "Editor should not be able to view tag.");
$this->assertTrue($tag->canView($admin), 'Admin should be able to view tag.');
$this->assertTrue($tag->canView($editor), 'Editor should be able to view tag.');
$tag = $this->objFromFixture('BlogTag', 'SecondTag');
$this->assertTrue($tag->canView($admin), 'Admin should be able to view tag.');
$this->assertFalse($tag->canView($editor), 'Editor should not be able to view tag.');
}
public function testCanEdit() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$admin = $this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
// The first blog can bew viewed by anybody
$tag = $this->objFromFixture("BlogTag", "firsttag");
$this->assertTrue($tag->canEdit($admin), "Admin should be able to edit tag.");
$this->assertTrue($tag->canEdit($editor), "Editor should be able to edit tag.");
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$tag = $this->objFromFixture("BlogTag", "secondtag");
$this->assertTrue($tag->canEdit($admin), "Admin should be able to edit tag.");
$this->assertFalse($tag->canEdit($editor), "Editor should not be able to edit tag.");
$this->assertTrue($tag->canEdit($admin), 'Admin should be able to edit tag.');
$this->assertTrue($tag->canEdit($editor), 'Editor should be able to edit tag.');
$tag = $this->objFromFixture("BlogTag", "thirdtag");
$this->assertTrue($tag->canEdit($admin), "Admin should always be able to edit tags.");
$this->assertTrue($tag->canEdit($editor), "Editor should be able to edit tag.");
$tag = $this->objFromFixture('BlogTag', 'SecondTag');
$this->assertTrue($tag->canEdit($admin), 'Admin should be able to edit tag.');
$this->assertFalse($tag->canEdit($editor), 'Editor should not be able to edit tag.');
$tag = $this->objFromFixture('BlogTag', 'ThirdTag');
$this->assertTrue($tag->canEdit($admin), 'Admin should always be able to edit tags.');
$this->assertTrue($tag->canEdit($editor), 'Editor should be able to edit tag.');
}
public function testCanCreate() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$admin = $this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
// The first blog can bew viewed by anybody
$tag = singleton("BlogTag");
$this->assertTrue($tag->canCreate($admin), "Admin should be able to create tag.");
$this->assertTrue($tag->canCreate($editor), "Editor should be able to create tag.");
$tag = singleton('BlogTag');
$this->assertTrue($tag->canCreate($admin), 'Admin should be able to create tag.');
$this->assertTrue($tag->canCreate($editor), 'Editor should be able to create tag.');
}
public function testCanDelete() {
$this->useDraftSite();
$admin = $this->objFromFixture("Member", "admin");
$editor = $this->objFromFixture('Member', 'editor');
$admin = $this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
// The first blog can bew viewed by anybody
$tag = $this->objFromFixture("BlogTag", "firsttag");
$this->assertTrue($tag->canDelete($admin), "Admin should be able to delete tag.");
$this->assertTrue($tag->canDelete($editor), "Editor should be able to delete tag.");
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$tag = $this->objFromFixture("BlogTag", "secondtag");
$this->assertTrue($tag->canDelete($admin), "Admin should be able to delete tag.");
$this->assertFalse($tag->canDelete($editor), "Editor should not be able to delete tag.");
$this->assertTrue($tag->canDelete($admin), 'Admin should be able to delete tag.');
$this->assertTrue($tag->canDelete($editor), 'Editor should be able to delete tag.');
$tag = $this->objFromFixture("BlogTag", "thirdtag");
$this->assertTrue($tag->canDelete($admin), "Admin should always be able to delete tags.");
$this->assertTrue($tag->canDelete($editor), "Editor should be able to delete tag.");
$tag = $this->objFromFixture('BlogTag', 'SecondTag');
$this->assertTrue($tag->canDelete($admin), 'Admin should be able to delete tag.');
$this->assertFalse($tag->canDelete($editor), 'Editor should not be able to delete tag.');
$tag = $this->objFromFixture('BlogTag', 'ThirdTag');
$this->assertTrue($tag->canDelete($admin), 'Admin should always be able to delete tags.');
$this->assertTrue($tag->canDelete($editor), 'Editor should be able to delete tag.');
}
}

View File

@ -1,129 +1,198 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class BlogTest extends SapphireTest {
/**
* @var string
*/
static $fixture_file = 'blog.yml';
static $fixture_file = "blog.yml";
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
Config::nest();
SS_Datetime::set_mock_now("2013-10-10 20:00:00");
$this->objFromFixture("Blog", "firstblog")->publish("Stage", "Live");
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$blog->publish('Stage', 'Live');
}
/**
* {@inheritdoc}
*/
public function tearDown() {
SS_Datetime::clear_mock_now();
Config::unnest();
parent::tearDown();
}
public function testGetExcludedSiteTreeClassNames() {
$member = Member::currentUser();
if($member) $member->logout();
$blog = $this->objFromFixture("Blog", 'firstblog');
if($member) {
$member->logout();
}
Config::inst()->update("BlogPost", "show_in_sitetree", true);
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
Config::inst()->update('BlogPost', 'show_in_sitetree', true);
$classes = $blog->getExcludedSiteTreeClassNames();
$this->assertNotContains('BlogPost', $classes, "BlogPost class should be hidden.");
Config::inst()->update("BlogPost", "show_in_sitetree", false);
$this->assertNotContains('BlogPost', $classes, 'BlogPost class should be hidden.');
Config::inst()->update('BlogPost', 'show_in_sitetree', false);
$classes = $blog->getExcludedSiteTreeClassNames();
$this->assertContains('BlogPost', $classes, "BlogPost class should be hidden.");
$this->assertContains('BlogPost', $classes, 'BlogPost class should be hidden.');
}
public function testGetArchivedBlogPosts() {
$member = Member::currentUser();
if($member) $member->logout();
$blog = $this->objFromFixture("Blog", "firstblog");
if($member) {
$member->logout();
}
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
// Test yearly
$archive = $blog->getArchivedBlogPosts(2013);
$this->assertEquals(2, $archive->count(), "Incorrect Yearly Archive count for 2013");
$this->assertEquals("First post", $archive->first()->Title, "Incorrect First Blog post");
$this->assertEquals("Second post", $archive->last()->Title, "Incorrect Last Blog post");
// Test monthly
$this->assertEquals(2, $archive->count(), 'Incorrect Yearly Archive count for 2013');
$this->assertEquals('First Post', $archive->first()->Title, 'Incorrect First Blog post');
$this->assertEquals('Second Post', $archive->last()->Title, 'Incorrect Last Blog post');
$archive = $blog->getArchivedBlogPosts(2013, 10);
$this->assertEquals(1, $archive->count(), "Incorrect monthly acrhive count.");
// Test daily
$this->assertEquals(1, $archive->count(), 'Incorrect monthly archive count.');
$archive = $blog->getArchivedBlogPosts(2013, 10, 01);
$this->assertEquals(1, $archive->count(), "Incorrect daily archive count.");
$this->assertEquals(1, $archive->count(), 'Incorrect daily archive count.');
}
public function testArchiveLinks() {
$blog = $this->objFromFixture("Blog", "firstblog");
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
// Test valid links
$archiveLink = Controller::join_links($blog->Link("archive"), 2013, 10, 01);
$response = Director::test($archiveLink);
$this->assertEquals(200, $response->getStatusCode(), "HTTP Status should be 200");
$link = Controller::join_links($blog->Link('archive'), '2013', '10', '01');
$archiveLink = Controller::join_links($blog->Link("archive"), 2013, 10);
$response = Director::test($archiveLink);
$this->assertEquals(200, $response->getStatusCode(), "HTTP Status should be 200");
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$archiveLink = Controller::join_links($blog->Link("archive"), 2013);
$response = Director::test($archiveLink);
$this->assertEquals(200, $response->getStatusCode(), "HTTP Status should be 200");
$link = Controller::join_links($blog->Link('archive'), '2013', '10');
$archiveLink = Controller::join_links($blog->Link("archive"), 2011, 10, 01);
$response = Director::test($archiveLink); // No posts on this date, but a valid entry.
$this->assertEquals(200, $response->getStatusCode(), "HTTP Status should be 200");
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$link = Controller::join_links($blog->Link('archive'), '2013');
// Test invalid links & dates
$response = Director::test($blog->Link("archive")); // 404 when no date is set
$this->assertEquals(404, $response->getStatusCode(), "HTTP Status should be 404");
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
// Invalid year
$archiveLink = Controller::join_links($blog->Link("archive"), "invalid-year");
$response = Director::test($archiveLink); // 404 when an invalid yer is set
$this->assertEquals(404, $response->getStatusCode(), "HTTP Status should be 404");
$link = Controller::join_links($blog->Link('archive'), '2011', '10', '01');
// Invalid month
$archiveLink = Controller::join_links($blog->Link("archive"), "2013", "99");
$response = Director::test($archiveLink); // 404 when an invalid month is set
$this->assertEquals(404, $response->getStatusCode(), "HTTP Status should be 404");
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
// Invalid day
$archiveLink = Controller::join_links($blog->Link("archive"), "2013", "10", "99");
$response = Director::test($archiveLink); // 404 when an invalid day is set
$this->assertEquals(404, $response->getStatusCode(), "HTTP Status should be 404");
$link = Controller::join_links($blog->Link('archive'));
$this->assertEquals(404, $this->getStatusOf($link), 'HTTP Status should be 404');
$link = Controller::join_links($blog->Link('archive'), 'invalid-year');
$this->assertEquals(404, $this->getStatusOf($link), 'HTTP Status should be 404');
$link = Controller::join_links($blog->Link('archive'), '2013', '99');
$this->assertEquals(404, $this->getStatusOf($link), 'HTTP Status should be 404');
$link = Controller::join_links($blog->Link('archive'), '2013', '10', '99');
$this->assertEquals(404, $this->getStatusOf($link), 'HTTP Status should be 404');
}
/**
* @param string $link
*
* @return int
*/
protected function getStatusOf($link) {
return Director::test($link)->getStatusCode();
}
public function testRoles() {
$blog = $this->objFromFixture('Blog', 'fourthblog');
$blog2 = $this->objFromFixture('Blog', 'firstblog');
$postA = $this->objFromFixture('BlogPost', 'post-a');
$postB = $this->objFromFixture('BlogPost', 'post-b');
$postC = $this->objFromFixture('BlogPost', 'post-c');
$editor = $this->objFromFixture('Member', 'blogeditor');
$writer = $this->objFromFixture('Member', 'writer');
$contributor = $this->objFromFixture('Member', 'contributor');
$visitor = $this->objFromFixture('Member', 'visitor');
/**
* @var Blog $firstBlog
*/
$firstBlog = $this->objFromFixture('Blog', 'FirstBlog');
// Check roleof
$this->assertEquals('Editor', $blog->RoleOf($editor));
$this->assertEquals('Contributor', $blog->RoleOf($contributor));
$this->assertEquals('Writer', $blog->RoleOf($writer));
$this->assertEmpty($blog->RoleOf($visitor));
/**
* @var Blog $fourthBlog
*/
$fourthBlog = $this->objFromFixture('Blog', 'FourthBlog');
/**
* @var BlogPost $postA
*/
$postA = $this->objFromFixture('BlogPost', 'PostA');
/**
* @var BlogPost $postB
*/
$postB = $this->objFromFixture('BlogPost', 'PostB');
/**
* @var BlogPost $postC
*/
$postC = $this->objFromFixture('BlogPost', 'PostC');
/**
* @var Member $editor
*/
$editor = $this->objFromFixture('Member', 'BlogEditor');
/**
* @var Member $writer
*/
$writer = $this->objFromFixture('Member', 'Writer');
/**
* @var Member $contributor
*/
$contributor = $this->objFromFixture('Member', 'Contributor');
/**
* @var Member $visitor
*/
$visitor = $this->objFromFixture('Member', 'Visitor');
$this->assertEquals('Editor', $fourthBlog->RoleOf($editor));
$this->assertEquals('Contributor', $fourthBlog->RoleOf($contributor));
$this->assertEquals('Writer', $fourthBlog->RoleOf($writer));
$this->assertEmpty($fourthBlog->RoleOf($visitor));
$this->assertEquals('Author', $postA->RoleOf($writer));
$this->assertEquals('Author', $postA->RoleOf($contributor));
$this->assertEquals('Editor', $postA->RoleOf($editor));
$this->assertEmpty($postA->RoleOf($visitor));
// Check that editors have all permissions on their own blog
$this->assertTrue($blog->canEdit($editor));
$this->assertFalse($blog2->canEdit($editor));
$this->assertTrue($blog->canAddChildren($editor));
$this->assertFalse($blog2->canAddChildren($editor));
$this->assertTrue($fourthBlog->canEdit($editor));
$this->assertFalse($firstBlog->canEdit($editor));
$this->assertTrue($fourthBlog->canAddChildren($editor));
$this->assertFalse($firstBlog->canAddChildren($editor));
$this->assertTrue($postA->canEdit($editor));
$this->assertTrue($postB->canEdit($editor));
$this->assertTrue($postC->canEdit($editor));
@ -131,11 +200,10 @@ class BlogTest extends SapphireTest {
$this->assertTrue($postB->canPublish($editor));
$this->assertTrue($postC->canPublish($editor));
// check rights of writers
$this->assertFalse($blog->canEdit($writer));
$this->assertFalse($blog2->canEdit($writer));
$this->assertTrue($blog->canAddChildren($writer));
$this->assertFalse($blog2->canAddChildren($writer));
$this->assertFalse($fourthBlog->canEdit($writer));
$this->assertFalse($firstBlog->canEdit($writer));
$this->assertTrue($fourthBlog->canAddChildren($writer));
$this->assertFalse($firstBlog->canAddChildren($writer));
$this->assertTrue($postA->canEdit($writer));
$this->assertFalse($postB->canEdit($writer));
$this->assertTrue($postC->canEdit($writer));
@ -143,11 +211,10 @@ class BlogTest extends SapphireTest {
$this->assertFalse($postB->canPublish($writer));
$this->assertTrue($postC->canPublish($writer));
// Check rights of contributors
$this->assertFalse($blog->canEdit($contributor));
$this->assertFalse($blog2->canEdit($contributor));
$this->assertTrue($blog->canAddChildren($contributor));
$this->assertFalse($blog2->canAddChildren($contributor));
$this->assertFalse($fourthBlog->canEdit($contributor));
$this->assertFalse($firstBlog->canEdit($contributor));
$this->assertTrue($fourthBlog->canAddChildren($contributor));
$this->assertFalse($firstBlog->canAddChildren($contributor));
$this->assertTrue($postA->canEdit($contributor));
$this->assertFalse($postB->canEdit($contributor));
$this->assertTrue($postC->canEdit($contributor));
@ -155,11 +222,10 @@ class BlogTest extends SapphireTest {
$this->assertFalse($postB->canPublish($contributor));
$this->assertFalse($postC->canPublish($contributor));
// Check rights of non-cms user
$this->assertFalse($blog->canEdit($visitor));
$this->assertFalse($blog2->canEdit($visitor));
$this->assertFalse($blog->canAddChildren($visitor));
$this->assertFalse($blog2->canAddChildren($visitor));
$this->assertFalse($fourthBlog->canEdit($visitor));
$this->assertFalse($firstBlog->canEdit($visitor));
$this->assertFalse($fourthBlog->canAddChildren($visitor));
$this->assertFalse($firstBlog->canAddChildren($visitor));
$this->assertFalse($postA->canEdit($visitor));
$this->assertFalse($postB->canEdit($visitor));
$this->assertFalse($postC->canEdit($visitor));
@ -167,5 +233,4 @@ class BlogTest extends SapphireTest {
$this->assertFalse($postB->canPublish($visitor));
$this->assertFalse($postC->canPublish($visitor));
}
}
}

View File

@ -1,150 +1,148 @@
#####################################################
# Mock date is set to 2013-10-01 20:00:00
#####################################################
Group:
admins:
Administrators:
Title: Administrators
editors:
Editors:
Title: Editors
blog-users:
BlogUsers:
Title: Blog Users
Code: blog-users
Code: BlogUsers
Permission:
admins:
Administrators:
Code: ADMIN
Group: =>Group.admins
editors:
Group: =>Group.Administrators
Editors:
Code: CMS_ACCESS_CMSMain
Group: =>Group.editors
blog-users:
Group: =>Group.Editors
BlogUsers:
Code: CMS_ACCESS_CMSMain
Group: =>Group.blog-users
Group: =>Group.BlogUsers
SiteConfig:
default:
Default:
CanEditType: 'OnlyTheseUsers'
CanCreateTopLevelType: 'OnlyTheseUsers'
EditorGroups: =>Group.admins,=>Group.editors
CreateTopLevelGroups: =>Group.admins,=>Group.editors
EditorGroups: =>Group.Administrators,=>Group.Editors
CreateTopLevelGroups: =>Group.Administrators,=>Group.Editors
Member:
admin:
Admin:
FirstName: Test
Surname: Administrator
Groups: =>Group.admins
editor:
Groups: =>Group.Administrators
Editor:
FirstName: Test
Surname: Editor
Groups: =>Group.editors
blogeditor:
Groups: =>Group.Editors
BlogEditor:
FirstName: Blog
Surname: Editor
Groups: =>Group.blog-users
writer:
Groups: =>Group.BlogUsers
Writer:
FirstName: Blog
Surname: Writer
Groups: =>Group.blog-users
contributor:
Groups: =>Group.BlogUsers
Contributor:
FirstName: Blog
Surname: Contributor
Groups: =>Group.blog-users
visitor:
Groups: =>Group.BlogUsers
Visitor:
FirstName: Blog
Surname: Visitor
Blog:
firstblog:
FirstBlog:
Title: 'First Blog'
secondblog:
SecondBlog:
Title: 'Second Blog'
CanViewType: 'OnlyTheseUsers'
CanEditType: 'OnlyTheseUsers'
ViewerGroups: =>Group.admins
EditorGroups: =>Group.admins
thirdblog:
ViewerGroups: =>Group.Administrators
EditorGroups: =>Group.Administrators
ThirdBlog:
Title: 'Third Blog'
CanEditType: 'OnlyTheseUsers'
EditorGroups: =>Group.editors
fourthblog:
EditorGroups: =>Group.Editors
FourthBlog:
Title: 'Fourth Blog'
Editors: =>Member.blogeditor
Writers: =>Member.writer
Contributors: =>Member.contributor
Editors: =>Member.BlogEditor
Writers: =>Member.Writer
Contributors: =>Member.Contributor
BlogTag:
firsttag:
FirstTag:
Title: 'First Tag'
URLSegment: 'first-tag'
Blog: =>Blog.firstblog
secondtag:
Blog: =>Blog.FirstBlog
SecondTag:
Title: 'Second Tag'
URLSegment: 'second-tag'
Blog: =>Blog.secondblog
thirdtag:
Blog: =>Blog.SecondBlog
ThirdTag:
Title: 'Third Tag'
URLSegment: 'third-tag'
Blog: =>Blog.thirdblog
Blog: =>Blog.ThirdBlog
BlogCategory:
firstcategory:
FirstCategory:
Title: 'First Category'
URLSegment: 'first-category'
Blog: =>Blog.firstblog
secondcategory:
Blog: =>Blog.FirstBlog
SecondCategory:
Title: 'Second Category'
URLSegment: 'second-category'
Blog: =>Blog.secondblog
thirdcategory:
Blog: =>Blog.SecondBlog
ThirdCategory:
Title: 'Third Category'
URLSegment: 'third-category'
Blog: =>Blog.thirdblog
Blog: =>Blog.ThirdBlog
BlogPost:
blogpost1:
Title: 'First post'
FirstBlogPost:
Title: 'First Post'
URLSegment: first-post
PublishDate: '2013-10-01 15:00:00'
Parent: =>Blog.firstblog
Tags: =>BlogTag.firsttag
Categories: =>BlogCategory.firstcategory
blogpost2:
Title: 'Second post'
Parent: =>Blog.FirstBlog
Tags: =>BlogTag.FirstTag
Categories: =>BlogCategory.FirstCategory
SecondBlogPost:
Title: 'Second Post'
URLSegment: second-post
PublishDate: '2013-09-01 15:00:00'
Parent: =>Blog.firstblog
blogpost3:
Title: 'Old post'
Parent: =>Blog.FirstBlog
ThirdBlogPost:
Title: 'Old Post'
URLSegment: old-post
PublishDate: '2012-01-09 15:00:00'
Parent: =>Blog.firstblog
futurepost:
Parent: =>Blog.FirstBlog
FirstFutureBlogPost:
Title: 'Future Post'
URLSegment: future-post
PublishDate: '2015-01-01 00:00:00'
Tags: =>BlogTag.firsttag
Categories: =>BlogCategory.firstcategory
Parent: =>Blog.firstblog
futurepost2:
Tags: =>BlogTag.FirstTag
Categories: =>BlogCategory.FirstCategory
Parent: =>Blog.FirstBlog
SecondFutureBlogPost:
Title: 'Future Post 2'
URLSegment: future-post-2
PublishDate: '2013-11-01 00:00:00'
Tags: =>BlogTag.firsttag
Categories: =>BlogCategory.firstcategory
Parent: =>Blog.firstblog
post-a:
Tags: =>BlogTag.FirstTag
Categories: =>BlogCategory.FirstCategory
Parent: =>Blog.FirstBlog
PostA:
Title: 'One Post'
PublishDate: '2012-01-09 15:00:00'
Parent: =>Blog.fourthblog
Authors: =>Member.writer,=>Member.contributor
post-b:
Parent: =>Blog.FourthBlog
Authors: =>Member.Writer,=>Member.Contributor
PostB:
Title: 'Second Post'
PublishDate: '2012-01-09 15:00:00'
Parent: =>Blog.fourthblog
Authors: =>Member.blogeditor
post-c:
Parent: =>Blog.FourthBlog
Authors: =>Member.BlogEditor
PostC:
Title: 'Third Post'
PublishDate: '2012-01-09 15:00:00'
Parent: =>Blog.fourthblog
Authors: =>Member.blogeditor,=>Member.writer,=>Member.contributor
Parent: =>Blog.FourthBlog
Authors: =>Member.BlogEditor,=>Member.Writer,=>Member.Contributor