silverstripe-blog/code/BlogTree.php

380 lines
10 KiB
PHP
Raw Normal View History

<?php
2012-05-21 14:58:26 +12:00
/**
* @package blog
*/
/**
* Blog tree is a way to group Blogs. It allows a tree of "Blog Holders".
* Viewing branch nodes shows all blog entries from all blog holder children
2012-05-21 14:58:26 +12:00
*/
class BlogTree extends Page {
private static $icon = "blog/images/blogtree-file.png";
private static $description = "A grouping of blogs";
private static $singular_name = 'Blog Tree Page';
private static $plural_name = 'Blog Tree Pages';
/**
* Default number of blog entries to show
*
* @var int
* @config
*/
private static $default_entries_limit = 10;
private static $db = array(
'Name' => 'Varchar(255)',
2012-05-21 14:58:26 +12:00
'LandingPageFreshness' => 'Varchar',
);
private static $allowed_children = array(
'BlogTree',
'BlogHolder'
2012-05-21 14:58:26 +12:00
);
/*
* Finds the BlogTree object most related to the current page.
* - If this page is a BlogTree, use that
* - If this page is a BlogEntry, use the parent Holder
* - Otherwise, try and find a 'top-level' BlogTree
*
* @param $page allows you to force a specific page, otherwise,
* uses current
* @return BlogTree
2012-05-21 14:58:26 +12:00
*/
public static function current($page = null) {
// extract page from current request if not specified
if (!$page && Controller::has_curr()) {
2012-05-21 14:58:26 +12:00
$controller = Controller::curr();
if ($controller->hasMethod('data')) {
$page = $controller->data();
}
2012-05-21 14:58:26 +12:00
}
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;
}
// Or, if we a a BlogEntry underneath a BlogTree, use our parent
if($page instanceof BlogEntry && $page->getParent() instanceof BlogTree) {
return $page->getParent();
}
2012-05-21 14:58:26 +12:00
}
2012-05-21 14:58:26 +12:00
// Try to find a top-level BlogTree
$top = BlogTree::get()->filter("ParentID", 0)->first();
2012-05-21 14:58:26 +12:00
if($top) return $top;
2012-05-21 14:58:26 +12:00
// Try to find any BlogTree that is not inside another BlogTree
$blogTrees = BlogTree::get();
foreach($blogTrees as $tree) {
2012-05-21 14:58:26 +12:00
if(!($tree->getParent() instanceof BlogTree)) return $tree;
}
2012-05-21 14:58:26 +12:00
// This shouldn't be possible, but assuming the above fails, just return anything you can get
return $blogTrees->first();
2012-05-21 14:58:26 +12:00
}
/**
* 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;
}
2012-05-21 14:58:26 +12:00
return $freshness;
}
2012-05-21 14:58:26 +12:00
/* ----------- CMS CONTROL -------------- */
public function getSettingsFields() {
$fields = parent::getSettingsFields();
$fields->addFieldToTab(
'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",
"INHERIT" => "Take value from parent Blog Tree"
)
)
);
2012-05-21 15:58:40 +12:00
2012-05-21 14:58:26 +12:00
return $fields;
}
2012-05-21 14:58:26 +12:00
/* ----------- New accessors -------------- */
2012-05-21 14:58:26 +12:00
public function loadDescendantBlogHolderIDListInto(&$idList) {
if ($children = $this->AllChildren()) {
foreach($children as $child) {
if(in_array($child->ID, $idList)) continue;
2012-05-21 14:58:26 +12:00
if($child instanceof BlogHolder) {
$idList[] = $child->ID;
2012-05-21 14:58:26 +12:00
} elseif($child instanceof BlogTree) {
$child->loadDescendantBlogHolderIDListInto($idList);
}
2012-05-21 14:58:26 +12:00
}
}
}
/**
* Build a list of all IDs for BlogHolders that are children of us
*
* @return array
*/
2012-05-21 14:58:26 +12:00
public function BlogHolderIDs() {
$holderIDs = array();
$this->loadDescendantBlogHolderIDListInto($holderIDs);
return $holderIDs;
}
2012-05-21 14:58:26 +12:00
/**
* Get entries in this blog.
*
* @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 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
2012-05-21 14:58:26 +12:00
*/
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;
2012-05-21 14:58:26 +12:00
// Build filtered list
$entries = BlogEntry::get()
->filter('ParentID', $holderIDs)
->sort($order = '"BlogEntry"."Date" DESC');
// 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('/^(?<year>\d+)([-\\/](?<month>\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']
));
2012-05-21 14:58:26 +12:00
}
}
// 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);
}
2012-05-21 14:58:26 +12:00
// Apply filters
if($filters) $entries = $entries->filter($filters);
2012-07-03 13:16:18 +12:00
// Extension point
$this->extend('updateEntries', $entries, $limit, $tag, $date, $filters, $where);
2012-07-03 13:16:18 +12:00
// Paginate results
2012-07-08 11:25:53 +12:00
$list = new PaginatedList($entries, Controller::curr()->request);
$list->setPageLength($limit);
return $list;
2012-05-21 14:58:26 +12:00
}
}
class BlogTree_Controller extends Page_Controller {
private static $allowed_actions = array(
2012-05-21 14:58:26 +12:00
'index',
'rss',
'tag',
'date'
);
private static $casting = array(
'SelectedTag' => 'Text',
'SelectedAuthor' => 'Text'
);
public function init() {
2012-05-21 14:58:26 +12:00
parent::init();
2012-05-21 14:58:26 +12:00
$this->IncludeBlogRSS();
Requirements::themedCSS("blog","blog");
2012-05-21 14:58:26 +12:00
}
/**
* Determine selected BlogEntry items to show on this page
*
* @param int $limit
* @return PaginatedList
*/
public function BlogEntries($limit = null) {
2012-05-21 14:58:26 +12:00
require_once('Zend/Date.php');
$filter = array();
// Defaults for limit
if($limit === null) $limit = BlogTree::config()->default_entries_limit;
2012-05-21 14:58:26 +12:00
// only use freshness if no action is present (might be displaying tags or rss)
$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;
2012-05-21 14:58:26 +12:00
}
// Allow filtering by author field
if($author = $this->SelectedAuthor()) {
$filter['Author:PartialMatch'] = $author;
2012-05-21 14:58:26 +12:00
}
// Return filtered items
return $this->Entries($limit, $this->SelectedTag(), $this->SelectedDate(), $filter);
2012-05-21 14:58:26 +12:00
}
/**
* This will create a <link> tag point to the RSS feed
*/
public function IncludeBlogRSS() {
2012-05-21 14:58:26 +12:00
RSSFeed::linkToFeed($this->Link('rss'), _t('BlogHolder.RSSFEED',"RSS feed of these blogs"));
}
2012-05-21 14:58:26 +12:00
/**
* Get the rss feed for this blog holder's entries
*/
public function rss() {
2012-05-21 14:58:26 +12:00
global $project_name;
$blogName = $this->Title;
2012-05-21 14:58:26 +12:00
$altBlogName = $project_name . ' blog';
2012-05-21 14:58:26 +12:00
$entries = $this->Entries(20);
if($entries) {
$rss = new RSSFeed($entries, $this->Link('rss'), ($blogName ? $blogName : $altBlogName), "", "Title", "RSSContent");
return $rss->outputToBrowser();
2012-05-21 14:58:26 +12:00
}
}
2012-05-21 14:58:26 +12:00
/**
* Protection against infinite loops when an RSS widget pointing to this page is added to this page
*/
public function defaultAction($action) {
2012-05-21 14:58:26 +12:00
if(stristr($_SERVER['HTTP_USER_AGENT'], 'SimplePie')) return $this->rss();
2012-05-21 14:58:26 +12:00
return parent::defaultAction($action);
}
2012-05-21 14:58:26 +12:00
/**
* Return the currently viewing tag used in the template as $Tag
2012-05-21 14:58:26 +12:00
*
* @return string
2012-05-21 14:58:26 +12:00
*/
public function SelectedTag() {
if ($this->request->latestParam('Action') == 'tag') {
$tag = $this->request->latestParam('ID');
return urldecode($tag);
}
return '';
2012-05-21 14:58:26 +12:00
}
2012-05-21 14:58:26 +12:00
/**
* Return the selected date from the blog tree
*
* @return string Date in format 'year-month', 'year', or false if not a date
2012-05-21 14:58:26 +12:00
*/
public function SelectedDate() {
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;
2012-05-21 14:58:26 +12:00
}
}
/**
* @return string
*/
public function SelectedAuthor() {
if($author = $this->request->getVar('author')) {
$hasAuthor = BlogEntry::get()
->filter('Author:PartialMatch', $author)
->Count();
if($hasAuthor) return $author;
}
}
/**
*
* @return string
*/
public function SelectedNiceDate(){
2012-05-21 14:58:26 +12:00
$date = $this->SelectedDate();
2012-05-21 14:58:26 +12:00
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]));
2012-05-21 14:58:26 +12:00
} else {
return date("Y", mktime(0, 0, 0, date('m'), 1, $date));
}
}
}