initial commit

This commit is contained in:
micmania1 2013-07-21 11:23:35 +01:00
commit 2201af5c74
15 changed files with 690 additions and 0 deletions

1
_config.php Executable file
View File

@ -0,0 +1 @@
<?php

6
_config/config.yml Executable file
View File

@ -0,0 +1,6 @@
---
Name: silverstripe-blog
---
Blog:
extensions:
- 'BlogPostFilter'

65
extensions/BlogPostFilter.php Executable file
View File

@ -0,0 +1,65 @@
<?php
/**
* Base extension of BlogPost.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <micmania@hotmail.co.uk>
*
**/
class BlogPostFilter extends Hierarchy {
/**
* Augments (@link Hierarchy::stageChildren()}
*
* @param $staged DataList
* @param $showAll boolean
**/
public function stageChildren($showAll = false) {
$staged = parent::stageChildren($showAll);
$controller = Controller::curr();
if($controller->class == "CMSPagesController" && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"))) {
return $staged->exclude("ClassName", $this->owner->getExcludedSiteTreeClassNames());
} else if(in_array($this->owner->ClassName, ClassInfo::subClassesFor("Blog")) && !Permission::check("VIEW_DRAFT_CONTENT")) {
// Get the current stage.
$stage = Versioned::current_stage();
if($stage == "Stage") $stage = "";
else $stage = "_" . Convert::raw2sql($stage);
$dataQuery = $staged->dataQuery()
->innerJoin("BlogPost", "BlogPost" . $stage . ".ID = SiteTree" . $stage . ".ID")
->where("PublishDate < NOW()");
$staged = $staged->setDataQuery($dataQuery);
}
return $staged;
}
/**
* Augments (@link Hierarchy::liveChildren()}
*
* @param $staged DataList
* @param $showAll boolean
**/
public function liveChildren($showAll = false, $onlyDeletedFromStage = false) {
$staged = parent::liveChildren($showAll, $onlyDeletedFromStage);
$controller = Controller::curr();
if($controller->class == "CMSPagesController" && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"))) {
return $staged->exclude("ClassName", $this->owner->getExcludedSiteTreeClassNames());
} else if(in_array($this->owner->ClassName, ClassInfo::subClassesFor("Blog")) && !Permission::check("VIEW_DRAFT_CONTENT")) {
$dataQuery = $staged->dataQuery()
->innerJoin("BlogPost", "BlogPost_Live.ID = SiteTree_Live.ID")
->where("PublishDate < NOW()");
$staged = $staged->setDataQuery($dataQuery);
}
return $staged;
}
}

5
forms/AjaxTextField.php Executable file
View File

@ -0,0 +1,5 @@
<?php
class AjaxTextField extends TextField {
}

View File

@ -0,0 +1,140 @@
<?php
/**
* Adds a component which allows a user to add a new DataObject by database field.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <micmania@hotmail.co.uk>
**/
class GridFieldAddByDBField implements GridField_ActionProvider, GridField_HTMLProvider {
/**
* HTML Fragment to render the field.
*
* @var string
**/
protected $targetFragment;
/**
* Default field to create the dataobject by should be Title.
*
* @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 $targetFragment string
**/
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
**/
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName == "add") {
$dbField = $this->getDataObjectField();
$objClass = $gridField->getModelClass();
$obj = new $objClass();
if($obj->hasField($dbField)) {
$obj->setCastedField($dbField, $data['gridfieldaddbydbfield'][$obj->ClassName][$dbField]);
$id = $gridField->getList()->add($obj);
if(!$id) {
$gridField->setError(_t("GridFieldAddByDBField.ADDFAIL", "Unable to save " . $obj->Title . " to the database."));
}
} else {
throw new UnexpectedValueException("Invalid field (" . $dbField . ") on " . $obj->ClassName . ".");
}
}
}
/**
* Renders the TextField and add button to the GridField.
*
* @param $girdField GridField
*
* @return string HTML
**/
public function getHTMLFragments($gridField) {
$dataClass = $gridField->getList()->dataClass();
$obj = singleton($dataClass);
$dbField = $this->getDataObjectField();
$textField = TextField::create("gridfieldaddbydbfield[" . $obj->ClassName . "][" . Convert::raw2htmlatt($dbField) . "]")
->setAttribute("placeholder", $obj->fieldLabel($dbField))
->addExtraClass("no-change-track");
$addAction = new GridField_FormAction($gridField, 'add',
sprintf(_t('GridField.ADD', "Add %s"), $obj->i18n_singular_name()), 'add', 'add');
$addAction->setAttribute('data-icon', 'add');
// Start thinking about rending this back to the GF
$forTemplate = new ArrayData(array());
$forTemplate->Fields = new ArrayList();
$forTemplate->Fields->push($textField);
$forTemplate->Fields->push($addAction);
return array(
$this->targetFragment => $forTemplate->renderWith("GridFieldAddByDBField")
);
}
/**
* Returns the database field for which we'll add the new data object.
*
* @return string
**/
public function getDataObjectField() {
return $this->dataObjectField;
}
/**
* Set the database field.
*
* @param $field string
**/
public function setDataObjectField($field) {
$this->dataObjectField = (string) $field;
}
}

View File

@ -0,0 +1,15 @@
<?php
class GridFieldConfig_AddByDBField extends GridFieldConfig_RecordEditor {
public function __construct($itemsPerPage = null, $dataObjectField = "Title") {
parent::__construct($itemsPerPage);
// Remove uneccesary components
$this->removeComponentsByType("GridFieldAddNewButton");
// Add new components
$this->addComponent(new GridFieldAddByDBField("buttons-before-left", $dataObjectField));
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* GirdField config necessary for managing a SiteTree object.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael String <micmania@hotmail.co.uk>
**/
class GridFieldConfig_SiteTree extends GridFieldConfig {
public function __construct($itemsPerPage = null) {
parent::__construct($itemsPerPage);
$this->addComponent(new GridFieldButtonRow('before'));
$this->addComponent(new GridFieldSiteTreeAddNewButton('buttons-before-left'));
$this->addComponent(new GridFieldToolbarHeader());
$this->addComponent($sort = new GridFieldSortableHeader());
$this->addComponent($filter = new GridFieldFilterHeader());
$this->addComponent(new GridFieldDataColumns());
$this->addComponent(new GridFieldSiteTreeEditButton());
$this->addComponent(new GridFieldPageCount('toolbar-header-right'));
$this->addComponent($pagination = new GridFieldPaginator($itemsPerPage));
$pagination->setThrowExceptionOnBadDataType(false);
}
}

View File

@ -0,0 +1,38 @@
<?php
/**
* This component provides a button for opening the add new form provided by
* {@link GridFieldDetailForm}.
*
* Only returns a button if {@link DataObject->canCreate()} for this record
* returns true.
*
* @package framework
* @subpackage fields-gridfield
*/
class GridFieldSiteTreeAddNewButton extends GridFieldAddNewButton {
public function getHTMLFragments($gridField) {
$singleton = singleton($gridField->getModelClass());
if(!$singleton->canCreate()) {
return array();
}
if(!$this->buttonName) {
// provide a default button name, can be changed by calling {@link setButtonName()} on this component
$objectName = $singleton->i18n_singular_name();
$this->buttonName = _t('GridField.Add', 'Add {name}', array('name' => $objectName));
}
$controller = $gridField->getForm()->getController();
$data = new ArrayData(array(
'NewLink' => $controller->LinkPageAdd("?ParentID=" . $controller->currentPageID()),
'ButtonName' => $this->buttonName,
));
return array(
$this->targetFragment => $data->renderWith('GridFieldAddNewbutton'),
);
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* Swaps the GridField Link out for the SiteTree edit link using {@link SiteTree::CMSEditLink()}
*
* @package silverstripe
* @subpackage blog
*
* @author Michael String <micmania@hotmail.co.uk>
**/
class GridFieldSiteTreeEditButton extends GridFieldEditButton {
/**
* @param GridField $gridField
* @param DataObject $record
* @param string $columnName
*
* @return string - the HTML for the column
*/
public function getColumnContent($gridField, $record, $columnName) {
// No permission checks, handled through GridFieldDetailForm,
// which can make the form readonly if no edit permissions are available.
$data = new ArrayData(array(
'Link' => $record->CMSEditLink()
));
return $data->renderWith('GridFieldEditButton');
}
}

25
model/BlogCategory.php Executable file
View File

@ -0,0 +1,25 @@
<?php
/**
* A blog category fo generalising blog posts.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <micmania@hotmail.co.uk>
**/
class BlogCategory extends DataObject {
private static $db = array(
"Title" => "Varchar(255)",
);
private static $has_one = array(
"Blog" => "Blog",
);
private static $many_many = array(
"BlogPosts" => "BlogPost",
);
}

25
model/BlogTag.php Executable file
View File

@ -0,0 +1,25 @@
<?php
/**
* A blog tag for keyword descriptions of a Blog post
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <micmania@hotmail.co.uk>
**/
class BlogTag extends DataObject {
private static $db = array(
"Title" => "Varchar(255)",
);
private static $has_one = array(
"Blog" => "Blog",
);
private static $many_many = array(
"BlogPosts" => "BlogPost",
);
}

189
page/Blog.php Executable file
View File

@ -0,0 +1,189 @@
<?php
/**
* Blog Holder
*
* @package silverstripe
* @subpackage blog
*
* @author Michael String <micmania@hotmail.co.uk>
**/
class Blog extends Page {
private static $has_many = array(
"Tags" => "BlogTag",
"Categories" => "BlogCategory"
);
private static $allowed_children = array(
"BlogPost"
);
/**
* Enable archive.
*
* @var boolean
**/
private static $archive_enabled = true;
/**
* Enable tags
*
* @var boolean
**/
private static $tags_enabled = true;
/**
* Enable categories
*
* @var boolean
**/
private static $categories_enabled = true;
/**
* Whether or not to show BlogPost's in a GridField. Usually this will be
* the case when they're hidden from the SiteTree.
*
* @var boolean
**/
private static $show_posts_in_gridfield = true;
public function getCMSFields() {
$fields = parent::getCMSFields();
if($this->config()->get("show_posts_in_gridfield")) {
$gridField = new GridField(
"BlogPost",
_t("Blog.FieldLabels.BlogPosts", "Blog Posts"),
$this->AllChildrenIncludingDeleted(),
GridFieldConfig_SiteTree::create()
);
$fields->addFieldToTab("Root.BlogPosts", $gridField);
}
if($this->config()->get("categories_enabled")) {
$fields->addFieldToTab("Root." . _t("Blog.CATEGORIES", "Categories"),
GridField::create(
"Categories",
_t("Blog.FieldLabels.Categories", "Categories"),
$this->Categories(),
GridFieldConfig_AddByDBField::create()
)
);
}
if($this->config()->get("tags_enabled")) {
$fields->addFieldToTab("Root." . _t("Blog.TAGS", "Tags"),
GridField::create(
"Tags",
_t("Blog.FieldLabels.Tags", "Tags"),
$this->Tags(),
GridFieldConfig_AddByDBField::create()
)
);
}
return $fields;
}
/**
* Loops through subclasses of BlogPost and checks whether they have been configured
* to be hidden. If so, then they will be excluded from the SiteTree.
*
* @return array
**/
public function getExcludedSiteTreeClassNames() {
$classes = array();
$tmpClasses = ClassInfo::subClassesFor("BlogPost");
foreach($tmpClasses as $class) {
if(!Config::inst()->get($class, "show_in_site_tree")) {
$classes[$class] = $class;
}
}
return $classes;
}
/**
* Return blogs posts
*
* @return DataList of BlogPost objects
**/
public function getBlogPosts() {
return $this->AllChildren()->filter("ClassName", ClassInfo::subClassesFor("BlogPost"));
}
}
/**
* Blog Controller
*
* @package silverstripe
* @subpackage blog
*
* @author Michael String <micmania@hotmail.co.uk>
**/
class Blog_Controller extends Page_Controller {
private static $allowed_actions = array(
'archive',
'tag',
'category',
);
private static $url_handlers = array(
'tag/$Tag' => "tag",
'category/$Category' => "category",
);
protected $blogPosts;
public function index() {
$this->blogPosts = $this->AllChildren();
return $this->render();
}
public function archive() {
return $this->render();
}
public function tag() {
$tag = $this->request->param("Tag");
if($tag) {
$tag = $this->Tags()->filter("Title", $tag)->first();
if($tag) {
$this->blogPosts = $this->AllChildren()->filter("ID", $tag->BlogPosts()->getIDList());
return $this->render();
}
}
return $this->httpError(404, "Not Found");
}
public function category() {
$category = $this->request->param("Category");
if($category) {
$category = $this->Categories()->filter("Title", $category)->first();
if($category) {
$this->blogPosts = $this->AllChildren()->filter("ID", $category->BlogPosts()->getIDList());
return $this->render();
}
}
return $this->httpError(404, "Not Found");
}
public function PaginatedPosts() {
return new PaginatedList($this->blogPosts);
}
}

100
page/BlogPost.php Executable file
View File

@ -0,0 +1,100 @@
<?php
/**
* An indivisual blog post.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <micmania@hotmail.co.uk>
**/
class BlogPost extends Page {
/**
* @var array
**/
private static $db = array(
"PublishDate" => "SS_Datetime",
);
/**
* @var array
**/
private static $allowed_children = array();
/**
* @var boolean
**/
public static $can_be_root = false;
/**
* This will display or hide the current class from the SiteTree. This
* variable can be configured using YAML.
*
* @var boolean
**/
private static $show_in_site_tree = false;
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->insertBefore(
$publishDate = DatetimeField::create("PublishDate", _t("BlogPost.FieldLabels.PublishDate", "Publish Date")),
"Content"
);
// Publish date field config.
$publishDate->getDateField()->setConfig("showcalendar", true);
return $fields;
}
/**
* If no publish date is set, set the date to now.
**/
public function onBeforeWrite() {
parent::onBeforeWrite();
if(!$this->PublishDate) $this->setCastedField("PublishDate", time());
}
/**
* Checks the publish date to see if the blog post as actually been published.
*
* @param $member Member|null
*
* @return boolean
**/
public function canView($member = null) {
if(!parent::canView($member)) return false;
if($this->PublishDate) {
$publishDate = $this->dbObject("PublishDate");
if($publishDate->InFuture() && !Permission::checkMember($member, "VIEW_DRAFT_CONTENT")) {
return false;
}
}
return true;
}
}
/**
* An indivisual blog post.
*
* @package silverstripe
* @subpackage blog
*
* @author Michael Strong <micmania@hotmail.co.uk>
**/
class BlogPost_Controller extends Page_Controller {
}

View File

@ -0,0 +1,5 @@
<div class="add-existing-autocompleter">
<% loop $Fields %>
<span>$Field</span>
<% end_loop %>
</div>

18
templates/Layout/Blog.ss Executable file
View File

@ -0,0 +1,18 @@
<% include SideBar %>
<div class="content-container unit size3of4 lastUnit">
<article>
<h1>$Title</h1>
<div class="content">$Content</div>
<% if BlogPosts %>
<ul>
<% loop BlogPosts %>
<li><a href="$Link" title="$Title">$Title</a></li>
<% end_loop %>
</ul>
<% else %>
<p>Unable to find any blog posts.</p>
<% end_if %>
</article>
$Form
$PageComments
</div>