Converted to PSR-2

This commit is contained in:
helpfulrobot 2015-11-21 19:17:29 +13:00
parent 4785ad0123
commit f82825d9a6
34 changed files with 4276 additions and 4078 deletions

View File

@ -1,54 +1,57 @@
<?php
class GridFieldCategorisationConfig extends GridFieldConfig_RecordEditor {
/**
* @param int $itemsPerPage
* @param array|SS_List $mergeRecords
* @param string $parentType
* @param string $parentMethod
* @param string $childMethod
*/
public function __construct($itemsPerPage = 15, $mergeRecords, $parentType, $parentMethod, $childMethod) {
parent::__construct($itemsPerPage);
class GridFieldCategorisationConfig extends GridFieldConfig_RecordEditor
{
/**
* @param int $itemsPerPage
* @param array|SS_List $mergeRecords
* @param string $parentType
* @param string $parentMethod
* @param string $childMethod
*/
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')
);
$this->addComponent(
new GridFieldAddByDBField('buttons-before-left')
);
$this->addComponent(
new GridFieldMergeAction($mergeRecords, $parentType, $parentMethod, $childMethod)
);
$this->addComponent(
new GridFieldMergeAction($mergeRecords, $parentType, $parentMethod, $childMethod)
);
/**
* @var GridFieldDataColumns $columns
*/
$columns = $this->getComponentByType('GridFieldDataColumns');
/**
* @var GridFieldDataColumns $columns
*/
$columns = $this->getComponentByType('GridFieldDataColumns');
$columns->setFieldFormatting(array(
'BlogPostsCount' => function ($value, CategorisationObject $item) {
return $item->BlogPosts()->Count();
}
));
$columns->setFieldFormatting(array(
'BlogPostsCount' => function ($value, CategorisationObject $item) {
return $item->BlogPosts()->Count();
}
));
$this->changeColumnOrder();
}
$this->changeColumnOrder();
}
/**
* Reorders GridField columns so that Actions is last.
*/
protected function changeColumnOrder() {
/**
* @var GridFieldDataColumns $columns
*/
$columns = $this->getComponentByType('GridFieldDataColumns');
/**
* Reorders GridField columns so that Actions is last.
*/
protected function changeColumnOrder()
{
/**
* @var GridFieldDataColumns $columns
*/
$columns = $this->getComponentByType('GridFieldDataColumns');
$columns->setDisplayFields(array(
'Title' => 'Title',
'BlogPostsCount' => 'Posts',
'MergeAction' => 'MergeAction',
'Actions' => 'Actions',
));
}
}
$columns->setDisplayFields(array(
'Title' => 'Title',
'BlogPostsCount' => 'Posts',
'MergeAction' => 'MergeAction',
'Actions' => 'Actions',
));
}
}

View File

@ -1,27 +1,30 @@
<?php
class GridFieldFormAction extends GridField_FormAction {
/**
* @var array
*/
protected $extraAttributes = array();
class GridFieldFormAction extends GridField_FormAction
{
/**
* @var array
*/
protected $extraAttributes = array();
/**
* @param array $attributes
*/
public function setExtraAttributes(array $attributes) {
$this->extraAttributes = $attributes;
}
/**
* @param array $attributes
*/
public function setExtraAttributes(array $attributes)
{
$this->extraAttributes = $attributes;
}
/**
* @return array
*/
public function getAttributes() {
$attributes = parent::getAttributes();
/**
* @return array
*/
public function getAttributes()
{
$attributes = parent::getAttributes();
return array_merge(
$attributes,
$this->extraAttributes
);
}
}
return array_merge(
$attributes,
$this->extraAttributes
);
}
}

View File

@ -1,140 +1,149 @@
<?php
class GridFieldMergeAction implements GridField_ColumnProvider, GridField_ActionProvider {
/**
* List of records to show in the MergeAction column.
*
* @var array|SS_List
*/
protected $records;
class GridFieldMergeAction implements GridField_ColumnProvider, GridField_ActionProvider
{
/**
* List of records to show in the MergeAction column.
*
* @var array|SS_List
*/
protected $records;
/**
* Type of parent DataObject (i.e BlogTag, BlogCategory).
*
* @var string
*/
protected $parentType;
/**
* Type of parent DataObject (i.e BlogTag, BlogCategory).
*
* @var string
*/
protected $parentType;
/**
* Relationship method to reference parent (i.e BlogTags).
*
* @var string
*/
protected $parentMethod;
/**
* Relationship method to reference parent (i.e BlogTags).
*
* @var string
*/
protected $parentMethod;
/**
* Relationship method to reference child (i.e BlogPosts).
*
* @var string
*/
protected $childMethod;
/**
* Relationship method to reference child (i.e BlogPosts).
*
* @var string
*/
protected $childMethod;
/**
* @param array|SS_List $records
* @param string $parentType
* @param string $parentMethod
* @param string $childMethod
*/
public function __construct($records = array(), $parentType, $parentMethod, $childMethod) {
$this->records = $records;
$this->parentType = $parentType;
$this->parentMethod = $parentMethod;
$this->childMethod = $childMethod;
}
/**
* @param array|SS_List $records
* @param string $parentType
* @param string $parentMethod
* @param string $childMethod
*/
public function __construct($records = array(), $parentType, $parentMethod, $childMethod)
{
$this->records = $records;
$this->parentType = $parentType;
$this->parentMethod = $parentMethod;
$this->childMethod = $childMethod;
}
/**
* {@inheritdoc}
*/
public function augmentColumns($gridField, &$columns) {
if(!in_array('MergeAction', $columns)) {
$columns[] = 'MergeAction';
}
/**
* {@inheritdoc}
*/
public function augmentColumns($gridField, &$columns)
{
if (!in_array('MergeAction', $columns)) {
$columns[] = 'MergeAction';
}
return $columns;
}
return $columns;
}
/**
* {@inheritdoc}
*/
public function getColumnsHandled($gridField) {
return array('MergeAction');
}
/**
* {@inheritdoc}
*/
public function getColumnsHandled($gridField)
{
return array('MergeAction');
}
/**
* {@inheritdoc}
*/
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());
$dropdown->setAttribute('id', 'Target_'.$record->ID);
$prefix = strtolower($this->parentMethod . '-' . $this->childMethod);
/**
* {@inheritdoc}
*/
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());
$dropdown->setAttribute('id', 'Target_'.$record->ID);
$prefix = strtolower($this->parentMethod . '-' . $this->childMethod);
$action = GridFieldFormAction::create(
$gridField,
'MergeAction' . $record->ID,
'Move',
'merge',
array(
'record' => $record->ID,
'target' => $prefix . '-target-record-' . $record->ID,
)
);
$action = GridFieldFormAction::create(
$gridField,
'MergeAction' . $record->ID,
'Move',
'merge',
array(
'record' => $record->ID,
'target' => $prefix . '-target-record-' . $record->ID,
)
);
$action->setExtraAttributes(array(
'data-target' => $prefix . '-target-record-' . $record->ID
));
$action->setExtraAttributes(array(
'data-target' => $prefix . '-target-record-' . $record->ID
));
return $dropdown->Field() . $action->Field() . '<a title="Move posts to" class="MergeActionReveal">move posts to</a>';
}
return $dropdown->Field() . $action->Field() . '<a title="Move posts to" class="MergeActionReveal">move posts to</a>';
}
return null;
}
return null;
}
/**
* {@inheritdoc}
*/
public function getColumnAttributes($gridField, $record, $columnName) {
return array('class' => 'MergeAction');
}
/**
* {@inheritdoc}
*/
public function getColumnAttributes($gridField, $record, $columnName)
{
return array('class' => 'MergeAction');
}
/**
* {@inheritdoc}
*/
public function getColumnMetadata($gridField, $columnName) {
return array('title' => 'Move posts to');
}
/**
* {@inheritdoc}
*/
public function getColumnMetadata($gridField, $columnName)
{
return array('title' => 'Move posts to');
}
/**
* {@inheritdoc}
*/
public function getActions($gridField) {
return array('merge');
}
/**
* {@inheritdoc}
*/
public function getActions($gridField)
{
return array('merge');
}
/**
* {@inheritdoc}
*/
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName === 'merge') {
$controller = Controller::curr();
/**
* {@inheritdoc}
*/
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
{
if ($actionName === 'merge') {
$controller = Controller::curr();
$request = $controller->getRequest();
$request = $controller->getRequest();
$target = $request->requestVar($arguments["target"]);
$target = $request->requestVar($arguments["target"]);
$parentType = $this->parentType;
$parentType = $this->parentType;
$fromParent = $parentType::get()->byId($arguments['record']);
$toParent = $parentType::get()->byId($target);
$fromParent = $parentType::get()->byId($arguments['record']);
$toParent = $parentType::get()->byId($target);
$posts = $fromParent->{$this->childMethod}();
$posts = $fromParent->{$this->childMethod}();
foreach($posts as $post) {
$relationship = $post->{$this->parentMethod}();
foreach ($posts as $post) {
$relationship = $post->{$this->parentMethod}();
$relationship->remove($fromParent);
$relationship->add($toParent);
}
}
}
$relationship->remove($fromParent);
$relationship->add($toParent);
}
}
}
}

View File

@ -8,105 +8,106 @@
* @property string $PublishDate
* @property string $Tags
*/
class BlogEntry extends BlogPost implements MigratableObject {
/**
* @var string
*/
private static $hide_ancestor = 'BlogEntry';
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',
);
/**
* @var array
*/
private static $db = array(
'Date' => 'SS_Datetime',
'Author' => 'Text',
'Tags' => 'Text',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
return false;
}
/**
* {@inheritdoc}
*/
public function canCreate($member = null)
{
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
//Migrate comma separated tags into BlogTag objects.
foreach($this->TagNames() as $tag) {
$existingTag = BlogTag::get()->filter(array('Title' => $tag, 'BlogID' => $this->ParentID));
if($existingTag->count()) {
//if tag already exists we will simply add it to this post.
$tagObject = $existingTag->First();
} else {
/**
* {@inheritdoc}
*/
public function up()
{
//Migrate comma separated tags into BlogTag objects.
foreach ($this->TagNames() as $tag) {
$existingTag = BlogTag::get()->filter(array('Title' => $tag, 'BlogID' => $this->ParentID));
if ($existingTag->count()) {
//if tag already exists we will simply add it to this post.
$tagObject = $existingTag->First();
} else {
//if the tag is now we create it and add it to this post.
$tagObject = new BlogTag();
$tagObject->Title = $tag;
$tagObject->BlogID = $this->ParentID;
$tagObject->write();
//if the tag is now we create it and add it to this post.
$tagObject = new BlogTag();
$tagObject->Title = $tag;
$tagObject->BlogID = $this->ParentID;
$tagObject->write();
}
}
if ($tagObject) {
$this->Tags()->add($tagObject);
}
}
if($tagObject){
$this->Tags()->add($tagObject);
}
}
//Store if the original entity was published or not (draft)
$published = $this->IsPublished();
// If a user has subclassed BlogEntry, it should not be turned into a BlogPost.
if ($this->ClassName === 'BlogEntry') {
$this->ClassName = 'BlogPost';
$this->RecordClassName = 'BlogPost';
}
//Migrate these key data attributes
$this->PublishDate = $this->Date;
$this->AuthorNames = $this->Author;
$this->InheritSideBar = true;
//Write and additionally publish the item if it was published before.
$this->write();
if ($published) {
$this->publish('Stage', 'Live');
$message = "PUBLISHED: ";
} else {
$message = "DRAFT: ";
}
return $message . $this->Title;
}
//Store if the original entity was published or not (draft)
$published = $this->IsPublished();
// If a user has subclassed BlogEntry, it should not be turned into a BlogPost.
if($this->ClassName === 'BlogEntry') {
$this->ClassName = 'BlogPost';
$this->RecordClassName = 'BlogPost';
}
//Migrate these key data attributes
$this->PublishDate = $this->Date;
$this->AuthorNames = $this->Author;
$this->InheritSideBar = true;
//Write and additionally publish the item if it was published before.
$this->write();
if($published){
$this->publish('Stage','Live');
$message = "PUBLISHED: ";
} else {
$message = "DRAFT: ";
}
return $message . $this->Title;
}
/**
* 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));
/**
* 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();
$results = array();
foreach($tags as $tag) {
if($tag) $results[mb_strtolower($tag)] = $tag;
}
return $results;
}
foreach ($tags as $tag) {
if ($tag) {
$results[mb_strtolower($tag)] = $tag;
}
}
return $results;
}
}
/**
* @deprecated since version 2.0
*/
class BlogEntry_Controller extends BlogPost_Controller {
class BlogEntry_Controller extends BlogPost_Controller
{
}

View File

@ -3,71 +3,75 @@
/**
* @deprecated since version 2.0
*/
class BlogHolder extends BlogTree implements MigratableObject {
/**
* @var string
*/
private static $hide_ancestor = 'BlogHolder';
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 $db = array(
'AllowCustomAuthors' => 'Boolean',
'ShowFullEntry' => 'Boolean',
);
/**
* @var array
*/
private static $has_one = array(
'Owner' => 'Member',
);
/**
* @var array
*/
private static $has_one = array(
'Owner' => 'Member',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
return false;
}
/**
* {@inheritdoc}
*/
public function canCreate($member = null)
{
return false;
}
//Overload these to stop the Uncaught Exception: Object->__call(): the method 'parent' does not exist on 'BlogHolder' error.
public function validURLSegment() {
return true;
}
public function syncLinkTracking() {
return null;
}
//Overload these to stop the Uncaught Exception: Object->__call(): the method 'parent' does not exist on 'BlogHolder' error.
public function validURLSegment()
{
return true;
}
public function syncLinkTracking()
{
return null;
}
/**
* {@inheritdoc}
*/
public function up() {
/**
* {@inheritdoc}
*/
public function up()
{
$published = $this->IsPublished();
$published = $this->IsPublished();
if ($this->ClassName === 'BlogHolder') {
$this->ClassName = 'Blog';
$this->RecordClassName = 'Blog';
$this->PostsPerPage = 10;
$this->write();
}
if($this->ClassName === 'BlogHolder') {
$this->ClassName = 'Blog';
$this->RecordClassName = 'Blog';
$this->PostsPerPage = 10;
$this->write();
}
if($published){
$this->publish('Stage','Live');
$message = "PUBLISHED: ";
} else {
$message = "DRAFT: ";
}
return $message . $this->Title;
}
if ($published) {
$this->publish('Stage', 'Live');
$message = "PUBLISHED: ";
} else {
$message = "DRAFT: ";
}
return $message . $this->Title;
}
}
/**
* @deprecated since version 2.0
*/
class BlogHolder_Controller extends BlogTree_Controller {
class BlogHolder_Controller extends BlogTree_Controller
{
}

View File

@ -3,51 +3,54 @@
/**
* @deprecated since version 2.0
*/
class BlogTree extends Page implements MigratableObject {
/**
* @var string
*/
private static $hide_ancestor = 'BlogTree';
class BlogTree extends Page implements MigratableObject
{
/**
* @var string
*/
private static $hide_ancestor = 'BlogTree';
/**
* @var array
*/
private static $db = array(
'Name' => 'Varchar(255)',
'LandingPageFreshness' => 'Varchar',
);
/**
* @var array
*/
private static $db = array(
'Name' => 'Varchar(255)',
'LandingPageFreshness' => 'Varchar',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
return false;
}
/**
* {@inheritdoc}
*/
public function canCreate($member = null)
{
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
$published = $this->IsPublished();
if($this->ClassName === 'BlogTree') {
$this->ClassName = 'Page';
$this->RecordClassName = 'Page';
$this->write();
}
if($published){
$this->publish('Stage','Live');
$message = "PUBLISHED: ";
} else {
$message = "DRAFT: ";
}
return $message . $this->Title;
}
/**
* {@inheritdoc}
*/
public function up()
{
$published = $this->IsPublished();
if ($this->ClassName === 'BlogTree') {
$this->ClassName = 'Page';
$this->RecordClassName = 'Page';
$this->write();
}
if ($published) {
$this->publish('Stage', 'Live');
$message = "PUBLISHED: ";
} else {
$message = "DRAFT: ";
}
return $message . $this->Title;
}
}
/**
* @deprecated since version 2.0
*/
class BlogTree_Controller extends Page_Controller {
class BlogTree_Controller extends Page_Controller
{
}

View File

@ -1,89 +1,92 @@
<?php
class BlogMigrationTask extends MigrationTask {
/**
* Should this task be invoked automatically via dev/build?
*
* @config
*
* @var bool
*/
private static $run_during_dev_build = true;
class BlogMigrationTask extends MigrationTask
{
/**
* Should this task be invoked automatically via dev/build?
*
* @config
*
* @var bool
*/
private static $run_during_dev_build = true;
/**
* {@inheritdoc}
*/
public function up() {
$classes = ClassInfo::implementorsOf('MigratableObject');
/**
* {@inheritdoc}
*/
public function up()
{
$classes = ClassInfo::implementorsOf('MigratableObject');
$this->message('Migrating legacy blog records');
$this->message('Migrating legacy blog records');
foreach($classes as $class) {
$this->upClass($class);
}
}
foreach ($classes as $class) {
$this->upClass($class);
}
}
/**
* @param string $text
*/
protected function message($text) {
if(Controller::curr() instanceof DatabaseAdmin) {
DB::alteration_message($text, 'obsolete');
} else {
echo $text . "<br/>";
}
}
/**
* @param string $text
*/
protected function message($text)
{
if (Controller::curr() instanceof DatabaseAdmin) {
DB::alteration_message($text, 'obsolete');
} else {
echo $text . "<br/>";
}
}
/**
* Migrate records of a single class
*
* @param string $class
* @param null|string $stage
*/
protected function upClass($class) {
if(!class_exists($class)) {
return;
}
/**
* Migrate records of a single class
*
* @param string $class
* @param null|string $stage
*/
protected function upClass($class)
{
if (!class_exists($class)) {
return;
}
if(is_subclass_of($class, 'SiteTree')) {
$items = SiteTree::get()->filter('ClassName', $class);
} else {
$items = $class::get();
}
if (is_subclass_of($class, 'SiteTree')) {
$items = SiteTree::get()->filter('ClassName', $class);
} else {
$items = $class::get();
}
if($count = $items->count()) {
$this->message(
sprintf(
'Migrating %s legacy %s records.',
$count,
$class
)
);
if ($count = $items->count()) {
$this->message(
sprintf(
'Migrating %s legacy %s records.',
$count,
$class
)
);
foreach($items as $item) {
$cancel = $item->extend('onBeforeUp');
foreach ($items as $item) {
$cancel = $item->extend('onBeforeUp');
if($cancel && min($cancel) === false) {
continue;
}
if ($cancel && min($cancel) === false) {
continue;
}
/**
* @var MigratableObject $item
*/
$result = $item->up();
$this->message($result);
/**
* @var MigratableObject $item
*/
$result = $item->up();
$this->message($result);
$item->extend('onAfterUp');
}
}
}
$item->extend('onAfterUp');
}
}
}
/**
* {@inheritdoc}
*/
public function down() {
$this->message('BlogMigrationTask::down() not implemented');
}
/**
* {@inheritdoc}
*/
public function down()
{
$this->message('BlogMigrationTask::down() not implemented');
}
}

View File

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

View File

@ -1,7 +1,7 @@
<?php
if(!class_exists('Widget')) {
return;
if (!class_exists('Widget')) {
return;
}
/**
@ -10,43 +10,45 @@ if(!class_exists('Widget')) {
* @property string $DisplayMode
* @property string $ArchiveType
*/
class ArchiveWidget extends BlogArchiveWidget implements MigratableObject {
/**
* @var array
*/
private static $db = array(
'DisplayMode' => 'Varchar',
);
class ArchiveWidget extends BlogArchiveWidget implements MigratableObject
{
/**
* @var array
*/
private static $db = array(
'DisplayMode' => 'Varchar',
);
/**
* @var array
*/
private static $only_available_in = array(
'none',
);
/**
* @var array
*/
private static $only_available_in = array(
'none',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
return false;
}
/**
* {@inheritdoc}
*/
public function canCreate($member = null)
{
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
if($this->DisplayMode) {
$this->ArchiveType = 'Monthly';
/**
* {@inheritdoc}
*/
public function up()
{
if ($this->DisplayMode) {
$this->ArchiveType = 'Monthly';
if($this->DisplayMode === 'year') {
$this->ArchiveType = 'Yearly';
}
}
if ($this->DisplayMode === 'year') {
$this->ArchiveType = 'Yearly';
}
}
$this->ClassName = 'BlogArchiveWidget';
$this->write();
return "Migrated " . $this->ArchiveType . " archive widget";
}
$this->ClassName = 'BlogArchiveWidget';
$this->write();
return "Migrated " . $this->ArchiveType . " archive widget";
}
}

View File

@ -1,7 +1,7 @@
<?php
if(!class_exists('Widget')) {
return;
if (!class_exists('Widget')) {
return;
}
/**
@ -9,36 +9,39 @@ if(!class_exists('Widget')) {
*
* @package blog
*/
class TagCloudWidget extends BlogTagsWidget implements MigratableObject {
/**
* @var array
*/
private static $db = array(
'Title' => 'Varchar',
'Limit' => 'Int',
'Sortby' => 'Varchar',
);
class TagCloudWidget extends BlogTagsWidget implements MigratableObject
{
/**
* @var array
*/
private static $db = array(
'Title' => 'Varchar',
'Limit' => 'Int',
'Sortby' => 'Varchar',
);
/**
* @var array
*/
private static $only_available_in = array(
'none',
);
/**
* @var array
*/
private static $only_available_in = array(
'none',
);
/**
* {@inheritdoc}
*/
public function canCreate($member = null) {
return false;
}
/**
* {@inheritdoc}
*/
public function canCreate($member = null)
{
return false;
}
/**
* {@inheritdoc}
*/
public function up() {
$this->ClassName = 'BlogTagsWidget';
$this->write();
return "Migrated " . $this->Title . " widget";
}
/**
* {@inheritdoc}
*/
public function up()
{
$this->ClassName = 'BlogTagsWidget';
$this->write();
return "Migrated " . $this->Title . " widget";
}
}

View File

@ -3,21 +3,23 @@
/**
* 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();
class BlogCommentExtension extends DataExtension
{
/**
* Extra CSS classes for styling different comment types.
*
* @return string
*/
public function getExtraClass()
{
$blogPost = $this->owner->getParent();
if($blogPost instanceof BlogPost) {
if($blogPost->isAuthor($this->owner->Author())) {
return 'author-comment';
}
}
if ($blogPost instanceof BlogPost) {
if ($blogPost->isAuthor($this->owner->Author())) {
return 'author-comment';
}
}
return '';
}
return '';
}
}

View File

@ -1,106 +1,114 @@
<?php
/**
* This class is responsible for filtering the SiteTree when necessary and also overlaps into
* filtering only published posts.
*
* @package silverstripe
* @subpackage blog
*/
class BlogFilter extends Lumberjack {
/**
* {@inheritdoc}
*/
public function stageChildren($showAll = false) {
$staged = parent::stageChildren($showAll);
if(!$this->shouldFilter() && $this->subclassForBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
$stage = Versioned::current_stage();
if($stage == 'Stage') {
$stage = '';
} elseif($stage) {
$stage = '_' . $stage;
}
$dataQuery = $staged->dataQuery()
->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->isBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
$dataQuery = $staged->dataQuery()
->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 = BlogPost::get()->filter(array(
'ParentID' => $this->owner->ID,
'ClassName' => $excluded
));
$gridField = new BlogFilter_GridField(
'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.
*/
class BlogFilter_GridField extends GridField {
/**
* @param FormTransformation $transformation
*
* @return $this
*/
public function transform(FormTransformation $transformation) {
return $this;
}
}
<?php
/**
* This class is responsible for filtering the SiteTree when necessary and also overlaps into
* filtering only published posts.
*
* @package silverstripe
* @subpackage blog
*/
class BlogFilter extends Lumberjack
{
/**
* {@inheritdoc}
*/
public function stageChildren($showAll = false)
{
$staged = parent::stageChildren($showAll);
if (!$this->shouldFilter() && $this->subclassForBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
$stage = Versioned::current_stage();
if ($stage == 'Stage') {
$stage = '';
} elseif ($stage) {
$stage = '_' . $stage;
}
$dataQuery = $staged->dataQuery()
->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->isBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
$dataQuery = $staged->dataQuery()
->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 = BlogPost::get()->filter(array(
'ParentID' => $this->owner->ID,
'ClassName' => $excluded
));
$gridField = new BlogFilter_GridField(
'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.
*/
class BlogFilter_GridField extends GridField
{
/**
* @param FormTransformation $transformation
*
* @return $this
*/
public function transform(FormTransformation $transformation)
{
return $this;
}
}

View File

@ -6,105 +6,110 @@
* @package silverstripe
* @subpackage blog
*/
class BlogMemberExtension extends DataExtension {
/**
* @var array
*/
private static $db = array(
'URLSegment' => 'Varchar',
'BlogProfileSummary' => 'Text',
);
class BlogMemberExtension extends DataExtension
{
/**
* @var array
*/
private static $db = array(
'URLSegment' => 'Varchar',
'BlogProfileSummary' => 'Text',
);
/**
* @var array
*/
private static $has_one = array(
'BlogProfileImage' => 'Image',
);
/**
* @var array
*/
private static $has_one = array(
'BlogProfileImage' => 'Image',
);
/**
* @var array
*/
private static $belongs_many_many = array(
'BlogPosts' => 'BlogPost',
);
/**
* @var array
*/
private static $belongs_many_many = array(
'BlogPosts' => 'BlogPost',
);
/**
* {@inheritdoc}
*/
public function onBeforeWrite() {
$count = 1;
/**
* {@inheritdoc}
*/
public function onBeforeWrite()
{
$count = 1;
$this->owner->URLSegment = $this->generateURLSegment();
$this->owner->URLSegment = $this->generateURLSegment();
while(!$this->validURLSegment()) {
$this->owner->URLSegment = preg_replace('/-[0-9]+$/', null, $this->owner->URLSegment) . '-' . $count;
$count++;
}
}
while (!$this->validURLSegment()) {
$this->owner->URLSegment = preg_replace('/-[0-9]+$/', null, $this->owner->URLSegment) . '-' . $count;
$count++;
}
}
/**
* Generate a unique URL segment based on the Member's name.
*
* @return string
*/
public function generateURLSegment() {
$filter = URLSegmentFilter::create();
$name = $this->owner->FirstName . ' ' . $this->owner->Surname;
$urlSegment = $filter->filter($name);
/**
* Generate a unique URL segment based on the Member's name.
*
* @return string
*/
public function generateURLSegment()
{
$filter = URLSegmentFilter::create();
$name = $this->owner->FirstName . ' ' . $this->owner->Surname;
$urlSegment = $filter->filter($name);
if(!$urlSegment || $urlSegment == '-' || $urlSegment == '-1') {
$urlSegment = 'profile-' . $this->owner->ID;
}
if (!$urlSegment || $urlSegment == '-' || $urlSegment == '-1') {
$urlSegment = 'profile-' . $this->owner->ID;
}
return $urlSegment;
}
return $urlSegment;
}
/**
* Returns TRUE if this object has a URL segment value that does not conflict with any other
* objects.
*
* @return bool
*/
public function validURLSegment() {
$conflict = Member::get()->filter('URLSegment', $this->owner->URLSegment);
/**
* Returns TRUE if this object has a URL segment value that does not conflict with any other
* objects.
*
* @return bool
*/
public function validURLSegment()
{
$conflict = Member::get()->filter('URLSegment', $this->owner->URLSegment);
if($this->owner->ID) {
$conflict = $conflict->exclude('ID', $this->owner->ID);
}
if ($this->owner->ID) {
$conflict = $conflict->exclude('ID', $this->owner->ID);
}
return $conflict->count() == 0;
}
return $conflict->count() == 0;
}
/**
* {@inheritdoc}
*/
public function updateCMSFields(FieldList $fields) {
$fields->removeByName('URLSegment');
/**
* {@inheritdoc}
*/
public function updateCMSFields(FieldList $fields)
{
$fields->removeByName('URLSegment');
// Remove the automatically-generated posts tab.
// Remove the automatically-generated posts tab.
$fields->removeFieldFromTab('Root', 'BlogPosts');
$fields->removeFieldFromTab('Root', 'BlogPosts');
// Construct a better posts tab.
// Construct a better posts tab.
Requirements::css(BLOGGER_DIR . '/css/cms.css');
Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
Requirements::css(BLOGGER_DIR . '/css/cms.css');
Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
$tab = new Tab('BlogPosts', 'Blog Posts');
$tab = new Tab('BlogPosts', 'Blog Posts');
$gridField = new GridField(
'BlogPosts',
'Blog Posts',
$this->owner->BlogPosts(),
new GridFieldConfig_BlogPost()
);
$gridField = new GridField(
'BlogPosts',
'Blog Posts',
$this->owner->BlogPosts(),
new GridFieldConfig_BlogPost()
);
$tab->Fields()->add($gridField);
$tab->Fields()->add($gridField);
$fields->addFieldToTab('Root', $tab);
$fields->addFieldToTab('Root', $tab);
return $fields;
}
return $fields;
}
}

View File

@ -1,42 +1,45 @@
<?php
/**
* This is responsible for filtering only published posts to users who do not have permission to
* view non-published posts.
*
* @package silverstripe
* @subpackage blog
*/
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 (Controller::curr() instanceof LeftAndMain) {
return;
}
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.
*
* @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) {
$dataQuery->innerJoin('BlogPost', '"SiteTree"."ID" = "BlogPost"."ID"');
}
}
<?php
/**
* This is responsible for filtering only published posts to users who do not have permission to
* view non-published posts.
*
* @package silverstripe
* @subpackage blog
*/
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 (Controller::curr() instanceof LeftAndMain) {
return;
}
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.
*
* @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)
{
$dataQuery->innerJoin('BlogPost', '"SiteTree"."ID" = "BlogPost"."ID"');
}
}

View File

@ -5,25 +5,28 @@
*
* Extends {@see BlogPost} with extensions to {@see CommentNotifiable}.
*/
class BlogPostNotifications extends DataExtension {
/**
* Notify all authors of notifications.
*
* @param SS_List $list
* @param mixed $comment
*/
public function updateNotificationRecipients(&$list, &$comment) {
$list = $this->owner->Authors();
}
class BlogPostNotifications extends DataExtension
{
/**
* Notify all authors of notifications.
*
* @param SS_List $list
* @param mixed $comment
*/
public function updateNotificationRecipients(&$list, &$comment)
{
$list = $this->owner->Authors();
}
/**
* Update comment to include the page title.
*
* @param string $subject
* @param Comment $comment
* @param Member|string $recipient
*/
public function updateNotificationSubject(&$subject, &$comment, &$recipient) {
$subject = sprintf('A new comment has been posted on ', $this->owner->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 = sprintf('A new comment has been posted on ', $this->owner->Title);
}
}

View File

@ -6,56 +6,59 @@
* @package silverstripe
* @subpackage blog
*/
class URLSegmentExtension extends DataExtension {
/**
* @var array
*/
private static $db = array(
'URLSegment' => 'Varchar(255)',
);
class URLSegmentExtension extends DataExtension
{
/**
* @var array
*/
private static $db = array(
'URLSegment' => 'Varchar(255)',
);
/**
* {@inheritdoc}
*/
public function onBeforeWrite() {
$this->owner->generateURLSegment();
}
/**
* {@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();
/**
* 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);
$this->owner->URLSegment = $filter->filter($this->owner->Title);
if(is_int($increment)) {
$this->owner->URLSegment .= '-' . $increment;
}
if (is_int($increment)) {
$this->owner->URLSegment .= '-' . $increment;
}
$duplicate = DataList::create($this->owner->ClassName)->filter(array(
'URLSegment' => $this->owner->URLSegment,
'BlogID' => $this->owner->BlogID,
));
$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 ($this->owner->ID) {
$duplicate = $duplicate->exclude('ID', $this->owner->ID);
}
if($duplicate->count() > 0) {
if(is_int($increment)) {
$increment += 1;
} else {
$increment = 0;
}
if ($duplicate->count() > 0) {
if (is_int($increment)) {
$increment += 1;
} else {
$increment = 0;
}
$this->owner->generateURLSegment((int) $increment);
}
$this->owner->generateURLSegment((int) $increment);
}
return $this->owner->URLSegment;
}
return $this->owner->URLSegment;
}
}

View File

@ -1,16 +1,18 @@
<?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;
}
}
<?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

@ -1,193 +1,200 @@
<?php
/**
* Adds a component which allows a user to add a new DataObject by database field.
*
* @package silverstripe
* @subpackage blog
*/
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.
*
* @var string
*/
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 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
*
* @return array
*/
public function getActions($gridField) {
return array(
'add',
);
}
/**
* Handles the add action for the given DataObject.
*
* @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') {
$dbField = $this->getDataObjectField();
$objClass = $gridField->getModelClass();
/**
* @var DataObject $obj
*/
$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'
);
}
} else {
return Security::permissionFailure(
Controller::curr(),
_t(
'GridFieldAddByDBField.PermissionFail',
'You don\'t have permission to create a {class}.',
'Unable to add the DataObject.',
array(
'class' => get_class($obj)
)
)
);
}
} else {
throw new UnexpectedValueException(
sprintf(
'Invalid field (%s) on %s.',
$dbField,
$obj->ClassName
)
);
}
}
return null;
}
/**
* 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) {
/**
* @var DataList $dataList
*/
$dataList = $gridField->getList();
$dataClass = $dataList->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')
);
}
}
<?php
/**
* Adds a component which allows a user to add a new DataObject by database field.
*
* @package silverstripe
* @subpackage blog
*/
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.
*
* @var string
*/
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 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
*
* @return array
*/
public function getActions($gridField)
{
return array(
'add',
);
}
/**
* Handles the add action for the given DataObject.
*
* @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') {
$dbField = $this->getDataObjectField();
$objClass = $gridField->getModelClass();
/**
* @var DataObject $obj
*/
$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'
);
}
} else {
return Security::permissionFailure(
Controller::curr(),
_t(
'GridFieldAddByDBField.PermissionFail',
'You don\'t have permission to create a {class}.',
'Unable to add the DataObject.',
array(
'class' => get_class($obj)
)
)
);
}
} else {
throw new UnexpectedValueException(
sprintf(
'Invalid field (%s) on %s.',
$dbField,
$obj->ClassName
)
);
}
}
return null;
}
/**
* 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)
{
/**
* @var DataList $dataList
*/
$dataList = $gridField->getList();
$dataClass = $dataList->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,94 +1,97 @@
<?php
/**
* 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
*/
class GridFieldBlogPostState extends GridFieldSiteTreeState {
/**
* {@inheritdoc}
*/
public function getColumnContent($gridField, $record, $columnName) {
if($columnName == 'State') {
Requirements::css(BLOGGER_DIR . '/css/cms.css');
if($record instanceof BlogPost) {
$modifiedLabel = '';
if($record->isModifiedOnStage) {
$modifiedLabel = '<span class="modified">' . _t('GridFieldBlogPostState.Modified') . '</span>';
}
if(!$record->isPublished()) {
/**
* @var SS_Datetime $lastEdited
*/
$lastEdited = $record->dbObject('LastEdited');
return _t(
'GridFieldBlogPostState.Draft',
'<i class="btn-icon gridfield-icon btn-icon-pencil"></i> Saved as Draft on {date}',
'State for when a post is saved.',
array(
'date' => $lastEdited->Nice(),
)
);
}
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $record->dbObject('PublishDate');
if(strtotime($record->PublishDate) > time()) {
return _t(
'GridFieldBlogPostState.Timer',
'<i class="gridfield-icon blog-icon-timer"></i> Publish at {date}',
'State for when a post is published.',
array(
'date' => $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' => $publishDate->Nice(),
)
) . $modifiedLabel;
}
}
return '';
}
/**
* {@inheritdoc}
*/
public function getColumnAttributes($gridField, $record, $columnName) {
if($columnName == 'State') {
if($record instanceof BlogPost) {
$published = $record->isPublished();
if(!$published) {
$class = 'gridfield-icon draft';
} else if(strtotime($record->PublishDate) > time()) {
$class = 'gridfield-icon timer';
} else {
$class = 'gridfield-icon published';
}
return array(
'class' => $class,
);
}
}
return array();
}
}
<?php
/**
* 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
*/
class GridFieldBlogPostState extends GridFieldSiteTreeState
{
/**
* {@inheritdoc}
*/
public function getColumnContent($gridField, $record, $columnName)
{
if ($columnName == 'State') {
Requirements::css(BLOGGER_DIR . '/css/cms.css');
if ($record instanceof BlogPost) {
$modifiedLabel = '';
if ($record->isModifiedOnStage) {
$modifiedLabel = '<span class="modified">' . _t('GridFieldBlogPostState.Modified') . '</span>';
}
if (!$record->isPublished()) {
/**
* @var SS_Datetime $lastEdited
*/
$lastEdited = $record->dbObject('LastEdited');
return _t(
'GridFieldBlogPostState.Draft',
'<i class="btn-icon gridfield-icon btn-icon-pencil"></i> Saved as Draft on {date}',
'State for when a post is saved.',
array(
'date' => $lastEdited->Nice(),
)
);
}
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $record->dbObject('PublishDate');
if (strtotime($record->PublishDate) > time()) {
return _t(
'GridFieldBlogPostState.Timer',
'<i class="gridfield-icon blog-icon-timer"></i> Publish at {date}',
'State for when a post is published.',
array(
'date' => $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' => $publishDate->Nice(),
)
) . $modifiedLabel;
}
}
return '';
}
/**
* {@inheritdoc}
*/
public function getColumnAttributes($gridField, $record, $columnName)
{
if ($columnName == 'State') {
if ($record instanceof BlogPost) {
$published = $record->isPublished();
if (!$published) {
$class = 'gridfield-icon draft';
} elseif (strtotime($record->PublishDate) > time()) {
$class = 'gridfield-icon timer';
} else {
$class = 'gridfield-icon published';
}
return array(
'class' => $class,
);
}
}
return array();
}
}

View File

@ -1,19 +1,21 @@
<?php
/**
* GridField config necessary for managing a SiteTree object.
*
* @package silverstripe
* @subpackage blog
*/
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());
}
}
<?php
/**
* GridField config necessary for managing a SiteTree object.
*
* @package silverstripe
* @subpackage blog
*/
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

@ -1,1045 +1,1086 @@
<?php
/**
* Blog Holder
*
* @package silverstripe
* @subpackage blog
*
* @method HasManyList Tags() List of tags in this blog
* @method HasManyList Categories() List of categories in this blog
* @method ManyManyList Editors() List of editors
* @method ManyManyList Writers() List of writers
* @method ManyManyList Contributors() List of contributors
*/
class Blog extends Page implements PermissionProvider {
/**
* 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.
*
* @config
*
* @var boolean
*/
private static $grant_user_access = true;
/**
* Permission to either require, or grant to users assigned to work on this blog.
*
* @config
*
* @var string
*/
private static $grant_user_permission = 'CMS_ACCESS_CMSMain';
/**
* Group code to assign newly granted users to.
*
* @config
*
* @var string
*/
private static $grant_user_group = 'blog-users';
/**
* @var array
*/
private static $db = array(
'PostsPerPage' => 'Int',
);
/**
* @var array
*/
private static $has_many = array(
'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',
);
/**
* @var array
*/
private static $extensions = array(
'BlogFilter',
);
/**
* @var array
*/
private static $defaults = array(
'ProvideComments' => false,
'PostsPerPage' => 10,
);
/**
* @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');
$self =& $this;
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
if(!$self->canEdit()) {
return;
}
$categories = GridField::create(
'Categories',
_t('Blog.Categories', 'Categories'),
$self->Categories(),
GridFieldCategorisationConfig::create(15, $self->Categories()->sort('Title'), 'BlogCategory', 'Categories', 'BlogPosts')
);
$tags = GridField::create(
'Tags',
_t('Blog.Tags', 'Tags'),
$self->Tags(),
GridFieldCategorisationConfig::create(15, $self->Tags()->sort('Title'), 'BlogTag', 'Tags', 'BlogPosts')
);
/**
* @var FieldList $fields
*/
$fields->addFieldsToTab('Root.Categorisation', array(
$categories,
$tags
));
$fields->findOrMakeTab('Root.Categorisation')->addExtraClass('blog-cms-categorisation');
});
return parent::getCMSFields();
}
/**
* {@inheritdoc}
*/
public function canEdit($member = null) {
$member = $this->getMember($member);
if($this->isEditor($member)) {
return true;
}
return parent::canEdit($member);
}
/**
* @param null|int|Member $member
*
* @return null|Member
*/
protected function getMember($member = null) {
if(!$member) {
$member = Member::currentUser();
}
if(is_numeric($member)) {
$member = Member::get()->byID($member);
}
return $member;
}
/**
* Check if this member is an editor of the blog.
*
* @param Member $member
*
* @return bool
*/
public function isEditor($member) {
$isEditor = $this->isMemberOf($member, $this->Editors());
$this->extend('updateIsEditor', $isEditor, $member);
return $isEditor;
}
/**
* Determine if the given member belongs to the given relation.
*
* @param Member $member
* @param DataList $relation
*
* @return bool
*/
protected function isMemberOf($member, $relation) {
if(!$member || !$member->exists()) {
return false;
}
if($relation instanceof UnsavedRelationList) {
return in_array($member->ID, $relation->getIDList());
}
return $relation->byID($member->ID) !== null;
}
/**
* Determine the role of the given member.
*
* Call be called via template to determine the current user.
*
* @example "Hello $RoleOf($CurrentMember.ID)"
*
* @param int|Member $member
*
* @return null|string
*/
public function RoleOf($member) {
if(is_numeric($member)) {
$member = 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 = $this->getMember($member);
if($this->isEditor($member) || $this->isWriter($member) || $this->isContributor($member)) {
return true;
}
return parent::canAddChildren($member);
}
/**
* {@inheritdoc}
*/
public function getSettingsFields() {
$fields = parent::getSettingsFields();
$fields->addFieldToTab('Root.Settings',
NumericField::create('PostsPerPage', _t('Blog.PostsPerPage', 'Posts Per Page'))
);
$members = $this->getCandidateUsers()->map()->toArray();
$editorField = ListboxField::create('Editors', 'Editors', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
->setDescription('
An editor has control over specific Blogs, and all posts included within it. Short of being able to assign other editors to a blog, they are able to handle most changes to their assigned blog.<br />
<br />
Editors have these permissions:<br />
<br />
Update or publish any BlogPost in their Blog<br />
Update or publish their Blog<br />
Assign/unassign writers to their Blog<br />
Assign/unassign contributors to their Blog<br />
Assign/unassign any member as an author of a particular BlogPost
');
if(!$this->canEditEditors()) {
$editorField = $editorField->performDisabledTransformation();
}
$writerField = ListboxField::create('Writers', 'Writers', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
->setDescription('
A writer has full control over creating, editing and publishing BlogPosts they have authored or have been assigned to. Writers are unable to edit BlogPosts to which they are not assigned.<br />
<br />
Writers have these permissions:<br />
<br />
Update or publish any BlogPost they have authored or have been assigned to<br />
Assign/unassign any member as an author of a particular BlogPost they have authored or have been assigned to
');
if(!$this->canEditWriters()) {
$writerField = $writerField->performDisabledTransformation();
}
$contributorField = ListboxField::create('Contributors', 'Contributors', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
->setDescription('
Contributors have the ability to create or edit BlogPosts, but are unable to publish without authorisation of an editor. They are also unable to assign other contributing authors to any of their BlogPosts.<br />
<br />
Contributors have these permissions:<br />
<br />
Update any BlogPost they have authored or have been assigned to
');
if(!$this->canEditContributors()) {
$contributorField = $contributorField->performDisabledTransformation();
}
$fields->addFieldsToTab('Root.Users', array(
$editorField,
$writerField,
$contributorField
));
return $fields;
}
/**
* Gets the list of user candidates to be assigned to assist with this blog.
*
* @return SS_List
*/
protected function getCandidateUsers() {
if($this->config()->grant_user_access) {
$list = Member::get();
$this->extend('updateCandidateUsers', $list);
return $list;
} 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);
}
/**
* Determine if this user can edit writers list.
*
* @param int|Member $member
*
* @return boolean
*/
public function canEditWriters($member = null) {
$member = $this->getMember($member);
$extended = $this->extendedCan('canEditWriters', $member);
if($extended !== null) {
return $extended;
}
if($this->isEditor($member)) {
return true;
}
return Permission::checkMember($member, self::MANAGE_USERS);
}
/**
* Determines if this user can edit the contributors list.
*
* @param int|Member $member
*
* @return boolean
*/
public function canEditContributors($member = null) {
$member = $this->getMember($member);
$extended = $this->extendedCan('canEditContributors', $member);
if($extended !== null) {
return $extended;
}
if($this->isEditor($member)) {
return true;
}
return Permission::checkMember($member, self::MANAGE_USERS);
}
/**
* Returns BlogPosts for a given date period.
*
* @param int $year
* @param null|int $month
* @param null|int $day
*
* @return DataList
*/
public function getArchivedBlogPosts($year, $month = null, $day = null) {
$query = $this->getBlogPosts()->dataQuery();
$stage = $query->getQueryParam('Versioned.stage');
if($stage) {
$stage = '_' . $stage;
}
$query->innerJoin('BlogPost', sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage));
$query->where(sprintf('YEAR("PublishDate") = \'%s\'', Convert::raw2sql($year)));
if($month) {
$query->where(sprintf('MONTH("PublishDate") = \'%s\'', Convert::raw2sql($month)));
if($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 string $urlSegment
*
* @return string
*/
public function ProfileLink($urlSegment) {
return Controller::join_links($this->Link(), 'profile', $urlSegment);
}
/**
* This sets the title for our gridfield.
*
* @return string
*/
public function getLumberjackTitle() {
return _t('Blog.LumberjackTitle', 'Blog Posts');
}
/**
* This overwrites lumberjacks default gridfield config.
*
* @return GridFieldConfig
*/
public function getLumberjackGridFieldConfig() {
return GridFieldConfig_BlogPost::create();
}
/**
* {@inheritdoc}
*/
public function providePermissions() {
return array(
Blog::MANAGE_USERS => array(
'name' => _t(
'Blog.PERMISSION_MANAGE_USERS_DESCRIPTION',
'Manage users for individual blogs'
),
'help' => _t(
'Blog.PERMISSION_MANAGE_USERS_HELP',
'Allow assignment of Editors, Writers, or Contributors to blogs'
),
'category' => _t('Blog.PERMISSIONS_CATEGORY', 'Blog permissions'),
'sort' => 100
)
);
}
/**
* {@inheritdoc}
*/
protected function onBeforeWrite() {
parent::onBeforeWrite();
$this->assignGroup();
}
/**
* Assign users as necessary to the blog group.
*/
protected function assignGroup() {
if(!$this->config()->grant_user_access) {
return;
}
$group = $this->getUserGroup();
// Must check if the method exists or else an error occurs when changing page type
if ($this->hasMethod('Editors')) {
foreach(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;
}
}
/**
* @package silverstripe
* @subpackage blog
*/
class Blog_Controller extends Page_Controller {
/**
* @var array
*/
private static $allowed_actions = array(
'archive',
'tag',
'category',
'rss',
'profile',
);
/**
* @var array
*/
private static $url_handlers = array(
'tag/$Tag!' => 'tag',
'category/$Category!' => 'category',
'archive/$Year!/$Month/$Day' => 'archive',
'profile/$URLSegment!' => 'profile',
);
/**
* @var array
*/
private static $casting = array(
'MetaTitle' => 'Text',
'FilterDescription' => 'Text',
);
/**
* The current Blog Post DataList query.
*
* @var DataList
*/
protected $blogPosts;
/**
* @return string
*/
public function index() {
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$this->blogPosts = $dataRecord->getBlogPosts();
return $this->render();
}
/**
* Renders a Blog Member's profile.
*
* @return SS_HTTPResponse
*/
public function profile() {
$profile = $this->getCurrentProfile();
if(!$profile) {
return $this->httpError(404, 'Not Found');
}
$this->blogPosts = $this->getCurrentProfilePosts();
return $this->render();
}
/**
* Get the Member associated with the current URL segment.
*
* @return null|Member
*/
public function getCurrentProfile() {
$urlSegment = $this->request->param('URLSegment');
if($urlSegment) {
return Member::get()
->filter('URLSegment', $urlSegment)
->first();
}
return null;
}
/**
* Get posts related to the current Member profile.
*
* @return null|DataList
*/
public function getCurrentProfilePosts() {
$profile = $this->getCurrentProfile();
if($profile) {
return $profile->BlogPosts()->filter('ParentID', $this->ID);
}
return null;
}
/**
* Renders an archive for a specified date. This can be by year or year/month.
*
* @return null|SS_HTTPResponse
*/
public function archive() {
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
$day = $this->getArchiveDay();
if($this->request->param('Month') && !$month) {
$this->httpError(404, 'Not Found');
}
if($month && $this->request->param('Day') && !$day) {
$this->httpError(404, 'Not Found');
}
if($year) {
$this->blogPosts = $dataRecord->getArchivedBlogPosts($year, $month, $day);
return $this->render();
}
$this->httpError(404, 'Not Found');
return null;
}
/**
* Fetches the archive year from the url.
*
* @return int
*/
public function getArchiveYear() {
if($this->request->param('Year')){
if(preg_match('/^[0-9]{4}$/', $year = $this->request->param('Year'))) {
return (int) $year;
}
} elseif($this->request->param('Action') == 'archive') {
return SS_Datetime::now()->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 null|SS_HTTPResponse
*/
public function tag() {
$tag = $this->getCurrentTag();
if($tag) {
$this->blogPosts = $tag->BlogPosts();
return $this->render();
}
$this->httpError(404, 'Not Found');
return null;
}
/**
* Tag Getter for use in templates.
*
* @return null|BlogTag
*/
public function getCurrentTag() {
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$tag = $this->request->param('Tag');
if($tag) {
return $dataRecord->Tags()
->filter('URLSegment', array($tag, rawurlencode($tag)))
->first();
}
return null;
}
/**
* Renders the blog posts for a given category.
*
* @return null|SS_HTTPResponse
*/
public function category() {
$category = $this->getCurrentCategory();
if($category) {
$this->blogPosts = $category->BlogPosts();
return $this->render();
}
$this->httpError(404, 'Not Found');
return null;
}
/**
* Category Getter for use in templates.
*
* @return null|BlogCategory
*/
public function getCurrentCategory() {
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$category = $this->request->param('Category');
if($category) {
return $dataRecord->Categories()
->filter('URLSegment', array($category, rawurlencode($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 = sprintf('%s - %s', $title, $filter);
}
$this->extend('updateMetaTitle', $title);
return $title;
}
/**
* Returns a description of the current filter.
*
* @return string
*/
public function getFilterDescription() {
$items = array();
$list = $this->PaginatedList();
$currentPage = $list->CurrentPage();
if($currentPage > 1) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_PAGE',
'Page {page}',
null,
array(
'page' => $currentPage,
)
);
}
if($author = $this->getCurrentProfile()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_AUTHOR',
'By {author}',
null,
array(
'author' => $author->Title,
)
);
}
if($tag = $this->getCurrentTag()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_TAG',
'Tagged with {tag}',
null,
array(
'tag' => $tag->Title,
)
);
}
if($category = $this->getCurrentCategory()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_CATEGORY',
'In category {category}',
null,
array(
'category' => $category->Title,
)
);
}
if($this->owner->getArchiveYear()) {
if($this->owner->getArchiveDay()) {
$date = $this->owner->getArchiveDate()->Nice();
} elseif($this->owner->getArchiveMonth()) {
$date = $this->owner->getArchiveDate()->format('F, Y');
} else {
$date = $this->owner->getArchiveDate()->format('Y');
}
$items[] = _t(
'Blog.FILTERDESCRIPTION_DATE',
'In {date}',
null,
array(
'date' => $date,
)
);
}
$result = '';
if($items) {
$result = implode(', ', $items);
}
$this->extend('updateFilterDescription', $result);
return $result;
}
/**
* Returns a list of paginated blog posts based on the BlogPost dataList.
*
* @return PaginatedList
*/
public function PaginatedList() {
$allPosts = $this->blogPosts ?: new ArrayList();
$posts = new PaginatedList($allPosts);
// Set appropriate page size
if($this->PostsPerPage > 0) {
$pageSize = $this->PostsPerPage;
} elseif($count = $allPosts->count()) {
$pageSize = $count;
} else {
$pageSize = 99999;
}
$posts->setPageLength($pageSize);
// Set current page
$start = $this->request->getVar($posts->getPaginationGetVar());
$posts->setPageStart($start);
return $posts;
}
/**
* Displays an RSS feed of blog posts.
*
* @return string
*/
public function rss() {
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$this->blogPosts = $dataRecord->getBlogPosts();
$rss = new RSSFeed($this->blogPosts, $this->Link(), $this->MetaTitle, $this->MetaDescription);
$this->extend('updateRss', $rss);
return $rss->outputToBrowser();
}
/**
* Returns the current archive date.
*
* @return null|Date
*/
public function getArchiveDate() {
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
$day = $this->getArchiveDay();
if($year) {
if($month) {
$date = sprintf('%s-%s-01', $year, $month);
if($day) {
$date = sprintf('%s-%s-%s', $year, $month, $day);
}
} else {
$date = sprintf('%s-01-01', $year);
}
return DBField::create_field('Date', $date);
}
return null;
}
/**
* Returns a link to the RSS feed.
*
* @return string
*/
public function getRSSLink() {
return $this->Link('rss');
}
}
<?php
/**
* Blog Holder
*
* @package silverstripe
* @subpackage blog
*
* @method HasManyList Tags() List of tags in this blog
* @method HasManyList Categories() List of categories in this blog
* @method ManyManyList Editors() List of editors
* @method ManyManyList Writers() List of writers
* @method ManyManyList Contributors() List of contributors
*/
class Blog extends Page implements PermissionProvider
{
/**
* 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.
*
* @config
*
* @var boolean
*/
private static $grant_user_access = true;
/**
* Permission to either require, or grant to users assigned to work on this blog.
*
* @config
*
* @var string
*/
private static $grant_user_permission = 'CMS_ACCESS_CMSMain';
/**
* Group code to assign newly granted users to.
*
* @config
*
* @var string
*/
private static $grant_user_group = 'blog-users';
/**
* @var array
*/
private static $db = array(
'PostsPerPage' => 'Int',
);
/**
* @var array
*/
private static $has_many = array(
'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',
);
/**
* @var array
*/
private static $extensions = array(
'BlogFilter',
);
/**
* @var array
*/
private static $defaults = array(
'ProvideComments' => false,
'PostsPerPage' => 10,
);
/**
* @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');
$self =& $this;
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
if (!$self->canEdit()) {
return;
}
$categories = GridField::create(
'Categories',
_t('Blog.Categories', 'Categories'),
$self->Categories(),
GridFieldCategorisationConfig::create(15, $self->Categories()->sort('Title'), 'BlogCategory', 'Categories', 'BlogPosts')
);
$tags = GridField::create(
'Tags',
_t('Blog.Tags', 'Tags'),
$self->Tags(),
GridFieldCategorisationConfig::create(15, $self->Tags()->sort('Title'), 'BlogTag', 'Tags', 'BlogPosts')
);
/**
* @var FieldList $fields
*/
$fields->addFieldsToTab('Root.Categorisation', array(
$categories,
$tags
));
$fields->findOrMakeTab('Root.Categorisation')->addExtraClass('blog-cms-categorisation');
});
return parent::getCMSFields();
}
/**
* {@inheritdoc}
*/
public function canEdit($member = null)
{
$member = $this->getMember($member);
if ($this->isEditor($member)) {
return true;
}
return parent::canEdit($member);
}
/**
* @param null|int|Member $member
*
* @return null|Member
*/
protected function getMember($member = null)
{
if (!$member) {
$member = Member::currentUser();
}
if (is_numeric($member)) {
$member = Member::get()->byID($member);
}
return $member;
}
/**
* Check if this member is an editor of the blog.
*
* @param Member $member
*
* @return bool
*/
public function isEditor($member)
{
$isEditor = $this->isMemberOf($member, $this->Editors());
$this->extend('updateIsEditor', $isEditor, $member);
return $isEditor;
}
/**
* Determine if the given member belongs to the given relation.
*
* @param Member $member
* @param DataList $relation
*
* @return bool
*/
protected function isMemberOf($member, $relation)
{
if (!$member || !$member->exists()) {
return false;
}
if ($relation instanceof UnsavedRelationList) {
return in_array($member->ID, $relation->getIDList());
}
return $relation->byID($member->ID) !== null;
}
/**
* Determine the role of the given member.
*
* Call be called via template to determine the current user.
*
* @example "Hello $RoleOf($CurrentMember.ID)"
*
* @param int|Member $member
*
* @return null|string
*/
public function RoleOf($member)
{
if (is_numeric($member)) {
$member = 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 = $this->getMember($member);
if ($this->isEditor($member) || $this->isWriter($member) || $this->isContributor($member)) {
return true;
}
return parent::canAddChildren($member);
}
/**
* {@inheritdoc}
*/
public function getSettingsFields()
{
$fields = parent::getSettingsFields();
$fields->addFieldToTab('Root.Settings',
NumericField::create('PostsPerPage', _t('Blog.PostsPerPage', 'Posts Per Page'))
);
$members = $this->getCandidateUsers()->map()->toArray();
$editorField = ListboxField::create('Editors', 'Editors', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
->setDescription('
An editor has control over specific Blogs, and all posts included within it. Short of being able to assign other editors to a blog, they are able to handle most changes to their assigned blog.<br />
<br />
Editors have these permissions:<br />
<br />
Update or publish any BlogPost in their Blog<br />
Update or publish their Blog<br />
Assign/unassign writers to their Blog<br />
Assign/unassign contributors to their Blog<br />
Assign/unassign any member as an author of a particular BlogPost
');
if (!$this->canEditEditors()) {
$editorField = $editorField->performDisabledTransformation();
}
$writerField = ListboxField::create('Writers', 'Writers', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
->setDescription('
A writer has full control over creating, editing and publishing BlogPosts they have authored or have been assigned to. Writers are unable to edit BlogPosts to which they are not assigned.<br />
<br />
Writers have these permissions:<br />
<br />
Update or publish any BlogPost they have authored or have been assigned to<br />
Assign/unassign any member as an author of a particular BlogPost they have authored or have been assigned to
');
if (!$this->canEditWriters()) {
$writerField = $writerField->performDisabledTransformation();
}
$contributorField = ListboxField::create('Contributors', 'Contributors', $members)
->setMultiple(true)
->setRightTitle('<a class="toggle-description">help</a>')
->setDescription('
Contributors have the ability to create or edit BlogPosts, but are unable to publish without authorisation of an editor. They are also unable to assign other contributing authors to any of their BlogPosts.<br />
<br />
Contributors have these permissions:<br />
<br />
Update any BlogPost they have authored or have been assigned to
');
if (!$this->canEditContributors()) {
$contributorField = $contributorField->performDisabledTransformation();
}
$fields->addFieldsToTab('Root.Users', array(
$editorField,
$writerField,
$contributorField
));
return $fields;
}
/**
* Gets the list of user candidates to be assigned to assist with this blog.
*
* @return SS_List
*/
protected function getCandidateUsers()
{
if ($this->config()->grant_user_access) {
$list = Member::get();
$this->extend('updateCandidateUsers', $list);
return $list;
} 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);
}
/**
* Determine if this user can edit writers list.
*
* @param int|Member $member
*
* @return boolean
*/
public function canEditWriters($member = null)
{
$member = $this->getMember($member);
$extended = $this->extendedCan('canEditWriters', $member);
if ($extended !== null) {
return $extended;
}
if ($this->isEditor($member)) {
return true;
}
return Permission::checkMember($member, self::MANAGE_USERS);
}
/**
* Determines if this user can edit the contributors list.
*
* @param int|Member $member
*
* @return boolean
*/
public function canEditContributors($member = null)
{
$member = $this->getMember($member);
$extended = $this->extendedCan('canEditContributors', $member);
if ($extended !== null) {
return $extended;
}
if ($this->isEditor($member)) {
return true;
}
return Permission::checkMember($member, self::MANAGE_USERS);
}
/**
* Returns BlogPosts for a given date period.
*
* @param int $year
* @param null|int $month
* @param null|int $day
*
* @return DataList
*/
public function getArchivedBlogPosts($year, $month = null, $day = null)
{
$query = $this->getBlogPosts()->dataQuery();
$stage = $query->getQueryParam('Versioned.stage');
if ($stage) {
$stage = '_' . $stage;
}
$query->innerJoin('BlogPost', sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage));
$query->where(sprintf('YEAR("PublishDate") = \'%s\'', Convert::raw2sql($year)));
if ($month) {
$query->where(sprintf('MONTH("PublishDate") = \'%s\'', Convert::raw2sql($month)));
if ($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 string $urlSegment
*
* @return string
*/
public function ProfileLink($urlSegment)
{
return Controller::join_links($this->Link(), 'profile', $urlSegment);
}
/**
* This sets the title for our gridfield.
*
* @return string
*/
public function getLumberjackTitle()
{
return _t('Blog.LumberjackTitle', 'Blog Posts');
}
/**
* This overwrites lumberjacks default gridfield config.
*
* @return GridFieldConfig
*/
public function getLumberjackGridFieldConfig()
{
return GridFieldConfig_BlogPost::create();
}
/**
* {@inheritdoc}
*/
public function providePermissions()
{
return array(
Blog::MANAGE_USERS => array(
'name' => _t(
'Blog.PERMISSION_MANAGE_USERS_DESCRIPTION',
'Manage users for individual blogs'
),
'help' => _t(
'Blog.PERMISSION_MANAGE_USERS_HELP',
'Allow assignment of Editors, Writers, or Contributors to blogs'
),
'category' => _t('Blog.PERMISSIONS_CATEGORY', 'Blog permissions'),
'sort' => 100
)
);
}
/**
* {@inheritdoc}
*/
protected function onBeforeWrite()
{
parent::onBeforeWrite();
$this->assignGroup();
}
/**
* Assign users as necessary to the blog group.
*/
protected function assignGroup()
{
if (!$this->config()->grant_user_access) {
return;
}
$group = $this->getUserGroup();
// Must check if the method exists or else an error occurs when changing page type
if ($this->hasMethod('Editors')) {
foreach (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;
}
}
/**
* @package silverstripe
* @subpackage blog
*/
class Blog_Controller extends Page_Controller
{
/**
* @var array
*/
private static $allowed_actions = array(
'archive',
'tag',
'category',
'rss',
'profile',
);
/**
* @var array
*/
private static $url_handlers = array(
'tag/$Tag!' => 'tag',
'category/$Category!' => 'category',
'archive/$Year!/$Month/$Day' => 'archive',
'profile/$URLSegment!' => 'profile',
);
/**
* @var array
*/
private static $casting = array(
'MetaTitle' => 'Text',
'FilterDescription' => 'Text',
);
/**
* The current Blog Post DataList query.
*
* @var DataList
*/
protected $blogPosts;
/**
* @return string
*/
public function index()
{
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$this->blogPosts = $dataRecord->getBlogPosts();
return $this->render();
}
/**
* Renders a Blog Member's profile.
*
* @return SS_HTTPResponse
*/
public function profile()
{
$profile = $this->getCurrentProfile();
if (!$profile) {
return $this->httpError(404, 'Not Found');
}
$this->blogPosts = $this->getCurrentProfilePosts();
return $this->render();
}
/**
* Get the Member associated with the current URL segment.
*
* @return null|Member
*/
public function getCurrentProfile()
{
$urlSegment = $this->request->param('URLSegment');
if ($urlSegment) {
return Member::get()
->filter('URLSegment', $urlSegment)
->first();
}
return null;
}
/**
* Get posts related to the current Member profile.
*
* @return null|DataList
*/
public function getCurrentProfilePosts()
{
$profile = $this->getCurrentProfile();
if ($profile) {
return $profile->BlogPosts()->filter('ParentID', $this->ID);
}
return null;
}
/**
* Renders an archive for a specified date. This can be by year or year/month.
*
* @return null|SS_HTTPResponse
*/
public function archive()
{
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
$day = $this->getArchiveDay();
if ($this->request->param('Month') && !$month) {
$this->httpError(404, 'Not Found');
}
if ($month && $this->request->param('Day') && !$day) {
$this->httpError(404, 'Not Found');
}
if ($year) {
$this->blogPosts = $dataRecord->getArchivedBlogPosts($year, $month, $day);
return $this->render();
}
$this->httpError(404, 'Not Found');
return null;
}
/**
* Fetches the archive year from the url.
*
* @return int
*/
public function getArchiveYear()
{
if ($this->request->param('Year')) {
if (preg_match('/^[0-9]{4}$/', $year = $this->request->param('Year'))) {
return (int) $year;
}
} elseif ($this->request->param('Action') == 'archive') {
return SS_Datetime::now()->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 null|SS_HTTPResponse
*/
public function tag()
{
$tag = $this->getCurrentTag();
if ($tag) {
$this->blogPosts = $tag->BlogPosts();
return $this->render();
}
$this->httpError(404, 'Not Found');
return null;
}
/**
* Tag Getter for use in templates.
*
* @return null|BlogTag
*/
public function getCurrentTag()
{
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$tag = $this->request->param('Tag');
if ($tag) {
return $dataRecord->Tags()
->filter('URLSegment', array($tag, rawurlencode($tag)))
->first();
}
return null;
}
/**
* Renders the blog posts for a given category.
*
* @return null|SS_HTTPResponse
*/
public function category()
{
$category = $this->getCurrentCategory();
if ($category) {
$this->blogPosts = $category->BlogPosts();
return $this->render();
}
$this->httpError(404, 'Not Found');
return null;
}
/**
* Category Getter for use in templates.
*
* @return null|BlogCategory
*/
public function getCurrentCategory()
{
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$category = $this->request->param('Category');
if ($category) {
return $dataRecord->Categories()
->filter('URLSegment', array($category, rawurlencode($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 = sprintf('%s - %s', $title, $filter);
}
$this->extend('updateMetaTitle', $title);
return $title;
}
/**
* Returns a description of the current filter.
*
* @return string
*/
public function getFilterDescription()
{
$items = array();
$list = $this->PaginatedList();
$currentPage = $list->CurrentPage();
if ($currentPage > 1) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_PAGE',
'Page {page}',
null,
array(
'page' => $currentPage,
)
);
}
if ($author = $this->getCurrentProfile()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_AUTHOR',
'By {author}',
null,
array(
'author' => $author->Title,
)
);
}
if ($tag = $this->getCurrentTag()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_TAG',
'Tagged with {tag}',
null,
array(
'tag' => $tag->Title,
)
);
}
if ($category = $this->getCurrentCategory()) {
$items[] = _t(
'Blog.FILTERDESCRIPTION_CATEGORY',
'In category {category}',
null,
array(
'category' => $category->Title,
)
);
}
if ($this->owner->getArchiveYear()) {
if ($this->owner->getArchiveDay()) {
$date = $this->owner->getArchiveDate()->Nice();
} elseif ($this->owner->getArchiveMonth()) {
$date = $this->owner->getArchiveDate()->format('F, Y');
} else {
$date = $this->owner->getArchiveDate()->format('Y');
}
$items[] = _t(
'Blog.FILTERDESCRIPTION_DATE',
'In {date}',
null,
array(
'date' => $date,
)
);
}
$result = '';
if ($items) {
$result = implode(', ', $items);
}
$this->extend('updateFilterDescription', $result);
return $result;
}
/**
* Returns a list of paginated blog posts based on the BlogPost dataList.
*
* @return PaginatedList
*/
public function PaginatedList()
{
$allPosts = $this->blogPosts ?: new ArrayList();
$posts = new PaginatedList($allPosts);
// Set appropriate page size
if ($this->PostsPerPage > 0) {
$pageSize = $this->PostsPerPage;
} elseif ($count = $allPosts->count()) {
$pageSize = $count;
} else {
$pageSize = 99999;
}
$posts->setPageLength($pageSize);
// Set current page
$start = $this->request->getVar($posts->getPaginationGetVar());
$posts->setPageStart($start);
return $posts;
}
/**
* Displays an RSS feed of blog posts.
*
* @return string
*/
public function rss()
{
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$this->blogPosts = $dataRecord->getBlogPosts();
$rss = new RSSFeed($this->blogPosts, $this->Link(), $this->MetaTitle, $this->MetaDescription);
$this->extend('updateRss', $rss);
return $rss->outputToBrowser();
}
/**
* Returns the current archive date.
*
* @return null|Date
*/
public function getArchiveDate()
{
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
$day = $this->getArchiveDay();
if ($year) {
if ($month) {
$date = sprintf('%s-%s-01', $year, $month);
if ($day) {
$date = sprintf('%s-%s-%s', $year, $month, $day);
}
} else {
$date = sprintf('%s-01-01', $year);
}
return DBField::create_field('Date', $date);
}
return null;
}
/**
* Returns a link to the RSS feed.
*
* @return string
*/
public function getRSSLink()
{
return $this->Link('rss');
}
}

View File

@ -1,145 +1,153 @@
<?php
/**
* A blog category for generalising blog posts.
*
* @package silverstripe
* @subpackage blog
*
* @method Blog Blog()
*
* @property string $URLSegment
* @property int $BlogID
*/
class BlogCategory 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',
);
/**
* @return DataList
*/
public function BlogPosts() {
$blogPosts = parent::BlogPosts();
$this->extend("updateGetBlogPosts", $blogPosts);
return $blogPosts;
}
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$fields = new FieldList(
TextField::create('Title', _t('BlogCategory.Title', 'Title'))
);
$this->extend('updateCMSFields', $fields);
return $fields;
}
/**
* Returns a relative link to this category.
*
* @return string
*/
public function getLink() {
return Controller::join_links($this->Blog()->Link(), 'category', $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);
}
}
<?php
/**
* A blog category for generalising blog posts.
*
* @package silverstripe
* @subpackage blog
*
* @method Blog Blog()
*
* @property string $URLSegment
* @property int $BlogID
*/
class BlogCategory 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',
);
/**
* @return DataList
*/
public function BlogPosts()
{
$blogPosts = parent::BlogPosts();
$this->extend("updateGetBlogPosts", $blogPosts);
return $blogPosts;
}
/**
* {@inheritdoc}
*/
public function getCMSFields()
{
$fields = new FieldList(
TextField::create('Title', _t('BlogCategory.Title', 'Title'))
);
$this->extend('updateCMSFields', $fields);
return $fields;
}
/**
* Returns a relative link to this category.
*
* @return string
*/
public function getLink()
{
return Controller::join_links($this->Blog()->Link(), 'category', $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

@ -1,686 +1,707 @@
<?php
/**
* An individual blog post.
*
* @package silverstripe
* @subpackage blog
*
* @method ManyManyList Categories()
* @method ManyManyList Tags()
* @method ManyManyList Authors()
* @method Blog Parent()
*
* @property string $PublishDate
* @property string $AuthorNames
* @property int $ParentID
*/
class BlogPost extends Page {
/**
* Same as above, but for list of users that can be
* given credit in the author field for blog posts
* @var string|bool false or group code
*/
private static $restrict_authors_to_group = false;
/**
* @var array
*/
private static $db = array(
'PublishDate' => 'SS_Datetime',
'AuthorNames' => 'Varchar(1024)',
'Summary' => 'HTMLText',
);
/**
* @var array
*/
private static $has_one = array(
'FeaturedImage' => 'Image',
);
/**
* @var array
*/
private static $many_many = array(
'Categories' => 'BlogCategory',
'Tags' => 'BlogTag',
'Authors' => 'Member',
);
/**
* @var array
*/
private static $defaults = array(
'ShowInMenus' => false,
'InheritSideBar' => true,
'ProvideComments' => true,
);
/**
* @var array
*/
private static $extensions = array(
'BlogPostFilter',
);
/**
* @var array
*/
private static $searchable_fields = array(
'Title',
);
/**
* @var array
*/
private static $summary_fields = array(
'Title',
);
/**
* @var array
*/
private static $casting = array(
'Excerpt' => 'Text',
);
/**
* @var array
*/
private static $allowed_children = array();
/**
* The default sorting lists BlogPosts with an empty PublishDate at the top.
*
* @var string
*/
private static $default_sort = '"PublishDate" IS NULL DESC, "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.
*
* @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) {
$member = $this->getMember($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.
*
* @param null|Member $member
*
* @return bool
*/
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());
}
return $list->byID($member->ID) !== null;
}
/**
* {@inheritdoc}
*/
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) {
$uploadField = UploadField::create('FeaturedImage', _t('BlogPost.FeaturedImage', 'Banner Image'));
$uploadField->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif'));
/**
* @var FieldList $fields
*/
$fields->insertAfter($uploadField, 'Content');
$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,
)
);
$summaryHolder->setHeadingLevel(4);
$summaryHolder->addExtraClass('custom-summary');
$fields->insertAfter($summaryHolder, 'FeaturedImage');
$fields->push(HiddenField::create('MenuTitle'));
$urlSegment = $fields->dataFieldByName('URLSegment');
$urlSegment->setURLPrefix($self->Parent()->RelativeLink());
$fields->removeFieldsFromTab('Root.Main', array(
'MenuTitle',
'URLSegment',
));
$authorField = ListboxField::create(
'Authors',
_t('BlogPost.Authors', 'Authors'),
$this->getCandidateAuthors()->map()->toArray()
)->setMultiple(true);
$authorNames = TextField::create(
'AuthorNames',
_t('BlogPost.AdditionalCredits', 'Additional Credits'),
null,
1024
)->setDescription(_t(
'BlogPost.AdditionalCredits_Description',
'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();
}
$publishDate = DatetimeField::create('PublishDate', _t('BlogPost.PublishDate', 'Publish Date'));
$publishDate->getDateField()->setConfig('showcalendar', true);
if(!$self->PublishDate) {
$publishDate->setDescription(_t(
'BlogPost.PublishDate_Description',
'Will be set to "now" if published without a value.')
);
}
// Get categories and tags
$parent = $self->Parent();
$categories = $parent instanceof Blog
? $parent->Categories()
: BlogCategory::get();
$tags = $parent instanceof Blog
? $parent->Tags()
: BlogTag::get();
$options = BlogAdminSidebar::create(
$publishDate,
$urlSegment,
TagField::create(
'Categories',
_t('BlogPost.Categories', 'Categories'),
$categories,
$self->Categories()
)
->setCanCreate($self->canCreateCategories())
->setShouldLazyLoad(true),
TagField::create(
'Tags',
_t('BlogPost.Tags', 'Tags'),
$tags,
$self->Tags()
)
->setCanCreate($self->canCreateTags())
->setShouldLazyLoad(true),
$authorField,
$authorNames
)->setTitle('Post Options');
$options->setName('blog-admin-sidebar');
$fields->insertBefore($options, 'Root');
});
$fields = parent::getCMSFields();
$fields->fieldByName('Root')->setTemplate('TabSet_holder');
return $fields;
}
/**
* Gets the list of author candidates to be assigned as authors of this blog post.
*
* @return SS_List
*/
public function getCandidateAuthors() {
if($this->config()->restrict_authors_to_group) {
return Group::get()->filter('Code', $this->config()->restrict_authors_to_group)->first()->Members();
} else {
$list = Member::get();
$this->extend('updateCandidateAuthors', $list);
return $list;
}
}
/**
* 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_numeric($member)) {
$member = Member::get()->byID($member);
}
return $member;
}
/**
* Determine whether user can create new categories.
*
* @param null|int|Member $member
*
* @return bool
*/
public function canCreateCategories($member = null) {
$member = $this->getMember($member);
$parent = $this->Parent();
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) {
return false;
}
if($parent->isEditor($member)) {
return true;
}
return Permission::checkMember($member, 'ADMIN');
}
/**
* Determine whether user can create new tags.
*
* @param null|int|Member $member
*
* @return bool
*/
public function canCreateTags($member = null) {
$member = $this->getMember($member);
$parent = $this->Parent();
if(!$parent || !$parent->exists() || !($parent instanceof Blog)) {
return false;
}
if($parent->isEditor($member)) {
return true;
}
if($parent->isWriter($member)) {
return true;
}
return Permission::checkMember($member, 'ADMIN');
}
/**
* {@inheritdoc}
*
* Update the PublishDate to now if the BlogPost would otherwise be published without a date.
*/
public function onBeforePublish() {
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
if(!$publishDate->getValue()) {
$this->PublishDate = SS_Datetime::now()->getValue();
$this->write();
}
}
/**
* {@inheritdoc}
*
* Sets blog relationship on all categories and tags assigned to this post.
*/
public function onAfterWrite() {
parent::onAfterWrite();
foreach($this->Categories() as $category) {
/**
* @var BlogCategory $category
*/
$category->BlogID = $this->ParentID;
$category->write();
}
foreach($this->Tags() as $tag) {
/**
* @var BlogTag $tag
*/
$tag->BlogID = $this->ParentID;
$tag->write();
}
}
/**
* {@inheritdoc}
*/
public function canView($member = null) {
$member = $this->getMember($member);
if(!parent::canView($member)) {
return false;
}
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
// Show past posts
if(!$publishDate->exists() || !$publishDate->InFuture()) {
return true;
}
// Anyone that can edit this page can view it
return $this->canEdit($member);
}
/**
* {@inheritdoc}
*/
public function canPublish($member = null) {
$member = $this->getMember($member);
if(Permission::checkMember($member, 'ADMIN')) {
return true;
}
$extended = $this->extendedCan('canPublish', $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;
}
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;
}
return $this->isAuthor($member);
}
/**
* Returns the post excerpt.
*
* @param int $wordsToDisplay
*
* @return string
*/
public function Excerpt($wordsToDisplay = 30) {
/**
* @var Text $content
*/
$content = $this->dbObject('Content');
return $content->Summary($wordsToDisplay);
}
/**
* Returns a monthly archive link for the current blog post.
*
* @param string $type
*
* @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')
);
}
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'));
}
/**
* Returns a yearly archive link for the current blog post.
*
* @return string
*/
public function getYearlyArchiveLink() {
/**
* @var SS_Datetime $date
*/
$date = $this->dbObject('PublishDate');
return Controller::join_links($this->Parent()->Link('archive'), $date->format('Y'));
}
/**
* Resolves static and dynamic authors linked to this post.
*
* @return ArrayList
*/
public function getCredits() {
$list = new ArrayList();
$list->merge($this->getDynamicCredits());
$list->merge($this->getStaticCredits());
return $list->sort('Name');
}
/**
* Resolves dynamic authors linked to this post.
*
* @return ArrayList
*/
protected function getDynamicCredits() {
// Find best page to host user profiles
$parent = $this->Parent();
if(! ($parent instanceof Blog) ) {
$parent = Blog::get()->first();
}
// If there is no parent blog, return list undecorated
if(!$parent) {
$items = $this->Authors()->toArray();
return new ArrayList($items);
}
// Update all authors
$items = new ArrayList();
foreach($this->Authors() as $author) {
// Add link for each author
$author = $author->customise(array(
'URL' => $parent->ProfileLink($author->URLSegment),
));
$items->push($author);
}
return $items;
}
/**
* Resolves static authors linked to this post.
*
* @return ArrayList
*/
protected function getStaticCredits() {
$items = new ArrayList();
$authors = array_filter(preg_split('/\s*,\s*/', $this->AuthorNames));
foreach($authors as $author) {
$item = new ArrayData(array(
'Name' => $author,
));
$items->push($item);
}
return $items;
}
/**
* 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');
return $labels;
}
/**
* {@inheritdoc}
*/
protected function onBeforeWrite() {
parent::onBeforeWrite();
if(!$this->exists() && ($member = Member::currentUser())) {
$this->Authors()->add($member);
}
}
}
/**
* @package silverstripe
* @subpackage blog
*/
class BlogPost_Controller extends Page_Controller {
}
<?php
/**
* An individual blog post.
*
* @package silverstripe
* @subpackage blog
*
* @method ManyManyList Categories()
* @method ManyManyList Tags()
* @method ManyManyList Authors()
* @method Blog Parent()
*
* @property string $PublishDate
* @property string $AuthorNames
* @property int $ParentID
*/
class BlogPost extends Page
{
/**
* Same as above, but for list of users that can be
* given credit in the author field for blog posts
* @var string|bool false or group code
*/
private static $restrict_authors_to_group = false;
/**
* @var array
*/
private static $db = array(
'PublishDate' => 'SS_Datetime',
'AuthorNames' => 'Varchar(1024)',
'Summary' => 'HTMLText',
);
/**
* @var array
*/
private static $has_one = array(
'FeaturedImage' => 'Image',
);
/**
* @var array
*/
private static $many_many = array(
'Categories' => 'BlogCategory',
'Tags' => 'BlogTag',
'Authors' => 'Member',
);
/**
* @var array
*/
private static $defaults = array(
'ShowInMenus' => false,
'InheritSideBar' => true,
'ProvideComments' => true,
);
/**
* @var array
*/
private static $extensions = array(
'BlogPostFilter',
);
/**
* @var array
*/
private static $searchable_fields = array(
'Title',
);
/**
* @var array
*/
private static $summary_fields = array(
'Title',
);
/**
* @var array
*/
private static $casting = array(
'Excerpt' => 'Text',
);
/**
* @var array
*/
private static $allowed_children = array();
/**
* The default sorting lists BlogPosts with an empty PublishDate at the top.
*
* @var string
*/
private static $default_sort = '"PublishDate" IS NULL DESC, "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.
*
* @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)
{
$member = $this->getMember($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.
*
* @param null|Member $member
*
* @return bool
*/
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());
}
return $list->byID($member->ID) !== null;
}
/**
* {@inheritdoc}
*/
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) {
$uploadField = UploadField::create('FeaturedImage', _t('BlogPost.FeaturedImage', 'Banner Image'));
$uploadField->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif'));
/**
* @var FieldList $fields
*/
$fields->insertAfter($uploadField, 'Content');
$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,
)
);
$summaryHolder->setHeadingLevel(4);
$summaryHolder->addExtraClass('custom-summary');
$fields->insertAfter($summaryHolder, 'FeaturedImage');
$fields->push(HiddenField::create('MenuTitle'));
$urlSegment = $fields->dataFieldByName('URLSegment');
$urlSegment->setURLPrefix($self->Parent()->RelativeLink());
$fields->removeFieldsFromTab('Root.Main', array(
'MenuTitle',
'URLSegment',
));
$authorField = ListboxField::create(
'Authors',
_t('BlogPost.Authors', 'Authors'),
$this->getCandidateAuthors()->map()->toArray()
)->setMultiple(true);
$authorNames = TextField::create(
'AuthorNames',
_t('BlogPost.AdditionalCredits', 'Additional Credits'),
null,
1024
)->setDescription(_t(
'BlogPost.AdditionalCredits_Description',
'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();
}
$publishDate = DatetimeField::create('PublishDate', _t('BlogPost.PublishDate', 'Publish Date'));
$publishDate->getDateField()->setConfig('showcalendar', true);
if (!$self->PublishDate) {
$publishDate->setDescription(_t(
'BlogPost.PublishDate_Description',
'Will be set to "now" if published without a value.')
);
}
// Get categories and tags
$parent = $self->Parent();
$categories = $parent instanceof Blog
? $parent->Categories()
: BlogCategory::get();
$tags = $parent instanceof Blog
? $parent->Tags()
: BlogTag::get();
$options = BlogAdminSidebar::create(
$publishDate,
$urlSegment,
TagField::create(
'Categories',
_t('BlogPost.Categories', 'Categories'),
$categories,
$self->Categories()
)
->setCanCreate($self->canCreateCategories())
->setShouldLazyLoad(true),
TagField::create(
'Tags',
_t('BlogPost.Tags', 'Tags'),
$tags,
$self->Tags()
)
->setCanCreate($self->canCreateTags())
->setShouldLazyLoad(true),
$authorField,
$authorNames
)->setTitle('Post Options');
$options->setName('blog-admin-sidebar');
$fields->insertBefore($options, 'Root');
});
$fields = parent::getCMSFields();
$fields->fieldByName('Root')->setTemplate('TabSet_holder');
return $fields;
}
/**
* Gets the list of author candidates to be assigned as authors of this blog post.
*
* @return SS_List
*/
public function getCandidateAuthors()
{
if ($this->config()->restrict_authors_to_group) {
return Group::get()->filter('Code', $this->config()->restrict_authors_to_group)->first()->Members();
} else {
$list = Member::get();
$this->extend('updateCandidateAuthors', $list);
return $list;
}
}
/**
* 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_numeric($member)) {
$member = Member::get()->byID($member);
}
return $member;
}
/**
* Determine whether user can create new categories.
*
* @param null|int|Member $member
*
* @return bool
*/
public function canCreateCategories($member = null)
{
$member = $this->getMember($member);
$parent = $this->Parent();
if (!$parent || !$parent->exists() || !($parent instanceof Blog)) {
return false;
}
if ($parent->isEditor($member)) {
return true;
}
return Permission::checkMember($member, 'ADMIN');
}
/**
* Determine whether user can create new tags.
*
* @param null|int|Member $member
*
* @return bool
*/
public function canCreateTags($member = null)
{
$member = $this->getMember($member);
$parent = $this->Parent();
if (!$parent || !$parent->exists() || !($parent instanceof Blog)) {
return false;
}
if ($parent->isEditor($member)) {
return true;
}
if ($parent->isWriter($member)) {
return true;
}
return Permission::checkMember($member, 'ADMIN');
}
/**
* {@inheritdoc}
*
* Update the PublishDate to now if the BlogPost would otherwise be published without a date.
*/
public function onBeforePublish()
{
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
if (!$publishDate->getValue()) {
$this->PublishDate = SS_Datetime::now()->getValue();
$this->write();
}
}
/**
* {@inheritdoc}
*
* Sets blog relationship on all categories and tags assigned to this post.
*/
public function onAfterWrite()
{
parent::onAfterWrite();
foreach ($this->Categories() as $category) {
/**
* @var BlogCategory $category
*/
$category->BlogID = $this->ParentID;
$category->write();
}
foreach ($this->Tags() as $tag) {
/**
* @var BlogTag $tag
*/
$tag->BlogID = $this->ParentID;
$tag->write();
}
}
/**
* {@inheritdoc}
*/
public function canView($member = null)
{
$member = $this->getMember($member);
if (!parent::canView($member)) {
return false;
}
/**
* @var SS_Datetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
// Show past posts
if (!$publishDate->exists() || !$publishDate->InFuture()) {
return true;
}
// Anyone that can edit this page can view it
return $this->canEdit($member);
}
/**
* {@inheritdoc}
*/
public function canPublish($member = null)
{
$member = $this->getMember($member);
if (Permission::checkMember($member, 'ADMIN')) {
return true;
}
$extended = $this->extendedCan('canPublish', $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;
}
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;
}
return $this->isAuthor($member);
}
/**
* Returns the post excerpt.
*
* @param int $wordsToDisplay
*
* @return string
*/
public function Excerpt($wordsToDisplay = 30)
{
/**
* @var Text $content
*/
$content = $this->dbObject('Content');
return $content->Summary($wordsToDisplay);
}
/**
* Returns a monthly archive link for the current blog post.
*
* @param string $type
*
* @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')
);
}
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'));
}
/**
* Returns a yearly archive link for the current blog post.
*
* @return string
*/
public function getYearlyArchiveLink()
{
/**
* @var SS_Datetime $date
*/
$date = $this->dbObject('PublishDate');
return Controller::join_links($this->Parent()->Link('archive'), $date->format('Y'));
}
/**
* Resolves static and dynamic authors linked to this post.
*
* @return ArrayList
*/
public function getCredits()
{
$list = new ArrayList();
$list->merge($this->getDynamicCredits());
$list->merge($this->getStaticCredits());
return $list->sort('Name');
}
/**
* Resolves dynamic authors linked to this post.
*
* @return ArrayList
*/
protected function getDynamicCredits()
{
// Find best page to host user profiles
$parent = $this->Parent();
if (! ($parent instanceof Blog)) {
$parent = Blog::get()->first();
}
// If there is no parent blog, return list undecorated
if (!$parent) {
$items = $this->Authors()->toArray();
return new ArrayList($items);
}
// Update all authors
$items = new ArrayList();
foreach ($this->Authors() as $author) {
// Add link for each author
$author = $author->customise(array(
'URL' => $parent->ProfileLink($author->URLSegment),
));
$items->push($author);
}
return $items;
}
/**
* Resolves static authors linked to this post.
*
* @return ArrayList
*/
protected function getStaticCredits()
{
$items = new ArrayList();
$authors = array_filter(preg_split('/\s*,\s*/', $this->AuthorNames));
foreach ($authors as $author) {
$item = new ArrayData(array(
'Name' => $author,
));
$items->push($item);
}
return $items;
}
/**
* 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');
return $labels;
}
/**
* {@inheritdoc}
*/
protected function onBeforeWrite()
{
parent::onBeforeWrite();
if (!$this->exists() && ($member = Member::currentUser())) {
$this->Authors()->add($member);
}
}
}
/**
* @package silverstripe
* @subpackage blog
*/
class BlogPost_Controller extends Page_Controller
{
}

View File

@ -12,135 +12,143 @@
* @property string $URLSegment
* @property int $BlogID
*/
class BlogTag extends DataObject implements CategorisationObject {
/**
* @var array
*/
private static $db = array(
'Title' => 'Varchar(255)',
);
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 $has_one = array(
'Blog' => 'Blog',
);
/**
* @var array
*/
private static $belongs_many_many = array(
'BlogPosts' => 'BlogPost',
);
/**
* @var array
*/
private static $belongs_many_many = array(
'BlogPosts' => 'BlogPost',
);
/**
* @var array
*/
private static $extensions = array(
'URLSegmentExtension',
);
/**
* @var array
*/
private static $extensions = array(
'URLSegmentExtension',
);
/**
* @return DataList
*/
public function BlogPosts() {
$blogPosts = parent::BlogPosts();
/**
* @return DataList
*/
public function BlogPosts()
{
$blogPosts = parent::BlogPosts();
$this->extend("updateGetBlogPosts", $blogPosts);
$this->extend("updateGetBlogPosts", $blogPosts);
return $blogPosts;
}
return $blogPosts;
}
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$fields = new FieldList(
TextField::create('Title', _t('BlogTag.Title', 'Title'))
);
/**
* {@inheritdoc}
*/
public function getCMSFields()
{
$fields = new FieldList(
TextField::create('Title', _t('BlogTag.Title', 'Title'))
);
$this->extend('updateCMSFields', $fields);
$this->extend('updateCMSFields', $fields);
return $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);
}
/**
* 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);
/**
* 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;
}
if ($extended !== null) {
return $extended;
}
return $this->Blog()->canView($member);
}
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);
/**
* 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;
}
if ($extended !== null) {
return $extended;
}
$permission = Blog::config()->grant_user_permission;
$permission = Blog::config()->grant_user_permission;
return Permission::checkMember($member, $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);
/**
* 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;
}
if ($extended !== null) {
return $extended;
}
return $this->Blog()->canEdit($member);
}
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);
/**
* 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;
}
if ($extended !== null) {
return $extended;
}
return $this->Blog()->canEdit($member);
}
return $this->Blog()->canEdit($member);
}
}

View File

@ -3,6 +3,6 @@
/**
* @method ManyManyList BlogPosts
*/
interface CategorisationObject {
interface CategorisationObject
{
}

View File

@ -1,135 +1,138 @@
<?php
if(!class_exists('Widget')) {
return;
}
/**
* @method Blog Blog()
*
* @property string $ArchiveType
* @property int $NumberToDisplay
*/
class BlogArchiveWidget extends Widget {
/**
* @var string
*/
private static $title = 'Archive';
/**
* @var string
*/
private static $cmsTitle = 'Archive';
/**
* @var string
*/
private static $description = 'Displays an archive list of posts.';
/**
* @var array
*/
private static $db = array(
'NumberToDisplay' => 'Int',
'ArchiveType' => 'Enum(\'Monthly,Yearly\', \'Monthly\')',
);
/**
* @var array
*/
private static $defaults = array(
'NumberOfMonths' => 12,
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$self =& $this;
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
/**
* @var Enum $archiveType
*/
$archiveType = $self->dbObject('ArchiveType');
$type = $archiveType->enumValues();
foreach($type as $k => $v) {
$type[$k] = _t('BlogArchiveWidget.' . ucfirst(strtolower($v)), $v);
}
/**
* @var FieldList $fields
*/
$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);
if($this->NumberToDisplay > 0) {
$posts = $posts->limit($this->NumberToDisplay);
}
$archive = new ArrayList();
if($posts->count() > 0) {
foreach($posts as $post) {
/**
* @var BlogPost $post
*/
$date = Date::create();
$date->setValue($post->PublishDate);
if($this->ArchiveType == 'Yearly') {
$year = $date->FormatI18N("%Y");
$month = null;
$title = $year;
} else {
$year = $date->FormatI18N("%Y");
$month = $date->FormatI18N("%m");
$title = $date->FormatI18N("%B %Y");
}
$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 {
}
<?php
if (!class_exists('Widget')) {
return;
}
/**
* @method Blog Blog()
*
* @property string $ArchiveType
* @property int $NumberToDisplay
*/
class BlogArchiveWidget extends Widget
{
/**
* @var string
*/
private static $title = 'Archive';
/**
* @var string
*/
private static $cmsTitle = 'Archive';
/**
* @var string
*/
private static $description = 'Displays an archive list of posts.';
/**
* @var array
*/
private static $db = array(
'NumberToDisplay' => 'Int',
'ArchiveType' => 'Enum(\'Monthly,Yearly\', \'Monthly\')',
);
/**
* @var array
*/
private static $defaults = array(
'NumberOfMonths' => 12,
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields()
{
$self =& $this;
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
/**
* @var Enum $archiveType
*/
$archiveType = $self->dbObject('ArchiveType');
$type = $archiveType->enumValues();
foreach ($type as $k => $v) {
$type[$k] = _t('BlogArchiveWidget.' . ucfirst(strtolower($v)), $v);
}
/**
* @var FieldList $fields
*/
$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);
if ($this->NumberToDisplay > 0) {
$posts = $posts->limit($this->NumberToDisplay);
}
$archive = new ArrayList();
if ($posts->count() > 0) {
foreach ($posts as $post) {
/**
* @var BlogPost $post
*/
$date = Date::create();
$date->setValue($post->PublishDate);
if ($this->ArchiveType == 'Yearly') {
$year = $date->FormatI18N("%Y");
$month = null;
$title = $year;
} else {
$year = $date->FormatI18N("%Y");
$month = $date->FormatI18N("%m");
$title = $date->FormatI18N("%B %Y");
}
$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,97 +1,100 @@
<?php
if(!class_exists("Widget")) {
return;
}
/**
* @method Blog Blog()
*/
class BlogCategoriesWidget extends Widget {
/**
* @var string
*/
private static $title = 'Categories';
/**
* @var string
*/
private static $cmsTitle = 'Blog Categories';
/**
* @var string
*/
private static $description = 'Displays a list of blog categories.';
/**
* @var array
*/
private static $db = array(
'Limit' => 'Int',
'Order' => 'Varchar',
'Direction' => 'Varchar',
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$this->beforeUpdateCMSFields(function (FieldList $fields) {
$fields[] = DropdownField::create(
'BlogID', _t('BlogCategoriesWidget.Blog', 'Blog'), Blog::get()->map()
);
$fields[] = NumericField::create(
'Limit', _t('BlogCategoriesWidget.Limit.Label', 'Limit'), 0
)
->setDescription(_t('BlogCategoriesWidget.Limit.Description', 'Limit the number of categories shown by this widget (set to 0 to show all categories).'))
->setMaxLength(3);
$fields[] = DropdownField::create(
'Order', _t('BlogCategoriesWidget.Sort.Label', 'Sort'), array('Title' => 'Title', 'Created' => 'Created', 'LastUpdated' => 'Updated')
)
->setDescription(_t('BlogCategoriesWidget.Sort.Description', 'Change the order of categories shown by this widget.'));
$fields[] = DropdownField::create(
'Direction', _t('BlogCategoriesWidget.Direction.Label', 'Direction'), array('ASC' => 'Ascending', 'DESC' => 'Descending')
)
->setDescription(_t('BlogCategoriesWidget.Direction.Description', 'Change the direction of ordering of categories shown by this widget.'));
});
return parent::getCMSFields();
}
/**
* @return DataList
*/
public function getCategories() {
$blog = $this->Blog();
if (!$blog) {
return array();
}
$query = $blog->Categories();
if ($this->Limit) {
$query = $query->limit(Convert::raw2sql($this->Limit));
}
if ($this->Order && $this->Direction) {
$query = $query->sort(Convert::raw2sql($this->Order), Convert::raw2sql($this->Direction));
}
return $query;
}
}
class BlogCategoriesWidget_Controller extends Widget_Controller {
}
<?php
if (!class_exists("Widget")) {
return;
}
/**
* @method Blog Blog()
*/
class BlogCategoriesWidget extends Widget
{
/**
* @var string
*/
private static $title = 'Categories';
/**
* @var string
*/
private static $cmsTitle = 'Blog Categories';
/**
* @var string
*/
private static $description = 'Displays a list of blog categories.';
/**
* @var array
*/
private static $db = array(
'Limit' => 'Int',
'Order' => 'Varchar',
'Direction' => 'Varchar',
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields()
{
$this->beforeUpdateCMSFields(function (FieldList $fields) {
$fields[] = DropdownField::create(
'BlogID', _t('BlogCategoriesWidget.Blog', 'Blog'), Blog::get()->map()
);
$fields[] = NumericField::create(
'Limit', _t('BlogCategoriesWidget.Limit.Label', 'Limit'), 0
)
->setDescription(_t('BlogCategoriesWidget.Limit.Description', 'Limit the number of categories shown by this widget (set to 0 to show all categories).'))
->setMaxLength(3);
$fields[] = DropdownField::create(
'Order', _t('BlogCategoriesWidget.Sort.Label', 'Sort'), array('Title' => 'Title', 'Created' => 'Created', 'LastUpdated' => 'Updated')
)
->setDescription(_t('BlogCategoriesWidget.Sort.Description', 'Change the order of categories shown by this widget.'));
$fields[] = DropdownField::create(
'Direction', _t('BlogCategoriesWidget.Direction.Label', 'Direction'), array('ASC' => 'Ascending', 'DESC' => 'Descending')
)
->setDescription(_t('BlogCategoriesWidget.Direction.Description', 'Change the direction of ordering of categories shown by this widget.'));
});
return parent::getCMSFields();
}
/**
* @return DataList
*/
public function getCategories()
{
$blog = $this->Blog();
if (!$blog) {
return array();
}
$query = $blog->Categories();
if ($this->Limit) {
$query = $query->limit(Convert::raw2sql($this->Limit));
}
if ($this->Order && $this->Direction) {
$query = $query->sort(Convert::raw2sql($this->Order), Convert::raw2sql($this->Direction));
}
return $query;
}
}
class BlogCategoriesWidget_Controller extends Widget_Controller
{
}

View File

@ -1,77 +1,80 @@
<?php
if(!class_exists("Widget")) {
return;
}
/**
* @method Blog Blog()
*
* @property int $NumberOfPosts
*/
class BlogRecentPostsWidget extends Widget {
/**
* @var string
*/
private static $title = 'Recent Posts';
/**
* @var string
*/
private static $cmsTitle = 'Recent Posts';
/**
* @var string
*/
private static $description = 'Displays a list of recent blog posts.';
/**
* @var array
*/
private static $db = array(
'NumberOfPosts' => 'Int',
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$this->beforeUpdateCMSFields(function ($fields) {
/**
* @var FieldList $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();
}
/**
* @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 {
}
<?php
if (!class_exists("Widget")) {
return;
}
/**
* @method Blog Blog()
*
* @property int $NumberOfPosts
*/
class BlogRecentPostsWidget extends Widget
{
/**
* @var string
*/
private static $title = 'Recent Posts';
/**
* @var string
*/
private static $cmsTitle = 'Recent Posts';
/**
* @var string
*/
private static $description = 'Displays a list of recent blog posts.';
/**
* @var array
*/
private static $db = array(
'NumberOfPosts' => 'Int',
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields()
{
$this->beforeUpdateCMSFields(function ($fields) {
/**
* @var FieldList $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();
}
/**
* @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,97 +1,100 @@
<?php
if(!class_exists("Widget")) {
return;
}
/**
* @method Blog Blog()
*/
class BlogTagsWidget extends Widget {
/**
* @var string
*/
private static $title = 'Tags';
/**
* @var string
*/
private static $cmsTitle = 'Blog Tags';
/**
* @var string
*/
private static $description = 'Displays a list of blog tags.';
/**
* @var array
*/
private static $db = array(
'Limit' => 'Int',
'Order' => 'Varchar',
'Direction' => 'Varchar',
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields() {
$this->beforeUpdateCMSFields(function (Fieldlist $fields) {
$fields[] = DropdownField::create(
'BlogID', _t('BlogTagsWidget.Blog', 'Blog'), Blog::get()->map()
);
$fields[] = NumericField::create(
'Limit', _t('BlogTagsWidget.Limit.Label', 'Limit'), 0
)
->setDescription(_t('BlogTagsWidget.Limit.Description', 'Limit the number of tags shown by this widget (set to 0 to show all tags).'))
->setMaxLength(3);
$fields[] = DropdownField::create(
'Order', _t('BlogTagsWidget.Sort.Label', 'Sort'), array('Title' => 'Title', 'Created' => 'Created', 'LastUpdated' => 'Updated')
)
->setDescription(_t('BlogTagsWidget.Sort.Description', 'Change the order of tags shown by this widget.'));
$fields[] = DropdownField::create(
'Direction', _t('BlogTagsWidget.Direction.Label', 'Direction'), array('ASC' => 'Ascending', 'DESC' => 'Descending')
)
->setDescription(_t('BlogTagsWidget.Direction.Description', 'Change the direction of ordering of tags shown by this widget.'));
});
return parent::getCMSFields();
}
/**
* @return DataList
*/
public function getTags() {
$blog = $this->Blog();
if (!$blog) {
return array();
}
$query = $blog->Tags();
if ($this->Limit) {
$query = $query->limit(Convert::raw2sql($this->Limit));
}
if ($this->Order && $this->Direction) {
$query = $query->sort(Convert::raw2sql($this->Order), Convert::raw2sql($this->Direction));
}
return $query;
}
}
class BlogTagsWidget_Controller extends Widget_Controller {
}
<?php
if (!class_exists("Widget")) {
return;
}
/**
* @method Blog Blog()
*/
class BlogTagsWidget extends Widget
{
/**
* @var string
*/
private static $title = 'Tags';
/**
* @var string
*/
private static $cmsTitle = 'Blog Tags';
/**
* @var string
*/
private static $description = 'Displays a list of blog tags.';
/**
* @var array
*/
private static $db = array(
'Limit' => 'Int',
'Order' => 'Varchar',
'Direction' => 'Varchar',
);
/**
* @var array
*/
private static $has_one = array(
'Blog' => 'Blog',
);
/**
* {@inheritdoc}
*/
public function getCMSFields()
{
$this->beforeUpdateCMSFields(function (Fieldlist $fields) {
$fields[] = DropdownField::create(
'BlogID', _t('BlogTagsWidget.Blog', 'Blog'), Blog::get()->map()
);
$fields[] = NumericField::create(
'Limit', _t('BlogTagsWidget.Limit.Label', 'Limit'), 0
)
->setDescription(_t('BlogTagsWidget.Limit.Description', 'Limit the number of tags shown by this widget (set to 0 to show all tags).'))
->setMaxLength(3);
$fields[] = DropdownField::create(
'Order', _t('BlogTagsWidget.Sort.Label', 'Sort'), array('Title' => 'Title', 'Created' => 'Created', 'LastUpdated' => 'Updated')
)
->setDescription(_t('BlogTagsWidget.Sort.Description', 'Change the order of tags shown by this widget.'));
$fields[] = DropdownField::create(
'Direction', _t('BlogTagsWidget.Direction.Label', 'Direction'), array('ASC' => 'Ascending', 'DESC' => 'Descending')
)
->setDescription(_t('BlogTagsWidget.Direction.Description', 'Change the direction of ordering of tags shown by this widget.'));
});
return parent::getCMSFields();
}
/**
* @return DataList
*/
public function getTags()
{
$blog = $this->Blog();
if (!$blog) {
return array();
}
$query = $blog->Tags();
if ($this->Limit) {
$query = $query->limit(Convert::raw2sql($this->Limit));
}
if ($this->Order && $this->Direction) {
$query = $query->sort(Convert::raw2sql($this->Order), Convert::raw2sql($this->Direction));
}
return $query;
}
}
class BlogTagsWidget_Controller extends Widget_Controller
{
}

View File

@ -3,116 +3,124 @@
/**
* @mixin PHPUnit_Framework_TestCase
*/
class BlogCategoryTest extends FunctionalTest {
/**
* @var string
*/
static $fixture_file = 'blog.yml';
class BlogCategoryTest extends FunctionalTest
{
/**
* @var string
*/
public static $fixture_file = 'blog.yml';
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
/**
* {@inheritdoc}
*/
public function setUp()
{
parent::setUp();
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
}
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
}
/**
* {@inheritdoc}
*/
public function tearDown() {
SS_Datetime::clear_mock_now();
/**
* {@inheritdoc}
*/
public function tearDown()
{
SS_Datetime::clear_mock_now();
parent::tearDown();
}
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() {
$member = Member::currentUser();
/**
* 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()
{
$member = Member::currentUser();
if($member) {
$member->logout();
}
if ($member) {
$member->logout();
}
$this->objFromFixture('BlogPost', 'FirstBlogPost');
$this->objFromFixture('BlogPost', 'FirstBlogPost');
/**
* @var BlogCategory $category
*/
$category = $this->objFromFixture('BlogCategory', 'FirstCategory');
/**
* @var BlogCategory $category
*/
$category = $this->objFromFixture('BlogCategory', 'FirstCategory');
$this->assertEquals(1, $category->BlogPosts()->count(), 'Category blog post count');
}
$this->assertEquals(1, $category->BlogPosts()->count(), 'Category blog post count');
}
public function testCanView() {
$this->useDraftSite();
public function testCanView()
{
$this->useDraftSite();
$this->objFromFixture('Member', 'Admin');
$this->objFromFixture('Member', 'Admin');
$editor = $this->objFromFixture('Member', 'Editor');
$category = $this->objFromFixture('BlogCategory', 'SecondCategory');
$editor = $this->objFromFixture('Member', 'Editor');
$category = $this->objFromFixture('BlogCategory', 'SecondCategory');
$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();
/**
* 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');
$category = $this->objFromFixture('BlogCategory', 'FirstCategory');
$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.');
$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', 'SecondCategory');
$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->assertFalse($category->canEdit($editor), 'Editor should not be able to edit category.');
$category = $this->objFromFixture('BlogCategory', 'ThirdCategory');
$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.');
}
$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();
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');
$category = singleton('BlogCategory');
$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();
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');
$category = $this->objFromFixture('BlogCategory', 'FirstCategory');
$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.');
$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', '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', '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.');
}
$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

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

View File

@ -1,79 +1,82 @@
<?php
class BlogPostTest extends SapphireTest {
/**
* @var string
*/
static $fixture_file = 'blog.yml';
class BlogPostTest extends SapphireTest
{
/**
* @var string
*/
public static $fixture_file = 'blog.yml';
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
}
/**
* {@inheritdoc}
*/
public function setUp()
{
parent::setUp();
}
/**
* {@inheritdoc}
*/
public function tearDown() {
SS_Datetime::clear_mock_now();
parent::tearDown();
}
/**
* {@inheritdoc}
*/
public function tearDown()
{
SS_Datetime::clear_mock_now();
parent::tearDown();
}
/**
* @dataProvider canViewProvider
*/
public function testCanView($date, $user, $page, $canView) {
$userRecord = $this->objFromFixture('Member', $user);
$pageRecord = $this->objFromFixture('BlogPost', $page);
SS_Datetime::set_mock_now($date);
$this->assertEquals($canView, $pageRecord->canView($userRecord));
}
public function canViewProvider() {
$someFutureDate = '2013-10-10 20:00:00';
$somePastDate = '2009-10-10 20:00:00';
return array(
// Check this post given the date has passed
array($someFutureDate, 'Editor', 'PostA', true),
array($someFutureDate, 'Contributor', 'PostA', true),
array($someFutureDate, 'BlogEditor', 'PostA', true),
array($someFutureDate, 'Writer', 'PostA', true),
// Check unpublished pages
array($somePastDate, 'Editor', 'PostA', true),
array($somePastDate, 'Contributor', 'PostA', true),
array($somePastDate, 'BlogEditor', 'PostA', true),
array($somePastDate, 'Writer', 'PostA', true),
// Test a page that was authored by another user
// Check this post given the date has passed
array($someFutureDate, 'Editor', 'FirstBlogPost', true),
array($someFutureDate, 'Contributor', 'FirstBlogPost', true),
array($someFutureDate, 'BlogEditor', 'FirstBlogPost', true),
array($someFutureDate, 'Writer', 'FirstBlogPost', true),
// Check future pages - non-editors shouldn't be able to see this
array($somePastDate, 'Editor', 'FirstBlogPost', true),
array($somePastDate, 'Contributor', 'FirstBlogPost', false),
array($somePastDate, 'BlogEditor', 'FirstBlogPost', false),
array($somePastDate, 'Writer', 'FirstBlogPost', false),
);
}
/**
* @dataProvider canViewProvider
*/
public function testCanView($date, $user, $page, $canView)
{
$userRecord = $this->objFromFixture('Member', $user);
$pageRecord = $this->objFromFixture('BlogPost', $page);
SS_Datetime::set_mock_now($date);
$this->assertEquals($canView, $pageRecord->canView($userRecord));
}
public function canViewProvider()
{
$someFutureDate = '2013-10-10 20:00:00';
$somePastDate = '2009-10-10 20:00:00';
return array(
// Check this post given the date has passed
array($someFutureDate, 'Editor', 'PostA', true),
array($someFutureDate, 'Contributor', 'PostA', true),
array($someFutureDate, 'BlogEditor', 'PostA', true),
array($someFutureDate, 'Writer', 'PostA', true),
// Check unpublished pages
array($somePastDate, 'Editor', 'PostA', true),
array($somePastDate, 'Contributor', 'PostA', true),
array($somePastDate, 'BlogEditor', 'PostA', true),
array($somePastDate, 'Writer', 'PostA', true),
// Test a page that was authored by another user
public function testCandidateAuthors() {
$blogpost = $this->objFromFixture('BlogPost', 'PostC');
// Check this post given the date has passed
array($someFutureDate, 'Editor', 'FirstBlogPost', true),
array($someFutureDate, 'Contributor', 'FirstBlogPost', true),
array($someFutureDate, 'BlogEditor', 'FirstBlogPost', true),
array($someFutureDate, 'Writer', 'FirstBlogPost', true),
// Check future pages - non-editors shouldn't be able to see this
array($somePastDate, 'Editor', 'FirstBlogPost', true),
array($somePastDate, 'Contributor', 'FirstBlogPost', false),
array($somePastDate, 'BlogEditor', 'FirstBlogPost', false),
array($somePastDate, 'Writer', 'FirstBlogPost', false),
);
}
$this->assertEquals(7, $blogpost->getCandidateAuthors()->count());
public function testCandidateAuthors()
{
$blogpost = $this->objFromFixture('BlogPost', 'PostC');
//Set the group to draw Members from
Config::inst()->update('BlogPost', 'restrict_authors_to_group','BlogUsers');
$this->assertEquals(7, $blogpost->getCandidateAuthors()->count());
$this->assertEquals(3, $blogpost->getCandidateAuthors()->count());
//Set the group to draw Members from
Config::inst()->update('BlogPost', 'restrict_authors_to_group', 'BlogUsers');
}
$this->assertEquals(3, $blogpost->getCandidateAuthors()->count());
}
}

View File

@ -3,124 +3,132 @@
/**
* @mixin PHPUnit_Framework_TestCase
*/
class BlogTagTest extends FunctionalTest {
/**
* @var string
*/
static $fixture_file = 'blog.yml';
class BlogTagTest extends FunctionalTest
{
/**
* @var string
*/
public static $fixture_file = 'blog.yml';
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
/**
* {@inheritdoc}
*/
public function setUp()
{
parent::setUp();
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
}
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
}
/**
* {@inheritdoc}
*/
public function tearDown() {
SS_Datetime::clear_mock_now();
/**
* {@inheritdoc}
*/
public function tearDown()
{
SS_Datetime::clear_mock_now();
parent::tearDown();
}
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.
*/
public function testBlogPosts() {
$member = Member::currentUser();
/**
* 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()
{
$member = Member::currentUser();
if($member) {
$member->logout();
}
if ($member) {
$member->logout();
}
$this->objFromFixture('BlogPost', 'FirstBlogPost');
$this->objFromFixture('BlogPost', 'FirstBlogPost');
/**
* @var BlogTag $tag
*/
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
/**
* @var BlogTag $tag
*/
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$this->assertEquals(1, $tag->BlogPosts()->count(), 'Tag blog post count');
}
$this->assertEquals(1, $tag->BlogPosts()->count(), 'Tag blog post count');
}
/**
* The first blog can be viewed by anybody.
*/
public function testCanView() {
$this->useDraftSite();
/**
* 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');
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$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.');
$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');
$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->assertFalse($tag->canView($editor), 'Editor should not be able to view tag.');
}
public function testCanEdit() {
$this->useDraftSite();
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');
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$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.');
$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', 'SecondTag');
$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->assertFalse($tag->canEdit($editor), 'Editor should not be able to edit tag.');
$tag = $this->objFromFixture('BlogTag', 'ThirdTag');
$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.');
}
$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();
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');
$tag = singleton('BlogTag');
$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.');
}
$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();
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');
$tag = $this->objFromFixture('BlogTag', 'FirstTag');
$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.');
$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', 'SecondTag');
$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->assertFalse($tag->canDelete($editor), 'Editor should not be able to delete tag.');
$tag = $this->objFromFixture('BlogTag', 'ThirdTag');
$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.');
}
$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

@ -3,332 +3,347 @@
/**
* @mixin PHPUnit_Framework_TestCase
*/
class BlogTest extends SapphireTest {
/**
* @var string
*/
static $fixture_file = 'blog.yml';
class BlogTest extends SapphireTest
{
/**
* @var string
*/
public static $fixture_file = 'blog.yml';
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
/**
* {@inheritdoc}
*/
public function setUp()
{
parent::setUp();
Config::nest();
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
Config::nest();
SS_Datetime::set_mock_now('2013-10-10 20:00:00');
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$blog->publish('Stage', 'Live');
}
$blog->publish('Stage', 'Live');
}
/**
* {@inheritdoc}
*/
public function tearDown() {
SS_Datetime::clear_mock_now();
Config::unnest();
/**
* {@inheritdoc}
*/
public function tearDown()
{
SS_Datetime::clear_mock_now();
Config::unnest();
parent::tearDown();
}
parent::tearDown();
}
public function testGetExcludedSiteTreeClassNames() {
$member = Member::currentUser();
public function testGetExcludedSiteTreeClassNames()
{
$member = Member::currentUser();
if($member) {
$member->logout();
}
if ($member) {
$member->logout();
}
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
Config::inst()->update('BlogPost', 'show_in_sitetree', true);
$classes = $blog->getExcludedSiteTreeClassNames();
Config::inst()->update('BlogPost', 'show_in_sitetree', true);
$classes = $blog->getExcludedSiteTreeClassNames();
$this->assertNotContains('BlogPost', $classes, 'BlogPost class should be hidden.');
$this->assertNotContains('BlogPost', $classes, 'BlogPost class should be hidden.');
Config::inst()->update('BlogPost', 'show_in_sitetree', false);
$classes = $blog->getExcludedSiteTreeClassNames();
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();
public function testGetArchivedBlogPosts()
{
$member = Member::currentUser();
if($member) {
$member->logout();
}
if ($member) {
$member->logout();
}
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$archive = $blog->getArchivedBlogPosts(2013);
$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');
$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);
$archive = $blog->getArchivedBlogPosts(2013, 10);
$this->assertEquals(1, $archive->count(), 'Incorrect monthly archive count.');
$this->assertEquals(1, $archive->count(), 'Incorrect monthly archive count.');
$archive = $blog->getArchivedBlogPosts(2013, 10, 01);
$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() {
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
public function testArchiveLinks()
{
/**
* @var Blog $blog
*/
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$link = Controller::join_links($blog->Link('archive'), '2013', '10', '01');
$link = Controller::join_links($blog->Link('archive'), '2013', '10', '01');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$link = Controller::join_links($blog->Link('archive'), '2013', '10');
$link = Controller::join_links($blog->Link('archive'), '2013', '10');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$link = Controller::join_links($blog->Link('archive'), '2013');
$link = Controller::join_links($blog->Link('archive'), '2013');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$link = Controller::join_links($blog->Link('archive'), '2011', '10', '01');
$link = Controller::join_links($blog->Link('archive'), '2011', '10', '01');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$link = Controller::join_links($blog->Link('archive'));
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$link = Controller::join_links($blog->Link('archive'));
$this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
$link = Controller::join_links($blog->Link('archive'), 'invalid-year');
$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');
}
/*
* Test archive year
*/
public function testArchiveYear(){
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$controller = new Blog_Controller($blog);
$this->requestURL($controller, 'first-post/archive/');
$this->assertEquals(2013, $controller->getArchiveYear(), 'getArchiveYear should return 2013');
}
/**
* @param string $link
*
* @return int
*/
protected function getStatusOf($link) {
return Director::test($link)->getStatusCode();
}
public function testRoles() {
/**
* @var Blog $firstBlog
*/
$firstBlog = $this->objFromFixture('Blog', 'FirstBlog');
/**
* @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));
// Test RoleOf with string values given
$this->assertEquals('Editor', $fourthBlog->RoleOf((string)(int)$editor->ID));
$this->assertEquals('Contributor', $fourthBlog->RoleOf((string)(int)$contributor->ID));
$this->assertEquals('Writer', $fourthBlog->RoleOf((string)(int)$writer->ID));
$this->assertEmpty($fourthBlog->RoleOf((string)(int)$visitor->ID));
$this->assertEquals('Author', $postA->RoleOf((string)(int)$writer->ID));
$this->assertEquals('Author', $postA->RoleOf((string)(int)$contributor->ID));
$this->assertEquals('Editor', $postA->RoleOf((string)(int)$editor->ID));
$this->assertEmpty($postA->RoleOf((string)(int)$visitor->ID));
// Test RoleOf with int values given
$this->assertEquals('Editor', $fourthBlog->RoleOf((int)$editor->ID));
$this->assertEquals('Contributor', $fourthBlog->RoleOf((int)$contributor->ID));
$this->assertEquals('Writer', $fourthBlog->RoleOf((int)$writer->ID));
$this->assertEmpty($fourthBlog->RoleOf((int)$visitor->ID));
$this->assertEquals('Author', $postA->RoleOf((int)$writer->ID));
$this->assertEquals('Author', $postA->RoleOf((int)$contributor->ID));
$this->assertEquals('Editor', $postA->RoleOf((int)$editor->ID));
$this->assertEmpty($postA->RoleOf((int)$visitor->ID));
$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));
$this->assertTrue($postA->canPublish($editor));
$this->assertTrue($postB->canPublish($editor));
$this->assertTrue($postC->canPublish($editor));
$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));
$this->assertTrue($postA->canPublish($writer));
$this->assertFalse($postB->canPublish($writer));
$this->assertTrue($postC->canPublish($writer));
$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));
$this->assertFalse($postA->canPublish($contributor));
$this->assertFalse($postB->canPublish($contributor));
$this->assertFalse($postC->canPublish($contributor));
$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));
$this->assertFalse($postA->canPublish($visitor));
$this->assertFalse($postB->canPublish($visitor));
$this->assertFalse($postC->canPublish($visitor));
}
public function testFilteredCategories() {
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$controller = new Blog_Controller($blog);
// Root url
$this->requestURL($controller, 'first-post');
$this->assertIDsEquals(
$blog->AllChildren()->column('ID'),
$controller->PaginatedList()->column('ID')
);
// RSS
$this->requestURL($controller, 'first-post/rss');
$this->assertIDsEquals(
$blog->AllChildren()->column('ID'),
$controller->PaginatedList()->column('ID')
);
// Posts
$firstPostID = $this->idFromFixture('BlogPost', 'FirstBlogPost');
$secondPostID = $this->idFromFixture('BlogPost', 'SecondBlogPost');
$firstFuturePostID = $this->idFromFixture('BlogPost', 'FirstFutureBlogPost');
$secondFuturePostID = $this->idFromFixture('BlogPost', 'SecondFutureBlogPost');
// Request first tag
$this->requestURL($controller, 'first-post/tag/first-tag');
$this->assertIDsEquals(
array($firstPostID, $firstFuturePostID, $secondFuturePostID),
$controller->PaginatedList()
);
// Request 2013 posts
$this->requestURL($controller, 'first-post/archive/2013');
$this->assertIDsEquals(
array($firstPostID, $secondPostID, $secondFuturePostID),
$controller->PaginatedList()
);
}
/**
* Mock a request against a given controller
*
* @param ContentController $controller
* @param string $url
*/
protected function requestURL(ContentController $controller, $url) {
$request = new SS_HTTPRequest('get', $url);
$request->match('$URLSegment//$Action/$ID/$OtherID');
$request->shift();
$controller->init();
$controller->handleRequest($request, new DataModel());
}
/**
* Assert these id lists match
*
* @param array|SS_List $left
* @param array|SS_List $right
*/
protected function assertIDsEquals($left, $right) {
if($left instanceof SS_List) $left = $left->column('ID');
if($right instanceof SS_List) $right = $right->column('ID');
asort($left);
asort($right);
$this->assertEquals(array_values($left), array_values($right));
}
$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');
}
/*
* Test archive year
*/
public function testArchiveYear()
{
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$controller = new Blog_Controller($blog);
$this->requestURL($controller, 'first-post/archive/');
$this->assertEquals(2013, $controller->getArchiveYear(), 'getArchiveYear should return 2013');
}
/**
* @param string $link
*
* @return int
*/
protected function getStatusOf($link)
{
return Director::test($link)->getStatusCode();
}
public function testRoles()
{
/**
* @var Blog $firstBlog
*/
$firstBlog = $this->objFromFixture('Blog', 'FirstBlog');
/**
* @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));
// Test RoleOf with string values given
$this->assertEquals('Editor', $fourthBlog->RoleOf((string)(int)$editor->ID));
$this->assertEquals('Contributor', $fourthBlog->RoleOf((string)(int)$contributor->ID));
$this->assertEquals('Writer', $fourthBlog->RoleOf((string)(int)$writer->ID));
$this->assertEmpty($fourthBlog->RoleOf((string)(int)$visitor->ID));
$this->assertEquals('Author', $postA->RoleOf((string)(int)$writer->ID));
$this->assertEquals('Author', $postA->RoleOf((string)(int)$contributor->ID));
$this->assertEquals('Editor', $postA->RoleOf((string)(int)$editor->ID));
$this->assertEmpty($postA->RoleOf((string)(int)$visitor->ID));
// Test RoleOf with int values given
$this->assertEquals('Editor', $fourthBlog->RoleOf((int)$editor->ID));
$this->assertEquals('Contributor', $fourthBlog->RoleOf((int)$contributor->ID));
$this->assertEquals('Writer', $fourthBlog->RoleOf((int)$writer->ID));
$this->assertEmpty($fourthBlog->RoleOf((int)$visitor->ID));
$this->assertEquals('Author', $postA->RoleOf((int)$writer->ID));
$this->assertEquals('Author', $postA->RoleOf((int)$contributor->ID));
$this->assertEquals('Editor', $postA->RoleOf((int)$editor->ID));
$this->assertEmpty($postA->RoleOf((int)$visitor->ID));
$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));
$this->assertTrue($postA->canPublish($editor));
$this->assertTrue($postB->canPublish($editor));
$this->assertTrue($postC->canPublish($editor));
$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));
$this->assertTrue($postA->canPublish($writer));
$this->assertFalse($postB->canPublish($writer));
$this->assertTrue($postC->canPublish($writer));
$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));
$this->assertFalse($postA->canPublish($contributor));
$this->assertFalse($postB->canPublish($contributor));
$this->assertFalse($postC->canPublish($contributor));
$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));
$this->assertFalse($postA->canPublish($visitor));
$this->assertFalse($postB->canPublish($visitor));
$this->assertFalse($postC->canPublish($visitor));
}
public function testFilteredCategories()
{
$blog = $this->objFromFixture('Blog', 'FirstBlog');
$controller = new Blog_Controller($blog);
// Root url
$this->requestURL($controller, 'first-post');
$this->assertIDsEquals(
$blog->AllChildren()->column('ID'),
$controller->PaginatedList()->column('ID')
);
// RSS
$this->requestURL($controller, 'first-post/rss');
$this->assertIDsEquals(
$blog->AllChildren()->column('ID'),
$controller->PaginatedList()->column('ID')
);
// Posts
$firstPostID = $this->idFromFixture('BlogPost', 'FirstBlogPost');
$secondPostID = $this->idFromFixture('BlogPost', 'SecondBlogPost');
$firstFuturePostID = $this->idFromFixture('BlogPost', 'FirstFutureBlogPost');
$secondFuturePostID = $this->idFromFixture('BlogPost', 'SecondFutureBlogPost');
// Request first tag
$this->requestURL($controller, 'first-post/tag/first-tag');
$this->assertIDsEquals(
array($firstPostID, $firstFuturePostID, $secondFuturePostID),
$controller->PaginatedList()
);
// Request 2013 posts
$this->requestURL($controller, 'first-post/archive/2013');
$this->assertIDsEquals(
array($firstPostID, $secondPostID, $secondFuturePostID),
$controller->PaginatedList()
);
}
/**
* Mock a request against a given controller
*
* @param ContentController $controller
* @param string $url
*/
protected function requestURL(ContentController $controller, $url)
{
$request = new SS_HTTPRequest('get', $url);
$request->match('$URLSegment//$Action/$ID/$OtherID');
$request->shift();
$controller->init();
$controller->handleRequest($request, new DataModel());
}
/**
* Assert these id lists match
*
* @param array|SS_List $left
* @param array|SS_List $right
*/
protected function assertIDsEquals($left, $right)
{
if ($left instanceof SS_List) {
$left = $left->column('ID');
}
if ($right instanceof SS_List) {
$right = $right->column('ID');
}
asort($left);
asort($right);
$this->assertEquals(array_values($left), array_values($right));
}
}