"));
- }
-
- $fields->addFieldToTab("Root.Main", new TextField("Tags", _t("BlogEntry.TS", "Tags (comma sep.)")),"Content");
-
- $this->extend('updateCMSFields', $fields);
-
- return $fields;
+ return parent::getCMSFields();
}
/**
@@ -106,7 +113,6 @@ class BlogEntry extends Page {
* @return ArrayList List of ArrayData with Tag, Link, and URLTag keys
*/
public function TagsCollection() {
-
$tags = $this->TagNames();
$output = new ArrayList();
@@ -123,11 +129,11 @@ class BlogEntry extends Page {
return $output;
}
- function Content() {
+ public function Content() {
if(self::$allow_wysiwyg_editing) {
return $this->getField('Content');
} else {
- $parser = new BBCodeParser($this->Content);
+ $parser = BBCodeParser::create($this->Content);
$content = new HTMLText('Content');
$content->value = $parser->parse();
return $content;
@@ -135,87 +141,72 @@ class BlogEntry extends Page {
}
/**
- * To be used by RSSFeed. If RSSFeed uses Content field, it doesn't pull in correctly parsed content.
+ * To be used by RSSFeed. If RSSFeed uses Content field, it doesn't pull in correctly parsed content.
+ *
+ * @return string
*/
- function RSSContent() {
- return $this->Content();
- }
-
- /**
- * Get a bbcode parsed summary of the blog entry
- * @deprecated
- */
- function ParagraphSummary(){
- user_error("BlogEntry::ParagraphSummary() is deprecated; use BlogEntry::Content()", E_USER_NOTICE);
-
- $val = $this->Content();
- $content = $val;
-
- if(!($content instanceof HTMLText)) {
- $content = new HTMLText('Content');
- $content->value = $val;
- }
-
- return $content->FirstParagraph('html');
- }
-
- /**
- * Get the bbcode parsed content
- * @deprecated
- */
- function ParsedContent() {
- user_error("BlogEntry::ParsedContent() is deprecated; use BlogEntry::Content()", E_USER_NOTICE);
+ public function RSSContent() {
return $this->Content();
}
/**
* Link for editing this blog entry
+ *
+ * @return string Edit URL
*/
- function EditURL() {
- return ($this->getParent()) ? $this->getParent()->Link('post') . '/' . $this->ID . '/' : false;
- }
-
- function IsOwner() {
- if(method_exists($this->Parent(), 'IsOwner')) {
- return $this->Parent()->IsOwner();
+ public function EditURL() {
+ $parent = $this->getParent();
+ if($parent) {
+ return Controller::join_links($parent->Link('post'), $this->ID);
}
}
+
+ /**
+ * Returns true if the current user is an admin, or is the owner of this blog
+ * {@see BlogHolder::IsOwner}
+ *
+ * @return bool
+ */
+ public function IsOwner() {
+ $parent = $this->Parent();
+ return $parent && $parent->hasMethod('IsOwner') && $parent->IsOwner();
+ }
/**
* Call this to enable WYSIWYG editing on your blog entries.
* By default the blog uses BBCode
*/
- static function allow_wysiwyg_editing() {
+ public static function allow_wysiwyg_editing() {
self::$allow_wysiwyg_editing = true;
}
/**
- * Get the previous blog entry from this section of blog pages.
+ * Get the next oldest blog entry from this section of blog pages.
*
* @return BlogEntry
*/
- function PreviousBlogEntry() {
- return DataObject::get_one(
- 'BlogEntry',
- "\"SiteTree\".\"ParentID\" = '$this->ParentID' AND \"BlogEntry\".\"Date\" < '$this->Date'",
- true,
- 'Date DESC'
- );
+ public function PreviousBlogEntry() {
+ return BlogEntry::get()
+ ->filter('ParentID', $this->ParentID)
+ ->exclude('ID', $this->ID)
+ ->filter('Date:LessThanOrEqual', $this->Date)
+ ->sort('"BlogEntry"."Date" DESC')
+ ->first();
}
/**
- * Get the next blog entry from this section of blog pages.
+ * Get the next most recent blog entry from this section of blog pages.
*
* @return BlogEntry
*/
- function NextBlogEntry() {
- return DataObject::get_one(
- 'BlogEntry',
- "\"SiteTree\".\"ParentID\" = '$this->ParentID' AND \"BlogEntry\".\"Date\" > '$this->Date'",
- true,
- 'Date ASC'
- );
+ public function NextBlogEntry() {
+ return BlogEntry::get()
+ ->filter('ParentID', $this->ParentID)
+ ->exclude('ID', $this->ID)
+ ->filter('Date:GreaterThanOrEqual', $this->Date)
+ ->sort('"BlogEntry"."Date" ASC')
+ ->first();
}
/**
@@ -223,7 +214,7 @@ class BlogEntry extends Page {
*
* @return BlogHolder
*/
- function getBlogHolder() {
+ public function getBlogHolder() {
$holder = null;
if($this->ParentID && $this->Parent()->ClassName == 'BlogHolder') {
$holder = $this->Parent();
@@ -236,47 +227,31 @@ class BlogEntry extends Page {
class BlogEntry_Controller extends Page_Controller {
private static $allowed_actions = array(
- 'index',
- 'unpublishPost',
- 'PageComments',
- 'SearchForm'
+ 'unpublishPost'
);
- function init() {
+ public function init() {
parent::init();
- Requirements::themedCSS("blog","blog");
+ Requirements::themedCSS("blog", "blog");
}
/**
* Gets a link to unpublish the blog entry
*/
- function unpublishPost() {
+ public function unpublishPost() {
if(!$this->IsOwner()) {
Security::permissionFailure(
$this,
'Unpublishing blogs is an administrator task. Please log in.'
);
} else {
- $SQL_id = (int) $this->ID;
-
- $page = DataObject::get_by_id('SiteTree', $SQL_id);
+ $page = BlogEntry::get()->byID($this->data()->ID);
$page->deleteFromStage('Live');
$page->flushCache();
- $this->redirect($this->getParent()->Link());
+ return $this->redirect($this->getParent()->Link());
}
}
-
- /**
- * Temporary workaround for compatibility with 'comments' module
- * (has been extracted from sapphire/trunk in 12/2010).
- *
- * @return Form
- */
- function PageComments() {
- if($this->hasMethod('CommentsForm')) return $this->CommentsForm();
- else if(method_exists('Page_Controller', 'PageComments')) return parent::PageComments();
- }
}
diff --git a/code/BlogHolder.php b/code/BlogHolder.php
index 340c48a..e8dc1c0 100644
--- a/code/BlogHolder.php
+++ b/code/BlogHolder.php
@@ -34,40 +34,37 @@ class BlogHolder extends BlogTree implements PermissionProvider {
'BlogEntry'
);
- function getCMSFields() {
+ public function getCMSFields() {
$blogOwners = $this->blogOwners();
- SiteTree::disableCMSFieldsExtensions();
- $fields = parent::getCMSFields();
- SiteTree::enableCMSFieldsExtensions();
+ // Add holder fields prior to extensions being called
+ $this->beforeUpdateCMSFields(function($fields) use ($blogOwners) {
+ $fields->addFieldsToTab(
+ 'Root.Main',
+ array(
+ DropdownField::create('OwnerID', 'Blog owner', $blogOwners->map('ID', 'Name')->toArray())
+ ->setEmptyString('(None)')
+ ->setHasEmptyDefault(true),
+ CheckboxField::create('AllowCustomAuthors', 'Allow non-admins to have a custom author field'),
+ CheckboxField::create("ShowFullEntry", "Show Full Entry")
+ ->setDescription('Show full content in overviews rather than summary')
+ ),
+ "Content"
+ );
+ });
- $fields->addFieldToTab(
- 'Root.Main',
- DropdownField::create('OwnerID', 'Blog owner', $blogOwners->map('ID', 'Name')->toArray())
- ->setEmptyString('(None)')
- ->setHasEmptyDefault(true),
- "Content"
- );
- $fields->addFieldToTab('Root.Main', new CheckboxField('AllowCustomAuthors', 'Allow non-admins to have a custom author field'), "Content");
- $fields->addFieldToTab(
- "Root.Main",
- CheckboxField::create("ShowFullEntry", "Show Full Entry")
- ->setDescription('Show full content in overviews rather than summary'),
- "Content"
- );
-
- $this->extend('updateCMSFields', $fields);
-
- return $fields;
+ return parent::getCMSFields();
}
/**
* Get members who have BLOGMANAGEMENT and ADMIN permission
- */
-
- function blogOwners($sort = array('FirstName'=>'ASC','Surname'=>'ASC'), $direction = null) {
-
- $members = Permission::get_members_by_permission(array('ADMIN','BLOGMANAGEMENT'));
+ *
+ * @param array $sort
+ * @param string $direction
+ * @return SS_List
+ */
+ public function blogOwners($sort = array('FirstName'=>'ASC','Surname'=>'ASC'), $direction = null) {
+ $members = Permission::get_members_by_permission(array('ADMIN', 'BLOGMANAGEMENT'));
$members->sort($sort);
$this->extend('extendBlogOwners', $members);
@@ -86,7 +83,7 @@ class BlogHolder extends BlogTree implements PermissionProvider {
/**
* Only display the blog entries that have the specified tag
*/
- function ShowTag() {
+ public function ShowTag() {
if($this->request->latestParam('Action') == 'tag') {
return Convert::raw2xml(Director::urlParam('ID'));
}
@@ -95,30 +92,30 @@ class BlogHolder extends BlogTree implements PermissionProvider {
/**
* Check if url has "/post"
*/
- function isPost() {
+ public function isPost() {
return $this->request->latestParam('Action') == 'post';
}
/**
* Link for creating a new blog entry
*/
- function postURL(){
+ public function postURL() {
return $this->Link('post');
}
/**
* Returns true if the current user is an admin, or is the owner of this blog
*
- * @return Boolean
+ * @return bool
*/
- function IsOwner() {
+ public function IsOwner() {
return (Permission::check('BLOGMANAGEMENT') || Permission::check('ADMIN'));
}
/**
* Create default blog setup
*/
- function requireDefaultRecords() {
+ public function requireDefaultRecords() {
parent::requireDefaultRecords();
// Skip creation of default records
@@ -179,7 +176,7 @@ class BlogHolder extends BlogTree implements PermissionProvider {
}
}
- function providePermissions() {
+ public function providePermissions() {
return array("BLOGMANAGEMENT" => "Blog management");
}
}
@@ -196,7 +193,7 @@ class BlogHolder_Controller extends BlogTree_Controller {
'BlogEntryForm' => 'BLOGMANAGEMENT',
);
- function init() {
+ public function init() {
parent::init();
Requirements::themedCSS("bbcodehelp");
}
@@ -204,14 +201,14 @@ class BlogHolder_Controller extends BlogTree_Controller {
/**
* Return list of usable tags for help
*/
- function BBTags() {
+ public function BBTags() {
return BBCodeParser::usable_tags();
}
/**
* Post a new blog entry
*/
- function post(){
+ public function post(){
if(!Permission::check('BLOGMANAGEMENT')) return Security::permissionFailure();
$page = $this->customise(array(
'Content' => false,
@@ -223,62 +220,74 @@ class BlogHolder_Controller extends BlogTree_Controller {
/**
* A simple form for creating blog entries
+ *
+ * @return Form
*/
- function BlogEntryForm() {
+ public function BlogEntryForm() {
if(!Permission::check('BLOGMANAGEMENT')) return Security::permissionFailure();
- $id = 0;
- if($this->request->latestParam('ID')) {
- $id = (int) $this->request->latestParam('ID');
- }
-
- $codeparser = new BBCodeParser();
+ $codeparser = BBCodeParser::create();
$membername = Member::currentUser() ? Member::currentUser()->getName() : "";
if(BlogEntry::$allow_wysiwyg_editing) {
- $contentfield = new HtmlEditorField("BlogPost", _t("BlogEntry.CN"));
+ $contentfield = HtmlEditorField::create("BlogPost", _t("BlogEntry.CN"));
} else {
- $contentfield = new CompositeField(
- new LiteralField("BBCodeHelper",""._t("BlogEntry.BBH")."" ),
- new TextareaField("BlogPost", _t("BlogEntry.CN"),20), // This is called BlogPost as the id #Content is generally used already
- new LiteralField("BBCodeTags","
".$codeparser->useable_tagsHTML()."
")
+ $contentfield = CompositeField::create(
+ LiteralField::create(
+ "BBCodeHelper",
+ ""._t("BlogEntry.BBH").""
+ ),
+ TextareaField::create(
+ "BlogPost",
+ _t("BlogEntry.CN"),
+ 20
+ ), // This is called BlogPost as the id #Content is generally used already
+ LiteralField::create(
+ "BBCodeTags",
+ "
".$codeparser->useable_tagsHTML()."
"
+ )
);
}
+
+ // Support for https://github.com/chillu/silverstripe-tagfield
if(class_exists('TagField')) {
- $tagfield = new TagField('Tags', null, null, 'BlogEntry');
+ $tagfield = TagField::create('Tags', null, null, 'BlogEntry');
$tagfield->setSeparator(', ');
} else {
- $tagfield = new TextField('Tags');
+ $tagfield = TextField::create('Tags');
}
$field = 'TextField';
if(!$this->AllowCustomAuthors && !Permission::check('ADMIN')) {
$field = 'ReadonlyField';
}
- $fields = new FieldList(
- new HiddenField("ID", "ID"),
- new TextField("Title", _t('BlogHolder.SJ', "Subject")),
- new $field("Author", _t('BlogEntry.AU'), $membername),
+ $fields = FieldList::create(
+ HiddenField::create("ID", "ID"),
+ TextField::create("Title", _t('BlogHolder.SJ', "Subject")),
+ $field::create("Author", _t('BlogEntry.AU'), $membername),
$contentfield,
$tagfield,
- new LiteralField("Tagsnote"," ")
+ LiteralField::create(
+ "Tagsnote",
+ " "
+ )
);
- $submitAction = new FormAction('postblog', _t('BlogHolder.POST', 'Post blog entry'));
+ $submitAction = FormAction::create('postblog', _t('BlogHolder.POST', 'Post blog entry'));
- $actions = new FieldList($submitAction);
- $validator = new RequiredFields('Title','BlogPost');
+ $actions = FieldList::create($submitAction);
+ $validator = RequiredFields::create('Title','BlogPost');
- $form = new Form($this, 'BlogEntryForm',$fields, $actions,$validator);
+ $form = Form::create($this, 'BlogEntryForm', $fields, $actions, $validator);
- if($id != 0) {
- $entry = DataObject::get_by_id('BlogEntry', $id);
+ $id = (int) $this->request->latestParam('ID');
+ if($id) {
+ $entry = BlogEntry::get()->byID($id);
if($entry->IsOwner()) {
$form->loadDataFrom($entry);
$form->Fields()->fieldByName('BlogPost')->setValue($entry->Content);
-
}
} else {
$form->loadDataFrom(array("Author" => Cookie::get("BlogHolder_Name")));
@@ -287,22 +296,18 @@ class BlogHolder_Controller extends BlogTree_Controller {
return $form;
}
- function postblog($data, $form) {
+ public function postblog($data, $form) {
if(!Permission::check('BLOGMANAGEMENT')) return Security::permissionFailure();
Cookie::set("BlogHolder_Name", $data['Author']);
$blogentry = false;
- if(isset($data['ID']) && $data['ID']) {
- $blogentry = DataObject::get_by_id("BlogEntry", $data['ID']);
- if(!$blogentry->IsOwner()) {
- unset($blogentry);
- }
+ if(!empty($data['ID'])) {
+ $candidate = BlogEntry::get()->byID($data['ID']);
+ if($candidate->IsOwner()) $blogentry = $candidate;
}
- if(!$blogentry) {
- $blogentry = new BlogEntry();
- }
+ if(!$blogentry) $blogentry = BlogEntry::create();
$form->saveInto($blogentry);
$blogentry->ParentID = $this->ID;
@@ -313,8 +318,11 @@ class BlogHolder_Controller extends BlogTree_Controller {
$blogentry->Locale = $this->Locale;
}
- $blogentry->writeToStage("Stage");
+ $oldMode = Versioned::get_reading_mode();
+ Versioned::reading_stage('Stage');
+ $blogentry->write();
$blogentry->publish("Stage", "Live");
+ Versioned::set_reading_mode($oldMode);
$this->redirect($this->Link());
}
diff --git a/code/BlogLeftMainExtension.php b/code/BlogLeftMainExtension.php
index 32fa014..cf2fc4f 100644
--- a/code/BlogLeftMainExtension.php
+++ b/code/BlogLeftMainExtension.php
@@ -4,36 +4,44 @@
* Adds author and "post date" fields.
*/
class BlogLeftMainExtension extends Extension {
- function updateListView($listView) {
+
+ /**
+ * {@see CMSMain::ListViewForm}
+ *
+ * @param type $listView
+ * @return type
+ */
+ public function updateListView($listView) {
$parentId = $listView->getController()->getRequest()->requestVar('ParentID');
- $parent = ($parentId) ? Page::get()->byId($parentId) : new Page();
+ if(!$parentId) return;
// Only apply logic for this page type
- if($parent && $parent instanceof BlogHolder) {
- $gridField = $listView->Fields()->dataFieldByName('Page');
- if($gridField) {
- // Sort by post date
- $list = $gridField->getList();
- $list = $list->leftJoin('BlogEntry', '"BlogEntry"."ID" = "SiteTree"."ID"');
- $gridField->setList($list->sort('Date', 'DESC'));
+ $parent = BlogHolder::get()->byId($parentId);
+ if(!$parent) return;
- // Change columns
- $cols = $gridField->getConfig()->getComponentByType('GridFieldDataColumns');
- if($cols) {
- $fields = $cols->getDisplayFields($gridField);
- $castings = $cols->getFieldCasting($gridField);
-
- // Add author to columns
- $fields['Author'] = _t("BlogEntry.AU", "Author");
- // Add post date and remove duplicate "created" date
- $fields['Date'] = _t("BlogEntry.DT", "Date");
- $castings['Date'] = 'SS_Datetime->Ago';
- if(isset($fields['Created'])) unset($fields['Created']);
-
- $cols->setDisplayFields($fields);
- $cols->setFieldCasting($castings);
- }
- }
- }
+ $gridField = $listView->Fields()->dataFieldByName('Page');
+ if(!$gridField) return;
+
+ // Sort by post date
+ $list = $gridField->getList();
+ $list = $list->leftJoin('BlogEntry', '"BlogEntry"."ID" = "SiteTree"."ID"');
+ $gridField->setList($list->sort('Date', 'DESC'));
+
+ // Change columns
+ $cols = $gridField->getConfig()->getComponentByType('GridFieldDataColumns');
+ if(!$cols) return;
+
+ $fields = $cols->getDisplayFields($gridField);
+ $castings = $cols->getFieldCasting($gridField);
+
+ // Add author to columns
+ $fields['Author'] = _t("BlogEntry.AU", "Author");
+ // Add post date and remove duplicate "created" date
+ $fields['Date'] = _t("BlogEntry.DT", "Date");
+ $castings['Date'] = 'SS_Datetime->Ago';
+ if(isset($fields['Created'])) unset($fields['Created']);
+
+ $cols->setDisplayFields($fields);
+ $cols->setFieldCasting($castings);
}
}
\ No newline at end of file
diff --git a/code/BlogTree.php b/code/BlogTree.php
index e5310ad..7cc2775 100644
--- a/code/BlogTree.php
+++ b/code/BlogTree.php
@@ -1,11 +1,11 @@
- 'Varchar(255)',
'LandingPageFreshness' => 'Varchar',
);
-
- private static $defaults = array(
- );
-
- private static $has_one = array();
- private static $has_many = array();
-
private static $allowed_children = array(
- 'BlogTree', 'BlogHolder'
+ 'BlogTree',
+ 'BlogHolder'
);
/*
@@ -48,179 +47,181 @@ class BlogTree extends Page {
* uses current
* @return BlogTree
*/
- static function current($page = null) {
-
+ public static function current($page = null) {
+ // extract page from current request if not specified
if (!$page && Controller::has_curr()) {
$controller = Controller::curr();
if ($controller->hasMethod('data')) {
$page = $controller->data();
}
}
-
+
if ($page) {
// If we _are_ a BlogTree, use us
if ($page instanceof BlogTree) return $page;
-
+
// If page is a virtual page use that
- if($page instanceof VirtualPage && $page->CopyContentFrom() instanceof BlogTree) return $page;
+ if($page instanceof VirtualPage && $page->CopyContentFrom() instanceof BlogTree) {
+ return $page;
+ }
// Or, if we a a BlogEntry underneath a BlogTree, use our parent
- if($page->is_a("BlogEntry")) {
- $parent = $page->getParent();
- if($parent instanceof BlogTree) return $parent;
+ if($page instanceof BlogEntry && $page->getParent() instanceof BlogTree) {
+ return $page->getParent();
}
}
-
+
// Try to find a top-level BlogTree
- $top = DataObject::get_one('BlogTree', "\"ParentID\" = '0'");
+ $top = BlogTree::get()->filter("ParentID", 0)->first();
if($top) return $top;
-
+
// Try to find any BlogTree that is not inside another BlogTree
- if($blogTrees=DataObject::get('BlogTree')) foreach($blogTrees as $tree) {
+ $blogTrees = BlogTree::get();
+ foreach($blogTrees as $tree) {
if(!($tree->getParent() instanceof BlogTree)) return $tree;
}
-
+
// This shouldn't be possible, but assuming the above fails, just return anything you can get
return $blogTrees->first();
}
- /* ----------- ACCESSOR OVERRIDES -------------- */
-
- public function getLandingPageFreshness() {
- $freshness = $this->getField('LandingPageFreshness');
- // If we want to inherit freshness, try that first
- if ($freshness == "INHERIT" && $this->getParent()) $freshness = $this->getParent()->LandingPageFreshness;
- // If we don't have a parent, or the inherited result was still inherit, use default
- if ($freshness == "INHERIT") $freshness = '';
+ /**
+ * Calculates number of months of landing page freshness to show
+ *
+ * @return int Number of months, if filtered
+ */
+ public function getLandingPageFreshnessMonths() {
+ $freshness = $this->LandingPageFreshness;
+
+ // Substitute 'INHERIT' for parent freshness, if available
+ if ($freshness === "INHERIT") {
+ $freshness = (($parent = $this->getParent()) && $parent instanceof BlogTree)
+ ? $parent->getLandingPageFreshnessMonths()
+ : null;
+ }
return $freshness;
}
-
+
/* ----------- CMS CONTROL -------------- */
-
- function getSettingsFields() {
+
+ public function getSettingsFields() {
$fields = parent::getSettingsFields();
$fields->addFieldToTab(
- 'Root.Settings',
+ 'Root.Settings',
new DropdownField(
- 'LandingPageFreshness',
- 'When you first open the blog, how many entries should I show',
- array(
- "" => "All entries",
- "1" => "Last month's entries",
- "2" => "Last 2 months' entries",
- "3" => "Last 3 months' entries",
- "4" => "Last 4 months' entries",
- "5" => "Last 5 months' entries",
- "6" => "Last 6 months' entries",
- "7" => "Last 7 months' entries",
- "8" => "Last 8 months' entries",
- "9" => "Last 9 months' entries",
- "10" => "Last 10 months' entries",
- "11" => "Last 11 months' entries",
- "12" => "Last year's entries",
+ 'LandingPageFreshness',
+ 'When you first open the blog, how many entries should I show',
+ array(
+ "" => "All entries",
+ "1" => "Last month's entries",
+ "2" => "Last 2 months' entries",
+ "3" => "Last 3 months' entries",
+ "4" => "Last 4 months' entries",
+ "5" => "Last 5 months' entries",
+ "6" => "Last 6 months' entries",
+ "7" => "Last 7 months' entries",
+ "8" => "Last 8 months' entries",
+ "9" => "Last 9 months' entries",
+ "10" => "Last 10 months' entries",
+ "11" => "Last 11 months' entries",
+ "12" => "Last year's entries",
"INHERIT" => "Take value from parent Blog Tree"
)
)
- );
+ );
return $fields;
}
-
+
/* ----------- New accessors -------------- */
-
+
public function loadDescendantBlogHolderIDListInto(&$idList) {
if ($children = $this->AllChildren()) {
foreach($children as $child) {
if(in_array($child->ID, $idList)) continue;
-
+
if($child instanceof BlogHolder) {
- $idList[] = $child->ID;
+ $idList[] = $child->ID;
} elseif($child instanceof BlogTree) {
$child->loadDescendantBlogHolderIDListInto($idList);
- }
+ }
}
}
}
-
- // Build a list of all IDs for BlogHolders that are children of us
+
+ /**
+ * Build a list of all IDs for BlogHolders that are children of us
+ *
+ * @return array
+ */
public function BlogHolderIDs() {
$holderIDs = array();
$this->loadDescendantBlogHolderIDListInto($holderIDs);
return $holderIDs;
}
-
+
/**
* Get entries in this blog.
- *
- * @param string $limit A clause to insert into the limit clause.
+ *
+ * @param string $limit Page size of paginated list
* @param string $tag Only get blog entries with this tag
* @param string $date Only get blog entries on this date - either a year, or a year-month eg '2008' or '2008-02'
- * @param callable $retrieveCallback A function to call with pagetype, filter and limit for custom blog
- * sorting or filtering
- * @param string $filter Filter condition
+ * @param array $filters A list of DataList compatible filters
+ * @param mixed $where Raw SQL WHERE condition(s)
* @return PaginatedList The list of entries in a paginated list
*/
- public function Entries($limit = '', $tag = '', $date = '', $retrieveCallback = null, $filter = '') {
-
- $tagCheck = '';
- $dateCheck = '';
-
- if($tag) {
- $SQL_tag = Convert::raw2sql($tag);
- $tagCheck = "AND \"BlogEntry\".\"Tags\" LIKE '%$SQL_tag%'";
- }
+ public function Entries($limit = '', $tag = '', $date = '', $filters = array(), $where = '') {
+ // Filter by all current blog holder parents, if any are available
+ $holderIDs = $this->BlogHolderIDs();
+ if(empty($holderIDs)) return false;
- if($date) {
- // Some systems still use the / seperator for date presentation
- if( strpos($date, '-') ) $seperator = '-';
- elseif( strpos($date, '/') ) $seperator = '/';
-
- if(isset($seperator) && !empty($seperator)) {
- // The 2 in the explode argument will tell it to only create 2 elements
- // i.e. in this instance the $year and $month fields respectively
- list($year,$month) = explode( $seperator, $date, 2);
-
- $year = (int)$year;
- $month = (int)$month;
+ // Build filtered list
+ $entries = BlogEntry::get()
+ ->filter('ParentID', $holderIDs)
+ ->sort($order = '"BlogEntry"."Date" DESC');
- if($year && $month) {
- if(method_exists(DB::getConn(), 'formattedDatetimeClause')) {
- $db_date=DB::getConn()->formattedDatetimeClause('"BlogEntry"."Date"', '%m');
- $dateCheck = "AND CAST($db_date AS " . DB::getConn()->dbDataType('unsigned integer') . ") = $month AND " . DB::getConn()->formattedDatetimeClause('"BlogEntry"."Date"', '%Y') . " = '$year'";
- } else {
- $dateCheck = "AND MONTH(\"BlogEntry\".\"Date\") = '$month' AND YEAR(\"BlogEntry\".\"Date\") = '$year'";
- }
- }
- } else {
- $year = (int) $date;
- if($year) {
- if(method_exists(DB::getConn(), 'formattedDatetimeClause')) {
- $dateCheck = "AND " . DB::getConn()->formattedDatetimeClause('"BlogEntry"."Date"', '%Y') . " = '$year'";
- } else {
- $dateCheck = "AND YEAR(\"BlogEntry\".\"Date\") = '$year'";
- }
- }
+ // Apply where condition
+ if($where) $entries = $entries->where($where);
+
+ // Add tag condition
+ if($tag) $entries = $entries->filter('Tags:PartialMatch', $tag);
+
+ // Add date condition
+ if($date && preg_match('/^(?\d+)([-\\/](?\d+))?/', $date, $matches)) {
+ // Add year filter
+ $yearExpression = DB::get_conn()->formattedDatetimeClause('"BlogEntry"."Date"', '%Y');
+ $uintExpression = DB::get_schema()->dbDataType('unsigned integer');
+ $entries = $entries->where(array(
+ "CAST($yearExpression AS $uintExpression) = ?" => $matches['year']
+ ));
+
+ // Add month filter
+ if(!empty($matches['month'])) {
+ $monthExpression = DB::get_conn()->formattedDatetimeClause('"BlogEntry"."Date"', '%m');
+ $entries = $entries->where(array(
+ "CAST($monthExpression AS $uintExpression) = ?" => $matches['month']
+ ));
}
}
-
- // Build a list of all IDs for BlogHolders that are children of us
- $holderIDs = $this->BlogHolderIDs();
- // If no BlogHolders, no BlogEntries. So return false
- if(empty($holderIDs)) return false;
-
- // Otherwise, do the actual query
- if($filter) $filter .= ' AND ';
- $filter .= '"SiteTree"."ParentID" IN (' . implode(',', $holderIDs) . ") $tagCheck $dateCheck";
+ // Deprecate old $retrieveCallback parameter
+ if($filters && (is_string($filters) || is_callable($filters))) {
+ Deprecation::notice(
+ '0.8',
+ '$retrieveCallback parameter is deprecated. Use updateEntries in an extension instead.'
+ );
+ $callbackWhere = $entries->dataQuery()->query()->getWhere();
+ return call_user_func($filters, 'BlogEntry', $callbackWhere, $limit, $order);
+ }
- $order = '"BlogEntry"."Date" DESC';
+ // Apply filters
+ if($filters) $entries = $entries->filter($filters);
- // By specifying a callback, you can alter the SQL, or sort on something other than date.
- if($retrieveCallback) return call_user_func($retrieveCallback, 'BlogEntry', $filter, $limit, $order);
-
- $entries = BlogEntry::get()->where($filter)->sort($order);
+ // Extension point
+ $this->extend('updateEntries', $entries, $limit, $tag, $date, $filters, $where);
+ // Paginate results
$list = new PaginatedList($entries, Controller::curr()->request);
$list->setPageLength($limit);
return $list;
@@ -228,66 +229,57 @@ class BlogTree extends Page {
}
class BlogTree_Controller extends Page_Controller {
-
+
private static $allowed_actions = array(
'index',
'rss',
'tag',
'date'
);
-
+
private static $casting = array(
'SelectedTag' => 'Text',
'SelectedAuthor' => 'Text'
);
-
- function init() {
+
+ public function init() {
parent::init();
-
+
$this->IncludeBlogRSS();
-
+
Requirements::themedCSS("blog","blog");
}
/**
* Determine selected BlogEntry items to show on this page
- *
+ *
* @param int $limit
* @return PaginatedList
*/
public function BlogEntries($limit = null) {
require_once('Zend/Date.php');
-
- if($limit === null) $limit = BlogTree::$default_entries_limit;
+ $filter = array();
+
+ // Defaults for limit
+ if($limit === null) $limit = BlogTree::config()->default_entries_limit;
// only use freshness if no action is present (might be displaying tags or rss)
- if ($this->LandingPageFreshness && !$this->request->param('Action')) {
- $d = new Zend_Date(SS_Datetime::now()->getValue());
- $d->sub($this->LandingPageFreshness, Zend_Date::MONTH);
- $date = $d->toString('YYYY-MM-dd');
-
- $filter = "\"BlogEntry\".\"Date\" > '$date'";
- } else {
- $filter = '';
+ $landingPageFreshness = $this->getLandingPageFreshnessMonths();
+ if ($landingPageFreshness && !$this->request->param('Action')) {
+ $date = new Zend_Date(SS_Datetime::now()->getValue());
+ $date->sub($landingPageFreshness, Zend_Date::MONTH);
+ $date = $date->toString('YYYY-MM-dd');
+
+ $filter["Date:GreaterThan"] = $date;
}
- // allow filtering by author field and some blogs have an authorID field which
- // may allow filtering by id
- if(isset($_GET['author']) && isset($_GET['authorID'])) {
- $author = Convert::raw2sql($_GET['author']);
- $id = Convert::raw2sql($_GET['authorID']);
-
- $filter .= " \"BlogEntry\".\"Author\" LIKE '". $author . "' OR \"BlogEntry\".\"AuthorID\" = '". $id ."'";
- }
- else if(isset($_GET['author'])) {
- $filter .= " \"BlogEntry\".\"Author\" LIKE '". Convert::raw2sql($_GET['author']) . "'";
- }
- else if(isset($_GET['authorID'])) {
- $filter .= " \"BlogEntry\".\"AuthorID\" = '". Convert::raw2sql($_GET['authorID']). "'";
+
+ // Allow filtering by author field
+ if($author = $this->SelectedAuthor()) {
+ $filter['Author:PartialMatch'] = $author;
}
- $date = $this->SelectedDate();
-
- return $this->Entries($limit, $this->SelectedTag(), ($date) ? $date : '', null, $filter);
+ // Return filtered items
+ return $this->Entries($limit, $this->SelectedTag(), $this->SelectedDate(), $filter);
}
/**
@@ -296,7 +288,7 @@ class BlogTree_Controller extends Page_Controller {
public function IncludeBlogRSS() {
RSSFeed::linkToFeed($this->Link('rss'), _t('BlogHolder.RSSFEED',"RSS feed of these blogs"));
}
-
+
/**
* Get the rss feed for this blog holder's entries
*/
@@ -305,7 +297,7 @@ class BlogTree_Controller extends Page_Controller {
$blogName = $this->Title;
$altBlogName = $project_name . ' blog';
-
+
$entries = $this->Entries(20);
if($entries) {
@@ -313,18 +305,18 @@ class BlogTree_Controller extends Page_Controller {
return $rss->outputToBrowser();
}
}
-
+
/**
* Protection against infinite loops when an RSS widget pointing to this page is added to this page
*/
public function defaultAction($action) {
if(stristr($_SERVER['HTTP_USER_AGENT'], 'SimplePie')) return $this->rss();
-
+
return parent::defaultAction($action);
}
-
+
/**
- * Return the currently viewing tag used in the template as $Tag
+ * Return the currently viewing tag used in the template as $Tag
*
* @return string
*/
@@ -335,68 +327,51 @@ class BlogTree_Controller extends Page_Controller {
}
return '';
}
-
+
/**
* Return the selected date from the blog tree
*
- * @return string
+ * @return string Date in format 'year-month', 'year', or false if not a date
*/
public function SelectedDate() {
- if($this->request->latestParam('Action') == 'date') {
- $year = $this->request->latestParam('ID');
- $month = $this->request->latestParam('OtherID');
-
- if(is_numeric($year) && is_numeric($month) && $month < 13) {
-
- $date = $year .'-'. $month;
- return $date;
-
- } else {
-
- if(is_numeric($year)) return $year;
- }
+ if($this->request->latestParam('Action') !== 'date') return false;
+
+ // Check year
+ $year = $this->request->latestParam('ID');
+ if(!is_numeric($year)) return false;
+
+ // Check month
+ $month = $this->request->latestParam('OtherID');
+ if(is_numeric($month) && $month < 13) {
+ return $year . '-' . $month;
+ } else {
+ return $year;
}
-
- return false;
}
/**
* @return string
*/
public function SelectedAuthor() {
- if($this->request->getVar('author')) {
- $hasAuthor = BlogEntry::get()->filter('Author', $this->request->getVar('author'))->Count();
- return $hasAuthor
- ? $this->request->getVar('author')
- : null;
- } elseif($this->request->getVar('authorID')) {
- $hasAuthor = BlogEntry::get()->filter('AuthorID', $this->request->getVar('authorID'))->Count();
- if($hasAuthor) {
- $member = Member::get()->byId($this->request->getVar('authorID'));
- if($member) {
- if($member->hasMethod('BlogAuthorTitle')) {
- return $member->BlogAuthorTitle;
- } else {
- return $member->Title;
- }
- } else {
- return null;
- }
- }
+ if($author = $this->request->getVar('author')) {
+ $hasAuthor = BlogEntry::get()
+ ->filter('Author:PartialMatch', $author)
+ ->Count();
+ if($hasAuthor) return $author;
}
}
-
+
/**
- *
+ *
* @return string
*/
public function SelectedNiceDate(){
$date = $this->SelectedDate();
-
+
if(strpos($date, '-')) {
$date = explode("-",$date);
return date("F", mktime(0, 0, 0, $date[1], 1, date('Y'))). " " .date("Y", mktime(0, 0, 0, date('m'), 1, $date[0]));
-
+
} else {
return date("Y", mktime(0, 0, 0, date('m'), 1, $date));
}
diff --git a/code/MetaWeblogController.php b/code/MetaWeblogController.php
index f890a75..5be2007 100644
--- a/code/MetaWeblogController.php
+++ b/code/MetaWeblogController.php
@@ -7,8 +7,9 @@ require_once(BASE_PATH . '/blog/thirdparty/xmlrpc/xmlrpc_wrappers.php');
/**
* MetaWeblogController provides the MetaWeblog API for SilverStripe blogs.
*/
-class MetaWeblogController extends Controller {
- function index($request) {
+class MetaWeblogController extends Controller {
+
+ public function index($request) {
// Create an xmlrpc server, and set up the method calls
$service = new xmlrpc_server(array(
@@ -34,16 +35,16 @@ class MetaWeblogController extends Controller {
/**
* Get a list of BlogHolders the user has access to.
*/
- function getUsersBlogs($appkey, $username, $password) {
+ public function getUsersBlogs($appkey, $username, $password) {
$member = MemberAuthenticator::authenticate(array(
- 'Email' => $username,
- 'Password' => $password,
+ 'Email' => $username,
+ 'Password' => $password,
));
// TODO Throw approriate error.
if(!$member) die();
- $blogholders = DataObject::get('BlogHolder');
+ $blogholders = SearchForm::get();
$response = array();
@@ -64,7 +65,7 @@ class MetaWeblogController extends Controller {
/**
* Get the most recent posts on a blog.
*/
- function getRecentPosts($blogid, $username, $password, $numberOfPosts) {
+ public function getRecentPosts($blogid, $username, $password, $numberOfPosts) {
$member = MemberAuthenticator::authenticate(array(
'Email' => $username,
'Password' => $password,
@@ -96,10 +97,8 @@ class MetaWeblogController extends Controller {
return $res;
}
- function getCategories() {
+ public function getCategories() {
//TODO dummy function
return array();
}
}
-
-?>
diff --git a/code/import/TypoImport.php b/code/import/TypoImport.php
deleted file mode 100644
index 2b3b21f..0000000
--- a/code/import/TypoImport.php
+++ /dev/null
@@ -1,152 +0,0 @@
-Title = "imported blog";
-
- // write it!
- $bholder->write();
- $bholder->publish("Stage", "Live");
-
- // get the typo articles
- $result = pg_query($dbconn, "SELECT * FROM contents WHERE type='Article'");
-
- while ($row = pg_fetch_row($result)) {
-
- // title [1]
- // author [2]
- // body [3]
- // body_html [4] (type rendered and cached the html here. This is the preferred blog entry content for migration)
- // keywords (space separated) [7] (tags table is just a list of the unique variants of these keywords)
- // created_at [8]
- // permalink [12] (this is like the url in sitetree, prolly not needed)
- // email [18] (address of the commenter)
- // url [19] (url of the commenter)
-
- $title = $row[1];
- $author = $row[2];
- $blog_entry = $row[4];
- $keywords = $row[7];
- $created_at = $row[8];
-
- // sometimes it's empty. If it is, grab the body
- if ($blog_entry == ""){
- // use "body"
- $blog_entry = $row[3];
- }
- echo "blog_entry: $blog_entry";
- echo " \n";
-
- // put the typo blog entry in the SS database
- $newEntry = new BlogEntry();
- $newEntry->Title = $title;
- $newEntry->Author = $author;
- $newEntry->Content = $blog_entry;
- $newEntry->Tags = $keywords;
- $newEntry->Date = $created_at;
-
- // tie each blog entry back to the blogholder we created initially
- $newEntry->ParentID = $bholder->ID;
-
- // write it!
- $newEntry->write();
- $newEntry->publish("Stage", "Live");
-
- // grab the id so we can get the comments
- $old_article_id = $row[0];
-
- // get the comments
- $result2 = pg_query($dbconn, "SELECT * FROM contents WHERE type = 'Comment' AND article_id = $old_article_id");
-
- while ($row2 = pg_fetch_row($result2)) {
- // grab the body_html
- $comment = $row2[4];
-
- // sometimes it's empty. If it is, grab the body
- if ($comment == ""){
- // use "body"
- $comment = $row2[3];
- }
-
-
-
-
- $Cauthor = $row2[2];
- $Ccreated_at = $row2[8];
-
- // put the typo blog comment in the SS database
- $newCEntry = new PageComment();
- $newCEntry->Name = $Cauthor;
- $newCEntry->Comment = $comment;
- $newCEntry->Created = $created_at;
-
- // need to grab the newly inserted blog entry's id
- $newCEntry->ParentID = $newEntry->ID;
-
- // write it!
- $newCEntry->write();
-
- echo "comment: $comment";
- echo " \n";
- }
-
- $newEntry->flushCache();
-
- // fix up the specialchars
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"×\", \"x\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"’\", \"’\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"‘\", \"‘\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"\", \"—\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"“\", \"“\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"”\", \"”\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"–\", \"–\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"—\", \"—\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"…\", \"…\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"™\", \"™\")");
- pg_query($dbconn, "UPDATE SiteTree SET Content = REPLACE(Content, \"&\", \"&\")");
-
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"×\", \"x\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"’\", \"’\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"‘\", \"‘\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"\", \"—\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"“\", \"“\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"”\", \"”\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"–\", \"–\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"—\", \"—\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"…\", \"…\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"™\", \"™\")");
- pg_query($dbconn, "UPDATE PageComment SET Comment = REPLACE(Comment, \"&\", \"&\")");
-
-
- }
-
- pg_close($dbconn);
-
- } // end function
-
-} // end class
-?>
diff --git a/code/widgets/ArchiveWidget.php b/code/widgets/ArchiveWidget.php
index 21c465d..b8b7624 100644
--- a/code/widgets/ArchiveWidget.php
+++ b/code/widgets/ArchiveWidget.php
@@ -1,117 +1,115 @@
'Varchar'
- );
-
- private static $defaults = array(
- 'DisplayMode' => 'month'
- );
-
- private static $title = 'Browse by Date';
-
- private static $cmsTitle = 'Blog Archive';
-
- private static $description =
- 'Show a list of months or years in which there are blog posts, and provide links to them.';
-
- function getCMSFields() {
- $fields = parent::getCMSFields();
-
- $fields->merge(
+/**
+ * Shows a widget with viewing blog entries
+ * by months or years.
+ *
+ * @package blog
+ */
+class ArchiveWidget extends Widget {
- new FieldList(
- new OptionsetField(
- 'DisplayMode',
- _t('ArchiveWidget.DispBY', 'Display by'),
- array(
- 'month' => _t('ArchiveWidget.MONTH', 'month'),
- 'year' => _t('ArchiveWidget.YEAR', 'year')
- )
+ private static $db = array(
+ 'DisplayMode' => 'Varchar'
+ );
+
+ private static $defaults = array(
+ 'DisplayMode' => 'month'
+ );
+
+ private static $title = 'Browse by Date';
+
+ private static $cmsTitle = 'Blog Archive';
+
+ private static $description =
+ 'Show a list of months or years in which there are blog posts, and provide links to them.';
+
+ public function getCMSFields() {
+ $fields = parent::getCMSFields();
+
+ $fields->merge(
+
+ new FieldList(
+ new OptionsetField(
+ 'DisplayMode',
+ _t('ArchiveWidget.DispBY', 'Display by'),
+ array(
+ 'month' => _t('ArchiveWidget.MONTH', 'month'),
+ 'year' => _t('ArchiveWidget.YEAR', 'year')
)
- )
- );
-
- $this->extend('updateCMSFields', $fields);
-
- return $fields;
- }
-
- function getDates() {
- Requirements::themedCSS('archivewidget');
-
- $results = new ArrayList();
- $container = BlogTree::current();
- $ids = $container->BlogHolderIDs();
-
- $stage = Versioned::current_stage();
- $suffix = (!$stage || $stage == 'Stage') ? "" : "_$stage";
+ )
+ )
+ );
- if(method_exists(DB::getConn(), 'formattedDatetimeClause')) {
- $monthclause = DB::getConn()->formattedDatetimeClause('"Date"', '%m');
- $yearclause = DB::getConn()->formattedDatetimeClause('"Date"', '%Y');
- } else {
- $monthclause = 'MONTH("Date")';
- $yearclause = 'YEAR("Date")';
- }
-
- if($this->DisplayMode == 'month') {
- $sqlResults = DB::query("
- SELECT DISTINCT CAST($monthclause AS " . DB::getConn()->dbDataType('unsigned integer') . ")
- AS \"Month\",
- $yearclause AS \"Year\"
- FROM \"SiteTree$suffix\" INNER JOIN \"BlogEntry$suffix\"
- ON \"SiteTree$suffix\".\"ID\" = \"BlogEntry$suffix\".\"ID\"
- WHERE \"ParentID\" IN (" . implode(', ', $ids) . ")
- ORDER BY \"Year\" DESC, \"Month\" DESC;"
- );
- } else {
- $sqlResults = DB::query("
- SELECT DISTINCT $yearclause AS \"Year\"
- FROM \"SiteTree$suffix\" INNER JOIN \"BlogEntry$suffix\"
- ON \"SiteTree$suffix\".\"ID\" = \"BlogEntry$suffix\".\"ID\"
- WHERE \"ParentID\" IN (" . implode(', ', $ids) . ")
- ORDER BY \"Year\" DESC"
- );
- }
-
- if($sqlResults) foreach($sqlResults as $sqlResult) {
- $isMonthDisplay = $this->DisplayMode == 'month';
-
- $monthVal = (isset($sqlResult['Month'])) ? (int) $sqlResult['Month'] : 1;
- $month = ($isMonthDisplay) ? $monthVal : 1;
- $year = ($sqlResult['Year']) ? (int) $sqlResult['Year'] : date('Y');
-
- $date = DBField::create_field('Date', array(
- 'Day' => 1,
- 'Month' => $month,
- 'Year' => $year
- ));
-
- if($isMonthDisplay) {
- $link = $container->Link('date') . '/' . $sqlResult['Year'] . '/' . sprintf("%'02d", $monthVal);
- } else {
- $link = $container->Link('date') . '/' . $sqlResult['Year'];
- }
-
- $results->push(new ArrayData(array(
- 'Date' => $date,
- 'Link' => $link
- )));
- }
-
- return $results;
- }
+ $this->extend('updateCMSFields', $fields);
+
+ return $fields;
}
+ public function getDates() {
+ Requirements::themedCSS('archivewidget');
+
+ $results = new ArrayList();
+ $container = BlogTree::current();
+ $ids = $container->BlogHolderIDs();
+
+ $stage = Versioned::current_stage();
+ $suffix = (!$stage || $stage == 'Stage') ? "" : "_$stage";
+
+ if(method_exists(DB::getConn(), 'formattedDatetimeClause')) {
+ $monthclause = DB::getConn()->formattedDatetimeClause('"Date"', '%m');
+ $yearclause = DB::getConn()->formattedDatetimeClause('"Date"', '%Y');
+ } else {
+ $monthclause = 'MONTH("Date")';
+ $yearclause = 'YEAR("Date")';
+ }
+
+ if($this->DisplayMode == 'month') {
+ $sqlResults = DB::query("
+ SELECT DISTINCT CAST($monthclause AS " . DB::getConn()->dbDataType('unsigned integer') . ")
+ AS \"Month\",
+ $yearclause AS \"Year\"
+ FROM \"SiteTree$suffix\" INNER JOIN \"BlogEntry$suffix\"
+ ON \"SiteTree$suffix\".\"ID\" = \"BlogEntry$suffix\".\"ID\"
+ WHERE \"ParentID\" IN (" . implode(', ', $ids) . ")
+ ORDER BY \"Year\" DESC, \"Month\" DESC;"
+ );
+ } else {
+ $sqlResults = DB::query("
+ SELECT DISTINCT $yearclause AS \"Year\"
+ FROM \"SiteTree$suffix\" INNER JOIN \"BlogEntry$suffix\"
+ ON \"SiteTree$suffix\".\"ID\" = \"BlogEntry$suffix\".\"ID\"
+ WHERE \"ParentID\" IN (" . implode(', ', $ids) . ")
+ ORDER BY \"Year\" DESC"
+ );
+ }
+
+ if($sqlResults) foreach($sqlResults as $sqlResult) {
+ $isMonthDisplay = $this->DisplayMode == 'month';
+
+ $monthVal = (isset($sqlResult['Month'])) ? (int) $sqlResult['Month'] : 1;
+ $month = ($isMonthDisplay) ? $monthVal : 1;
+ $year = ($sqlResult['Year']) ? (int) $sqlResult['Year'] : date('Y');
+
+ $date = DBField::create_field('Date', array(
+ 'Day' => 1,
+ 'Month' => $month,
+ 'Year' => $year
+ ));
+
+ if($isMonthDisplay) {
+ $link = $container->Link('date') . '/' . $sqlResult['Year'] . '/' . sprintf("%'02d", $monthVal);
+ } else {
+ $link = $container->Link('date') . '/' . $sqlResult['Year'];
+ }
+
+ $results->push(new ArrayData(array(
+ 'Date' => $date,
+ 'Link' => $link
+ )));
+ }
+
+ return $results;
+ }
}
diff --git a/code/widgets/BlogManagementWidget.php b/code/widgets/BlogManagementWidget.php
index 8f3c2fa..a2dc2ef 100644
--- a/code/widgets/BlogManagementWidget.php
+++ b/code/widgets/BlogManagementWidget.php
@@ -1,60 +1,66 @@
value();
- if($unmoderatedcount == 1) {
- return _t("BlogManagementWidget.UNM1", "You have 1 unmoderated comment");
- } else if($unmoderatedcount > 1) {
- return sprintf(_t("BlogManagementWidget.UNMM", "You have %i unmoderated comments"), $unmoderatedcount);
- } else {
- return _t("BlogManagementWidget.COMADM", "Comment administration");
- }
+ public function CommentText() {
+ if(!class_exists('Comment')) return false;
+ $unmoderatedcount = DB::query("SELECT COUNT(*) FROM \"Comment\" WHERE \"Moderated\"=1")->value();
+ if($unmoderatedcount == 1) {
+ return _t("BlogManagementWidget.UNM1", "You have 1 unmoderated comment");
+ } else if($unmoderatedcount > 1) {
+ return sprintf(_t("BlogManagementWidget.UNMM", "You have %i unmoderated comments"), $unmoderatedcount);
+ } else {
+ return _t("BlogManagementWidget.COMADM", "Comment administration");
}
-
- function CommentLink() {
-
- if(!Permission::check('BLOGMANAGEMENT') || !class_exists('Comment')) return false;
- $unmoderatedcount = DB::query("SELECT COUNT(*) FROM \"Comment\" WHERE \"Moderated\"=1")->value();
-
- if($unmoderatedcount > 0) {
- return "admin/comments/unmoderated";
- } else {
- return "admin/comments";
- }
- }
-
}
- class BlogManagementWidget_Controller extends Widget_Controller {
-
- function WidgetHolder() {
- if(Permission::check("BLOGMANAGEMENT")) {
- return $this->renderWith("WidgetHolder");
- }
- }
-
- function PostLink() {
- $container = BlogTree::current();
- return ($container && $container->ClassName != "BlogTree") ? $container->Link('post') : false;
+ /**
+ * Link to edit comment
+ *
+ * @return string
+ */
+ public function CommentLink() {
+ if(!Permission::check('BLOGMANAGEMENT') || !class_exists('Comment')) return false;
+ $unmoderatedcount = DB::query("SELECT COUNT(*) FROM \"Comment\" WHERE \"Moderated\"=1")->value();
+
+ if($unmoderatedcount > 0) {
+ return "admin/comments/unmoderated";
+ } else {
+ return "admin/comments";
}
}
}
+
+class BlogManagementWidget_Controller extends Widget_Controller {
+
+ public function WidgetHolder() {
+ if(Permission::check("BLOGMANAGEMENT")) {
+ return $this->renderWith("WidgetHolder");
+ }
+ }
+
+ public function PostLink() {
+ $container = BlogTree::current();
+ return ($container && $container->ClassName != "BlogTree") ? $container->Link('post') : false;
+ }
+}
diff --git a/code/widgets/RSSWidget.php b/code/widgets/RSSWidget.php
index 5615436..2b9e6d9 100644
--- a/code/widgets/RSSWidget.php
+++ b/code/widgets/RSSWidget.php
@@ -1,109 +1,107 @@
"Text",
+ "RssUrl" => "Text",
+ "NumberToShow" => "Int"
+ );
+
+ private static $defaults = array(
+ "NumberToShow" => 10,
+ "RSSTitle" => 'RSS Feed'
+ );
+
+ private static $cmsTitle = "RSS Feed";
+
+ private static $description = "Downloads another page's RSS feed and displays items in a list.";
+
/**
- * Presents a list of items from an RSS feed url
- *
- * @package blog
+ * If the RssUrl is relative, convert it to absolute with the
+ * current baseURL to avoid confusing simplepie.
+ * Passing relative URLs to simplepie will result
+ * in strange DNS lookups and request timeouts.
+ *
+ * @return string
*/
- class RSSWidget extends Widget {
-
- private static $db = array(
- "RSSTitle" => "Text",
- "RssUrl" => "Text",
- "NumberToShow" => "Int"
- );
-
- private static $defaults = array(
- "NumberToShow" => 10,
- "RSSTitle" => 'RSS Feed'
- );
-
- private static $cmsTitle = "RSS Feed";
-
- private static $description = "Downloads another page's RSS feed and displays items in a list.";
-
- /**
- * If the RssUrl is relative, convert it to absolute with the
- * current baseURL to avoid confusing simplepie.
- * Passing relative URLs to simplepie will result
- * in strange DNS lookups and request timeouts.
- *
- * @return string
- */
- function getAbsoluteRssUrl() {
- $urlParts = parse_url($this->RssUrl);
- if(!isset($urlParts['host']) || !$urlParts['host']) {
- return Director::absoluteBaseURL() . $this->RssUrl;
- } else {
- return $this->RssUrl;
- }
- }
-
- function getCMSFields() {
- $fields = parent::getCMSFields();
-
- $fields->merge(
- new FieldList(
- new TextField("RSSTitle", _t('RSSWidget.CT', "Custom title for the feed")),
- new TextField("RssUrl", _t(
- 'RSSWidget.URL',
- "URL of the other page's RSS feed. Please make sure this URL points to an RSS feed."
- )),
- new NumericField("NumberToShow", _t('RSSWidget.NTS', "Number of Items to show"))
- )
- );
-
- $this->extend('updateCMSFields', $fields);
-
- return $fields;
- }
-
- function Title() {
- return ($this->RSSTitle) ? $this->RSSTitle : _t('RSSWidget.DEFAULTTITLE', 'RSS Feed');
- }
-
- function getFeedItems() {
- $output = new ArrayList();
-
- // Protection against infinite loops when an RSS widget pointing to this page is added to this page
- if(stristr($_SERVER['HTTP_USER_AGENT'], 'SimplePie')) {
- return $output;
- }
-
- if(!class_exists('SimplePie')) {
- throw new LogicException(
- 'Please install the "simplepie/simplepie" library by adding it to the "require" '
- + 'section of your composer.json'
- );
- }
-
- $t1 = microtime(true);
- $feed = new SimplePie();
- $feed->set_feed_url($this->AbsoluteRssUrl);
- $feed->set_cache_location(TEMP_FOLDER);
- $feed->init();
- if($items = $feed->get_items(0, $this->NumberToShow)) {
- foreach($items as $item) {
-
- // Cast the Date
- $date = new Date('Date');
- $date->setValue($item->get_date());
-
- // Cast the Title
- $title = new Text('Title');
- $title->setValue(html_entity_decode($item->get_title()));
-
- $output->push(new ArrayData(array(
- 'Title' => $title,
- 'Date' => $date,
- 'Link' => $item->get_link()
- )));
- }
- return $output;
- }
+ public function getAbsoluteRssUrl() {
+ $urlParts = parse_url($this->RssUrl);
+ if(!isset($urlParts['host']) || !$urlParts['host']) {
+ return Director::absoluteBaseURL() . $this->RssUrl;
+ } else {
+ return $this->RssUrl;
}
}
+ public function getCMSFields() {
+ $fields = parent::getCMSFields();
+
+ $fields->merge(
+ new FieldList(
+ new TextField("RSSTitle", _t('RSSWidget.CT', "Custom title for the feed")),
+ new TextField("RssUrl", _t(
+ 'RSSWidget.URL',
+ "URL of the other page's RSS feed. Please make sure this URL points to an RSS feed."
+ )),
+ new NumericField("NumberToShow", _t('RSSWidget.NTS', "Number of Items to show"))
+ )
+ );
+
+ $this->extend('updateCMSFields', $fields);
+
+ return $fields;
+ }
+
+ public function Title() {
+ return $this->RSSTitle ?: _t('RSSWidget.DEFAULTTITLE', 'RSS Feed');
+ }
+
+ public function getFeedItems() {
+ $output = new ArrayList();
+
+ // Protection against infinite loops when an RSS widget pointing to this page is added to this page
+ if(stristr($_SERVER['HTTP_USER_AGENT'], 'SimplePie')) {
+ return $output;
+ }
+
+ if(!class_exists('SimplePie')) {
+ throw new LogicException(
+ 'Please install the "simplepie/simplepie" library by adding it to the "require" '
+ + 'section of your composer.json'
+ );
+ }
+
+ $t1 = microtime(true);
+ $feed = new SimplePie();
+ $feed->set_feed_url($this->AbsoluteRssUrl);
+ $feed->set_cache_location(TEMP_FOLDER);
+ $feed->init();
+ if($items = $feed->get_items(0, $this->NumberToShow)) {
+ foreach($items as $item) {
+
+ // Cast the Date
+ $date = new Date('Date');
+ $date->setValue($item->get_date());
+
+ // Cast the Title
+ $title = new Text('Title');
+ $title->setValue(html_entity_decode($item->get_title()));
+
+ $output->push(new ArrayData(array(
+ 'Title' => $title,
+ 'Date' => $date,
+ 'Link' => $item->get_link()
+ )));
+ }
+ return $output;
+ }
+ }
}
diff --git a/code/widgets/SubscribeRSSWidget.php b/code/widgets/SubscribeRSSWidget.php
index 8190c47..26f288c 100644
--- a/code/widgets/SubscribeRSSWidget.php
+++ b/code/widgets/SubscribeRSSWidget.php
@@ -1,33 +1,31 @@
Link('rss');
- }
+ public function getRSSLink() {
+ Requirements::themedCSS('subscribersswidget');
+ $container = BlogTree::current();
+ if ($container) return $container->Link('rss');
}
-
}
diff --git a/code/widgets/TagCloudWidget.php b/code/widgets/TagCloudWidget.php
index a07e3d9..6aaf282 100644
--- a/code/widgets/TagCloudWidget.php
+++ b/code/widgets/TagCloudWidget.php
@@ -1,155 +1,154 @@
"Varchar",
+ "Limit" => "Int",
+ "Sortby" => "Varchar"
+ );
+
+ private static $defaults = array(
+ "Title" => "Tag Cloud",
+ "Limit" => "0",
+ "Sortby" => "alphabet"
+ );
+
+ private static $cmsTitle = "Tag Cloud";
+
+ private static $description = "Shows a tag cloud of tags on your blog.";
+
/**
- * A list of tags associated with blog posts
- *
- * @package blog
+ * List of popularity classes in order of least to most popular
+ *
+ * @config
+ * @var array
*/
- class TagCloudWidget extends Widget {
-
- private static $db = array(
- "Title" => "Varchar",
- "Limit" => "Int",
- "Sortby" => "Varchar"
- );
+ private static $popularities = array(
+ 'not-popular',
+ 'not-very-popular',
+ 'somewhat-popular',
+ 'popular',
+ 'very-popular',
+ 'ultra-popular'
+ );
- private static $defaults = array(
- "Title" => "Tag Cloud",
- "Limit" => "0",
- "Sortby" => "alphabet"
- );
+ public function getCMSFields() {
- private static $cmsTitle = "Tag Cloud";
-
- private static $description = "Shows a tag cloud of tags on your blog.";
-
- /**
- * List of popularity classes in order of least to most popular
- *
- * @config
- * @var array
- */
- private static $popularities = array(
- 'not-popular',
- 'not-very-popular',
- 'somewhat-popular',
- 'popular',
- 'very-popular',
- 'ultra-popular'
- );
-
- public function getCMSFields() {
-
- $this->beforeUpdateCMSFields(function($fields) {
- $fields->merge(
- new FieldList(
- new TextField("Title", _t("TagCloudWidget.TILE", "Title")),
- new TextField("Limit", _t("TagCloudWidget.LIMIT", "Limit number of tags")),
- new OptionsetField(
- "Sortby",
- _t("TagCloudWidget.SORTBY", "Sort by"),
- array(
- "alphabet" => _t("TagCloudWidget.SBAL", "alphabet"),
- "frequency" => _t("TagCloudWidget.SBFREQ", "frequency")
- )
+ $this->beforeUpdateCMSFields(function($fields) {
+ $fields->merge(
+ new FieldList(
+ new TextField("Title", _t("TagCloudWidget.TILE", "Title")),
+ new TextField("Limit", _t("TagCloudWidget.LIMIT", "Limit number of tags")),
+ new OptionsetField(
+ "Sortby",
+ _t("TagCloudWidget.SORTBY", "Sort by"),
+ array(
+ "alphabet" => _t("TagCloudWidget.SBAL", "alphabet"),
+ "frequency" => _t("TagCloudWidget.SBFREQ", "frequency")
)
)
- );
+ )
+ );
+ });
+
+ return parent::getCMSFields();
+ }
+
+ public function Title() {
+ return $this->Title ?: _t('TagCloudWidget.DEFAULTTITLE', 'Tag Cloud');
+ }
+
+ /**
+ * Current BlogTree used as the container for this tagcloud.
+ * Used by {@link TagCloudWidgetTest} for testing
+ *
+ * @var BlogTree
+ */
+ public static $container = null;
+
+ /**
+ * Return all sorted tags in the system
+ *
+ * @return ArrayList
+ */
+ public function getTagsCollection() {
+ Requirements::themedCSS("tagcloud");
+
+ // Ensure there is a valid BlogTree with entries
+ $container = BlogTree::current(self::$container);
+ if( !$container
+ || !($entries = $container->Entries())
+ || $entries->count() == 0
+ ) return null;
+
+ // Extract all tags from each entry
+ $tagCounts = array(); // Mapping of tag => frequency
+ $tagLabels = array(); // Mapping of tag => label
+ foreach($entries as $entry) {
+ $theseTags = $entry->TagNames();
+ foreach($theseTags as $tag => $tagLabel) {
+ $tagLabels[$tag] = $tagLabel;
+ //getting the count into key => value map
+ $tagCounts[$tag] = isset($tagCounts[$tag]) ? $tagCounts[$tag] + 1 : 1;
+ }
+ }
+ if(empty($tagCounts)) return null;
+ $minCount = min($tagCounts);
+ $maxCount = max($tagCounts);
+
+ // Apply sorting mechanism
+ if($this->Sortby == "alphabet") {
+ // Sort by name
+ ksort($tagCounts);
+ } else {
+ // Sort by frequency
+ uasort($tagCounts, function($a, $b) {
+ return $b - $a;
});
-
- return parent::getCMSFields();
}
- function Title() {
- return $this->Title ? $this->Title : _t('TagCloudWidget.DEFAULTTITLE', 'Tag Cloud');
- }
-
- /**
- * Current BlogTree used as the container for this tagcloud.
- * Used by {@link TagCloudWidgetTest} for testing
- *
- * @var BlogTree
- */
- public static $container = null;
+ // Apply limiting
+ if($this->Limit > 0) $tagCounts = array_slice($tagCounts, 0, $this->Limit, true);
- /**
- * Return all sorted tags in the system
- *
- * @return ArrayList
- */
- function getTagsCollection() {
- Requirements::themedCSS("tagcloud");
+ // Calculate buckets of popularities
+ $numsizes = count(array_unique($tagCounts)); //Work out the number of different sizes
+ $popularities = self::config()->popularities;
+ $buckets = count($popularities);
- // Ensure there is a valid BlogTree with entries
- $container = BlogTree::current(self::$container);
- if( !$container
- || !($entries = $container->Entries())
- || $entries->count() == 0
- ) return null;
+ // If there are more frequencies than buckets, divide frequencies into buckets
+ if ($numsizes > $buckets) $numsizes = $buckets;
- // Extract all tags from each entry
- $tagCounts = array(); // Mapping of tag => frequency
- $tagLabels = array(); // Mapping of tag => label
- foreach($entries as $entry) {
- $theseTags = $entry->TagNames();
- foreach($theseTags as $tag => $tagLabel) {
- $tagLabels[$tag] = $tagLabel;
- //getting the count into key => value map
- $tagCounts[$tag] = isset($tagCounts[$tag]) ? $tagCounts[$tag] + 1 : 1;
- }
- }
- if(empty($tagCounts)) return null;
- $minCount = min($tagCounts);
- $maxCount = max($tagCounts);
+ // Adjust offset to use central buckets (if using a subset of available buckets)
+ $offset = round(($buckets - $numsizes)/2);
- // Apply sorting mechanism
- if($this->Sortby == "alphabet") {
- // Sort by name
- ksort($tagCounts);
+ $output = new ArrayList();
+ foreach($tagCounts as $tag => $count) {
+
+ // Find position of $count in the selected range, adjusted for bucket range used
+ if($maxCount == $minCount) {
+ $popularity = $offset;
} else {
- // Sort by frequency
- uasort($tagCounts, function($a, $b) {
- return $b - $a;
- });
+ $popularity = round(
+ ($count-$minCount) / ($maxCount-$minCount) * ($numsizes-1)
+ ) + $offset;
}
-
- // Apply limiting
- if($this->Limit > 0) $tagCounts = array_slice($tagCounts, 0, $this->Limit, true);
+ $class = $popularities[$popularity];
- // Calculate buckets of popularities
- $numsizes = count(array_unique($tagCounts)); //Work out the number of different sizes
- $popularities = self::config()->popularities;
- $buckets = count($popularities);
-
- // If there are more frequencies than buckets, divide frequencies into buckets
- if ($numsizes > $buckets) $numsizes = $buckets;
-
- // Adjust offset to use central buckets (if using a subset of available buckets)
- $offset = round(($buckets - $numsizes)/2);
-
- $output = new ArrayList();
- foreach($tagCounts as $tag => $count) {
-
- // Find position of $count in the selected range, adjusted for bucket range used
- if($maxCount == $minCount) {
- $popularity = $offset;
- } else {
- $popularity = round(
- ($count-$minCount) / ($maxCount-$minCount) * ($numsizes-1)
- ) + $offset;
- }
- $class = $popularities[$popularity];
-
- $output->push(new ArrayData(array(
- "Tag" => $tagLabels[$tag],
- "Count" => $count,
- "Class" => $class,
- "Link" => Controller::join_links($container->Link('tag'), urlencode($tag))
- )));
- }
- return $output;
+ $output->push(new ArrayData(array(
+ "Tag" => $tagLabels[$tag],
+ "Count" => $count,
+ "Class" => $class,
+ "Link" => Controller::join_links($container->Link('tag'), urlencode($tag))
+ )));
}
+ return $output;
}
}
diff --git a/composer.json b/composer.json
index 7afc4a1..f3abe6a 100644
--- a/composer.json
+++ b/composer.json
@@ -4,22 +4,22 @@
"type": "silverstripe-module",
"keywords": ["silverstripe", "blog"],
"authors": [
- {
- "name": "Saophalkun Ponlu",
- "email": "phalkunz@silverstripe.com"
- },
- {
- "name": "Carlos Barberis",
- "email": "carlos@silverstripe.com"
- }
+ {
+ "name": "Saophalkun Ponlu",
+ "email": "phalkunz@silverstripe.com"
+ },
+ {
+ "name": "Carlos Barberis",
+ "email": "carlos@silverstripe.com"
+ }
],
-
- "require":
- {
- "silverstripe/cms": "~3.1"
+ "require": {
+ "silverstripe/cms": "~3.2"
},
- "suggest":
- {
+ "require-dev": {
+ "phpunit/PHPUnit": "~3.7@stable"
+ },
+ "suggest": {
"silverstripe/widgets": "Additional 'sidebar features', e.g. a list of recent posts and a tagcloud",
"silverstripe/comments": "Enable user comments on any page type, including blog posts",
"simplepie/simplepie": "Parse RSS feeds, required for the RSS widget"
diff --git a/tests/BlogTreeTest.php b/tests/BlogTreeTest.php
index 6c14845..86be699 100644
--- a/tests/BlogTreeTest.php
+++ b/tests/BlogTreeTest.php
@@ -72,11 +72,12 @@ class BlogTreeTest extends SapphireTest {
function testLandingPageFreshness() {
$node = $this->objFromFixture('BlogTree', 'root');
- $this->assertEquals($node->LandingPageFreshness, '7 DAYS');
+ $this->assertEquals('7', $node->LandingPageFreshness);
$node = $this->objFromFixture('BlogTree', 'levela');
- $this->assertEquals($node->LandingPageFreshness, '2 DAYS');
+ $this->assertEquals('2', $node->LandingPageFreshness);
$node = $this->objFromFixture('BlogTree', 'levelb');
- $this->assertEquals($node->LandingPageFreshness, '7 DAYS');
+ $this->assertEquals('INHERIT', $node->LandingPageFreshness);
+ $this->assertEquals('7', $node->getLandingPageFreshnessMonths());
}
function testGettingAssociatedBlogTree() {
diff --git a/tests/BlogTreeTest.yml b/tests/BlogTreeTest.yml
index b66730d..2d354e8 100644
--- a/tests/BlogTreeTest.yml
+++ b/tests/BlogTreeTest.yml
@@ -1,13 +1,13 @@
BlogTree:
root:
Title: Root BlogTree
- LandingPageFreshness: 7 DAYS
+ LandingPageFreshness: 7
otherroot:
Title: Other root BlogTree
levela:
Title: Level A
Parent: =>BlogTree.root
- LandingPageFreshness: 2 DAYS
+ LandingPageFreshness: 2
levelb:
Title: Level B
Parent: =>BlogTree.root
@@ -27,7 +27,7 @@ BlogHolder:
levelaa_blog1:
Title: Level AA Blog 1
Parent: =>BlogTree.levelaa
- LandingPageFreshness: 1 DAY
+ LandingPageFreshness: 1
levelaa_blog2:
Title: Level AA Blog 2
Parent: =>BlogTree.levelaa