diff --git a/code/admin/GridFieldCategorisationConfig.php b/code/admin/GridFieldCategorisationConfig.php
new file mode 100644
index 0000000..d629228
--- /dev/null
+++ b/code/admin/GridFieldCategorisationConfig.php
@@ -0,0 +1,51 @@
+removeComponentsByType("GridFieldAddNewButton");
+
+ $this->addComponent(
+ new GridFieldAddByDBField("buttons-before-left")
+ );
+
+ $this->addComponent(
+ new GridFieldMergeAction($mergeRecords, $parentType, $parentMethod, $childMethod)
+ );
+
+ $columns = $this->getComponentByType('GridFieldDataColumns');
+
+ $columns->setFieldFormatting(array(
+ 'BlogPostsCount' => function($value, &$item) {
+ return $item->BlogPosts()->Count();
+ }
+ ));
+
+ $this->changeColumnOrder();
+ }
+
+ /**
+ * 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',
+ ));
+ }
+}
\ No newline at end of file
diff --git a/code/admin/GridFieldFormAction.php b/code/admin/GridFieldFormAction.php
new file mode 100644
index 0000000..1020fb3
--- /dev/null
+++ b/code/admin/GridFieldFormAction.php
@@ -0,0 +1,28 @@
+extraAttributes = $attributes;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAttributes()
+ {
+ $attributes = parent::getAttributes();
+
+ return array_merge(
+ $attributes,
+ $this->extraAttributes
+ );
+ }
+}
\ No newline at end of file
diff --git a/code/admin/GridFieldMergeAction.php b/code/admin/GridFieldMergeAction.php
new file mode 100644
index 0000000..2c25153
--- /dev/null
+++ b/code/admin/GridFieldMergeAction.php
@@ -0,0 +1,140 @@
+records = $records;
+ $this->parentType = $parentType;
+ $this->parentMethod = $parentMethod;
+ $this->childMethod = $childMethod;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function augmentColumns($gridField, &$columns) {
+ if(!in_array('MergeAction', $columns)) {
+ $columns[] = 'MergeAction';
+ }
+
+ return $columns;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getColumnsHandled($gridField) {
+ return array('MergeAction');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getColumnContent($gridField, $record, $columnName) {
+ if($columnName === 'MergeAction') {
+ $dropdown = new DropdownField('Target', 'Target', $this->records->map());
+
+ $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->setExtraAttributes(array(
+ 'data-target' => $prefix . '-target-record-' . $record->ID
+ ));
+
+ return $dropdown->Field() . $action->Field() . 'move posts to';
+ }
+
+ return null;
+ }
+
+ /**
+ * {@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 getActions($gridField) {
+ return array('merge');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
+ if($actionName === 'merge') {
+ $controller = Controller::curr();
+
+ $request = $controller->getRequest();
+
+ $target = $request->requestVar($arguments["target"]);
+
+ $parentType = $this->parentType;
+
+ $fromParent = $parentType::get()->byId($arguments['record']);
+ $toParent = $parentType::get()->byId($target);
+
+ $posts = $fromParent->{$this->childMethod}();
+
+ foreach ($posts as $post) {
+ $relationship = $post->{$this->parentMethod}();
+
+ $relationship->remove($fromParent);
+ $relationship->add($toParent);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/model/Blog.php b/code/model/Blog.php
index b3bb9dc..42023f8 100644
--- a/code/model/Blog.php
+++ b/code/model/Blog.php
@@ -5,7 +5,7 @@
*
* @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
@@ -13,7 +13,7 @@
* @method ManyManyList Contributors() List of contributors
*
* @author Michael Strong
-**/
+ **/
class Blog extends Page implements PermissionProvider {
/**
@@ -63,7 +63,7 @@ class Blog extends Page implements PermissionProvider {
'Writers' => 'Member',
'Contributors' => 'Member',
);
-
+
private static $allowed_children = array(
"BlogPost",
);
@@ -80,41 +80,38 @@ class Blog extends Page implements PermissionProvider {
public function getCMSFields() {
Requirements::css(BLOGGER_DIR . '/css/cms.css');
-
Requirements::javascript(BLOGGER_DIR . '/js/expandable-help-text.js');
+ Requirements::javascript(BLOGGER_DIR . '/js/merge-action.js');
$self =& $this;
- $this->beforeUpdateCMSFields(function($fields) use ($self) {
- // Don't show this tab if edit is not allowed
- if(!$self->canEdit()) return;
-
- // Create categories and tag config
- $config = GridFieldConfig_RecordEditor::create();
- $config->removeComponentsByType("GridFieldAddNewButton");
- $config->addComponent(new GridFieldAddByDBField("buttons-before-left"));
+ $this->beforeUpdateCMSFields(function ($fields) use ($self) {
+ if(!$self->canEdit()) {
+ return;
+ }
$categories = GridField::create(
"Categories",
_t("Blog.Categories", "Categories"),
$self->Categories(),
- $config
+ GridFieldCategorisationConfig::create(15, $self->Categories(), 'BlogCategory', 'Categories', 'BlogPosts')
);
$tags = GridField::create(
"Tags",
_t("Blog.Tags", "Tags"),
$self->Tags(),
- $config
+ GridFieldCategorisationConfig::create(15, $self->Categories(), 'BlogTag', 'Tags', 'BlogPosts')
);
- $fields->addFieldsToTab("Root.BlogOptions", array(
+ $fields->addFieldsToTab("Root.Categorisation", array(
$categories,
$tags
));
});
-
+
$fields = parent::getCMSFields();
+
return $fields;
}
@@ -122,6 +119,7 @@ class Blog extends Page implements PermissionProvider {
* Check if this member is an editor of the blog
*
* @param Member $member
+ *
* @return boolean
*/
public function isEditor($member) {
@@ -134,6 +132,7 @@ class Blog extends Page implements PermissionProvider {
* Check if this member is a writer of the blog
*
* @param Member $member
+ *
* @return boolean
*/
public function isWriter($member) {
@@ -146,6 +145,7 @@ class Blog extends Page implements PermissionProvider {
* Check if this member is a contributor of the blog
*
* @param Member $member
+ *
* @return boolean
*/
public function isContributor($member) {
@@ -161,6 +161,7 @@ class Blog extends Page implements PermissionProvider {
* E.g. `Hello $RoleOf($CurrentMember.ID)`
*
* @param Member|integer $member
+ *
* @return string|null Author, Editor, Writer, Contributor, or null if no role
*/
public function RoleOf($member) {
@@ -178,6 +179,7 @@ class Blog extends Page implements PermissionProvider {
*
* @param Member $member
* @param DataList $list Relation to check
+ *
* @return boolean
*/
protected function isMemberOf($member, $list) {
@@ -191,11 +193,10 @@ class Blog extends Page implements PermissionProvider {
}
-
public function canEdit($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
-
+
// Allow editors to edit this page
if($this->isEditor($member)) return true;
@@ -206,6 +207,7 @@ class Blog extends Page implements PermissionProvider {
* Determine if this user can edit the editors list
*
* @param Member $member
+ *
* @return boolean
*/
public function canEditEditors($member = null) {
@@ -222,6 +224,7 @@ class Blog extends Page implements PermissionProvider {
* Determine if this user can edit writers list
*
* @param Member $member
+ *
* @return boolean
*/
public function canEditWriters($member = null) {
@@ -242,12 +245,13 @@ class Blog extends Page implements PermissionProvider {
* Determines if this user can edit the contributors list
*
* @param type $member
+ *
* @return boolean
*/
public function canEditContributors($member = null) {
$member = $member ?: Member::currentUser();
if(is_numeric($member)) $member = Member::get()->byID($member);
-
+
$extended = $this->extendedCan('canEditContributors', $member);
if($extended !== null) return $extended;
@@ -273,7 +277,7 @@ class Blog extends Page implements PermissionProvider {
public function getSettingsFields() {
$fields = parent::getSettingsFields();
- $fields->addFieldToTab("Root.Settings",
+ $fields->addFieldToTab("Root.Settings",
NumericField::create("PostsPerPage", _t("Blog.PostsPerPage", "Posts Per Page"))
);
@@ -328,11 +332,11 @@ class Blog extends Page implements PermissionProvider {
Update any BlogPost they have authored or have been assigned to
');
-
+
if(!$this->canEditContributors()) {
$contributorField = $contributorField->performDisabledTransformation();
}
-
+
$fields->addFieldsToTab('Root.Users', array(
$editorField,
$writerField,
@@ -347,7 +351,7 @@ class Blog extends Page implements PermissionProvider {
* Return blog posts
*
* @return DataList of BlogPost objects
- **/
+ **/
public function getBlogPosts() {
$blogPosts = BlogPost::get()->filter("ParentID", $this->ID);
//Allow decorators to manipulate list
@@ -356,7 +360,6 @@ class Blog extends Page implements PermissionProvider {
}
-
/**
* Returns blogs posts for a given date period.
*
@@ -365,7 +368,7 @@ class Blog extends Page implements PermissionProvider {
* @param $day int
*
* @return DataList
- **/
+ **/
public function getArchivedBlogPosts($year, $month = null, $day = null) {
$query = $this->getBlogPosts()->dataQuery();
@@ -387,8 +390,9 @@ class Blog extends Page implements PermissionProvider {
/**
* Get a link to a Member profile.
- *
+ *
* @param urlSegment
+ *
* @return String
*/
public function ProfileLink($urlSegment) {
@@ -406,7 +410,6 @@ class Blog extends Page implements PermissionProvider {
}
-
/**
* This overwrites lumberjacks default gridfield config.
*
@@ -499,7 +502,6 @@ class Blog extends Page implements PermissionProvider {
}
-
/**
* Blog Controller
*
@@ -507,7 +509,7 @@ class Blog extends Page implements PermissionProvider {
* @subpackage blog
*
* @author Michael Strong
-**/
+ **/
class Blog_Controller extends Page_Controller {
private static $allowed_actions = array(
@@ -531,15 +533,14 @@ class Blog_Controller extends Page_Controller {
);
- /**
+ /**
* The current Blog Post DataList query.
*
* @var DataList
- **/
+ **/
protected $blogPosts;
-
public function index() {
$this->blogPosts = $this->getBlogPosts();
return $this->render();
@@ -549,7 +550,7 @@ class Blog_Controller extends Page_Controller {
* Renders a Blog Member's profile.
*
* @return SS_HTTPResponse
- **/
+ **/
public function profile() {
$profile = $this->getCurrentProfile();
@@ -564,9 +565,9 @@ class Blog_Controller extends Page_Controller {
/**
* Get the Member associated with the current URL segment.
- *
+ *
* @return Member|null
- **/
+ **/
public function getCurrentProfile() {
$urlSegment = $this->request->param('URLSegment');
@@ -581,9 +582,9 @@ class Blog_Controller extends Page_Controller {
/**
* Get posts related to the current Member profile
- *
+ *
* @return DataList|null
- **/
+ **/
public function getCurrentProfilePosts() {
$profile = $this->getCurrentProfile();
@@ -598,7 +599,7 @@ class Blog_Controller extends Page_Controller {
* Renders an archive for a specificed date. This can be by year or year/month
*
* @return SS_HTTPResponse
- **/
+ **/
public function archive() {
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
@@ -622,12 +623,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Renders the blog posts for a given tag.
*
* @return SS_HTTPResponse
- **/
+ **/
public function tag() {
$tag = $this->getCurrentTag();
if($tag) {
@@ -638,12 +638,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Renders the blog posts for a given category
*
* @return SS_HTTPResponse
- **/
+ **/
public function category() {
$category = $this->getCurrentCategory();
if($category) {
@@ -664,7 +663,7 @@ class Blog_Controller extends Page_Controller {
if($filter) {
$title = "{$title} - {$filter}";
}
-
+
$this->extend('updateMetaTitle', $title);
return $title;
}
@@ -725,7 +724,7 @@ class Blog_Controller extends Page_Controller {
if($this->owner->getArchiveYear()) {
if($this->owner->getArchiveDay()) {
$date = $this->owner->getArchiveDate()->Nice();
- } elseif($this->owner->getArchiveMonth ()) {
+ } elseif($this->owner->getArchiveMonth()) {
$date = $this->owner->getArchiveDate()->format("F, Y");
} else {
$date = $this->owner->getArchiveDate()->format("Y");
@@ -751,7 +750,7 @@ class Blog_Controller extends Page_Controller {
* Displays an RSS feed of blog posts
*
* @return string HTML
- **/
+ **/
public function rss() {
$rss = new RSSFeed($this->getBlogPosts(), $this->Link(), $this->MetaTitle, $this->MetaDescription);
$this->extend('updateRss', $rss);
@@ -759,12 +758,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Returns a list of paginated blog posts based on the blogPost dataList
*
* @return PaginatedList
- **/
+ **/
public function PaginatedList() {
$posts = new PaginatedList($this->blogPosts);
@@ -783,12 +781,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Tag Getter for use in templates.
*
* @return BlogTag|null
- **/
+ **/
public function getCurrentTag() {
$tag = $this->request->param("Tag");
if($tag) {
@@ -800,12 +797,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Category Getter for use in templates.
*
* @return BlogCategory|null
- **/
+ **/
public function getCurrentCategory() {
$category = $this->request->param("Category");
if($category) {
@@ -817,12 +813,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Fetches the archive year from the url
*
* @return int|null
- **/
+ **/
public function getArchiveYear() {
$year = $this->request->param("Year");
if(preg_match("/^[0-9]{4}$/", $year)) {
@@ -832,12 +827,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Fetches the archive money from the url.
*
* @return int|null
- **/
+ **/
public function getArchiveMonth() {
$month = $this->request->param("Month");
if(preg_match("/^[0-9]{1,2}$/", $month)) {
@@ -852,12 +846,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Fetches the archive day from the url
*
* @return int|null
- **/
+ **/
public function getArchiveDay() {
$day = $this->request->param("Day");
if(preg_match("/^[0-9]{1,2}$/", $day)) {
@@ -871,12 +864,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Returns the current archive date.
*
* @return Date
- **/
+ **/
public function getArchiveDate() {
$year = $this->getArchiveYear();
$month = $this->getArchiveMonth();
@@ -896,12 +888,11 @@ class Blog_Controller extends Page_Controller {
}
-
/**
* Returns a link to the RSS feed.
*
* @return string URL
- **/
+ **/
public function getRSSLink() {
return $this->Link("rss");
}
diff --git a/css/cms.css b/css/cms.css
index 4bbf658..bd6d6b7 100755
--- a/css/cms.css
+++ b/css/cms.css
@@ -7,24 +7,20 @@
/*
* Sprite maps & Icons
*/
-/* line 48, blog-icon/*.png */
.blog-icon-sprite, .gridfield-icon .blog-icon-timer {
background-image: url('../images/blog-icon-s0a5ab5f851.png');
background-repeat: no-repeat;
}
-/* line 84, ../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/utilities/sprites/_base.scss */
.gridfield-icon .blog-icon-timer {
background-position: 0 0;
}
-/* line 20, ../scss/cms.scss */
#FeaturedImage .middleColumn {
clear: none;
float: left;
}
-/* line 25, ../scss/cms.scss */
.blog-admin-sidebar {
width: 280px;
border-right: none;
@@ -34,11 +30,9 @@
bottom: 0px;
height: 100%;
}
-/* line 34, ../scss/cms.scss */
.blog-admin-sidebar .cms-panel-toggle a {
text-align: left;
}
-/* line 38, ../scss/cms.scss */
.blog-admin-sidebar ~ .blog-admin-outer {
width: 100%;
padding-right: 280px;
@@ -48,59 +42,47 @@
overflow-x: hidden;
box-sizing: border-box;
}
-/* line 47, ../scss/cms.scss */
.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset {
position: relative;
overflow: auto;
height: 100%;
width: 100%;
}
-/* line 54, ../scss/cms.scss */
.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title label {
float: none;
}
-/* line 57, ../scss/cms.scss */
.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title .middleColumn, .blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title input {
width: 100%;
max-width: 100%;
margin-left: 0;
}
-/* line 68, ../scss/cms.scss */
.blog-admin-sidebar .cms-content-view > .field + .field {
margin-top: 10px;
}
-/* line 73, ../scss/cms.scss */
.blog-admin-sidebar .cms-content-view > .field.urlsegment .preview {
padding-top: 0;
line-height: 25px;
}
-/* line 78, ../scss/cms.scss */
.blog-admin-sidebar .cms-content-view > .field.urlsegment .edit {
float: right;
}
-/* line 85, ../scss/cms.scss */
.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn > .date {
width: 60%;
}
-/* line 89, ../scss/cms.scss */
.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn > .time {
width: 36%;
float: right;
}
-/* line 94, ../scss/cms.scss */
.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn .middleColumn, .blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn input {
width: 100%;
}
-/* line 103, ../scss/cms.scss */
.blog-admin-sidebar.collapsed ~ .blog-admin-outer {
padding-right: 41px;
}
-/* line 109, ../scss/cms.scss */
.blog-admin-sidebar.cms-content-tools .cms-panel-content {
width: auto;
}
-/* line 115, ../scss/cms.scss */
.toggle-description {
text-indent: -1000000px;
display: inline-block;
@@ -110,14 +92,12 @@
margin-left: 4px;
}
-/* line 124, ../scss/cms.scss */
.middleColumn.toggle-description-correct-middle {
margin-left: 0;
float: left;
width: 416px;
}
-/* line 130, ../scss/cms.scss */
label.right.toggle-description-correct-right {
display: inline-block;
margin-left: 0;
@@ -125,22 +105,26 @@ label.right.toggle-description-correct-right {
float: left;
}
-/* line 137, ../scss/cms.scss */
.description.toggle-description-correct-description {
width: 416px;
padding: 12px 0;
}
-/* line 144, ../scss/cms.scss */
.custom-summary .ui-accordion-content .field {
margin: 0;
}
-/* line 148, ../scss/cms.scss */
.custom-summary .ui-accordion-content,
.custom-summary .ui-accordion-content .field {
padding: 0;
}
-/* line 153, ../scss/cms.scss */
.custom-summary .ui-icon-triangle-1-e {
background-position: -16px -128px;
}
+
+.cms table.ss-gridfield-table tr td.MergeAction {
+ width: 150px;
+}
+
+.cms table.ss-gridfield-table tr td.MergeAction select {
+ width: 75px;
+}
diff --git a/js/merge-action.js b/js/merge-action.js
new file mode 100644
index 0000000..74530b8
--- /dev/null
+++ b/js/merge-action.js
@@ -0,0 +1,44 @@
+/**
+ * Register expandable help text functions with fields.
+ */
+(function ($) {
+
+ $.entwine('ss', function ($) {
+
+ $('.MergeAction').entwine({
+ 'onadd': function() {
+ var $this = $(this);
+
+ $this.on('click', 'select', function() {
+ return false;
+ });
+
+ $this.children('button').each(function(i, button) {
+ var $button = $(button);
+ var $select = $button.prev('select');
+
+ $button.before('');
+ });
+
+ $this.on('change', 'select', function(e) {
+ var $target = $(e.target);
+
+ $target.next('input').val($target.val());
+ });
+
+ $this.children('button, select').hide();
+
+ $this.on('click', '.MergeActionReveal', function(e) {
+ var $target = $(e.target);
+
+ $target.parent().children('button, select').show();
+ $target.hide();
+
+ return false;
+ });
+ }
+ })
+
+ });
+
+}(jQuery));
diff --git a/scss/cms.scss b/scss/cms.scss
index a6840a1..d9159ec 100755
--- a/scss/cms.scss
+++ b/scss/cms.scss
@@ -1,12 +1,10 @@
/**
* CMS Styles
*/
-
/**
* Include Compass framework
*/
@import "compass";
-
/*
* Sprite maps & Icons
*/
@@ -56,7 +54,7 @@
}
.middleColumn, input {
width: 100%;
- max-width:100%;
+ max-width: 100%;
margin-left: 0;
}
}
@@ -88,7 +86,7 @@
> .time {
width: 36%;
- float:right;
+ float: right;
}
.middleColumn, input {
@@ -140,7 +138,6 @@ label.right.toggle-description-correct-right {
}
.custom-summary {
-
.ui-accordion-content .field {
margin: 0;
}
@@ -153,5 +150,12 @@ label.right.toggle-description-correct-right {
.ui-icon-triangle-1-e {
background-position: -16px -128px;
}
+}
-}
\ No newline at end of file
+.cms table.ss-gridfield-table tr td.MergeAction {
+ width: 150px;
+}
+
+.cms table.ss-gridfield-table tr td.MergeAction select {
+ width: 75px;
+}