Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Blog Module /

Discuss the Blog Module.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

[SOLVED] Hiding Future Blog Posts (i.e. Scheduling Entries)


Go to End


7 Posts   3657 Views

Avatar
Bstarr

Community Member, 25 Posts

5 July 2011 at 5:45am

Thanks to everyone who has been helping me through my issues. I have one last problem with my blog. I want to hide posts with publish dates greater than the current date/time. I have looked through tutorials and previous posts and believe somewhere in the BlogTree.php I need to have the $Now listed. Can anyone tell me what I am doing wrong?

I created a Blogtree.php in the mysite/code folder and used the code I found in a previous thread...

// 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);
			$date = $d->toString('YYYY-MM-dd');
			 if(defined('DB::USE_ANSI_SQL')) { 
			$filter = "\"BlogEntry\".\"Date\" < NOW()";
         } else {
            $filter = "`BlogEntry`.Date < NOW()";
         } 

However, it is still not working I have future posts showing up. Below is the whole page code.

<?php 

/**
 * @package blog
 */

/**
 * Blog tree allows a tree of Blog Holders. Viewing branch nodes shows all blog entries from all blog holder children
 */

class BlogTree extends Page {
	
	// Default number of blog entries to show
	static $default_entries_limit = 10;
	
	static $db = array(
		'Name' => 'Varchar',
		'InheritSideBar' => 'Boolean',
		'LandingPageFreshness' => 'Varchar',
	);
	
	static $defaults = array(
		'InheritSideBar' => True
	);
	
	static $has_one = array(
		"SideBar" => "WidgetArea",
	);
	
	static $allowed_children = array(
		'BlogTree', 'BlogHolder'
	);

	/*
	 * 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
	 */
	static function current($page = null) {
		
		if (!$page) {
			$controller = Controller::curr();
			if($controller) $page = $controller->data();
		}
		
		// If we _are_ a BlogTree, use us
		if ($page 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;
		}
		
		// Try to find a top-level BlogTree
		$top = DataObject::get_one('BlogTree', "\"ParentID\" = '0'");
		if($top) return $top;
		
		// Try to find any BlogTree that is not inside another BlogTree
		foreach(DataObject::get('BlogTree') 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 DataObject::get_one('BlogTree');
	}

	/* ----------- 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 = '';
		return $freshness;
	}
	
	function SideBar() {
		if($this->InheritSideBar && $this->getParent()) {
			if (method_exists($this->getParent(), 'SideBar')) return $this->getParent()->SideBar();
		}
		
		if($this->SideBarID){
			return DataObject::get_by_id('WidgetArea', $this->SideBarID);
			// @todo: This segfaults - investigate why then fix: return $this->getComponent('SideBar');
		}
	}
	
	/* ----------- CMS CONTROL -------------- */
	
	function getCMSFields() {
		$fields = parent::getCMSFields();
		$fields->addFieldToTab("Root.Content.Main", new TextField("Name", "Name of blog"));
		$fields->addFieldToTab('Root.Content.Main', new DropdownField('LandingPageFreshness', 'When you first open the blog, how many entries should I show', array( 
 			"" => "All entries", 
			"1 MONTH" => "Last month's entries", 
			"2 MONTH" => "Last 2 months' entries", 
			"3 MONTH" => "Last 3 months' entries", 
			"4 MONTH" => "Last 4 months' entries", 
			"5 MONTH" => "Last 5 months' entries", 
			"6 MONTH" => "Last 6 months' entries", 
			"7 MONTH" => "Last 7 months' entries", 
			"8 MONTH" => "Last 8 months' entries", 
			"9 MONTH" => "Last 9 months' entries", 
			"10 MONTH" => "Last 10 months' entries", 
			"11 MONTH" => "Last 11 months' entries", 
			"12 MONTH" => "Last year's entries", 
			"INHERIT" => "Take value from parent Blog Tree"
		))); 
 	
		$fields->addFieldToTab("Root.Content.Widgets", new CheckboxField("InheritSideBar", 'Inherit Sidebar From Parent'));
		$fields->addFieldToTab("Root.Content.Widgets", new WidgetAreaEditor("SideBar"));
		
		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; 
				} elseif($child instanceof BlogTree) {
					$child->loadDescendantBlogHolderIDListInto($idList);
				}                             
			}
		}
	}
	
	// Build a list of all IDs for BlogHolders that are children of us
	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 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 callback retrieveCallback A function to call with pagetype, filter and limit for custom blog sorting or filtering
	 * @param string $where
	 * @return DataObjectSet
	 */
	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%'";
		}

		if($date) {
			if(strpos($date, '-')) {
				$year = (int) substr($date, 0, strpos($date, '-'));
				$month = (int) substr($date, strpos($date, '-') + 1);

				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'";
					}
				}
			}
		}

		// 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 .= '"ParentID" IN (' . implode(',', $holderIDs) . ") $tagCheck $dateCheck";

		$order = '"BlogEntry"."Date" DESC';

		// 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);
		
		return DataObject::get('BlogEntry', $filter, $order, '', $limit);
	}
}

class BlogTree_Controller extends Page_Controller {
	
	static $allowed_actions = array(
		'index',
		'rss',
		'tag'
	);
	
	function init() {
		parent::init();
		
		$this->IncludeBlogRSS();
		
		Requirements::themedCSS("blog");
	}

	function BlogEntries($limit = null) {
		require_once('Zend/Date.php');
		
		if($limit === null) $limit = BlogTree::$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);
			$date = $d->toString('YYYY-MM-dd');
			 if(defined('DB::USE_ANSI_SQL')) { 
			$filter = "\"BlogEntry\".\"Date\" < NOW()";
         } else {
            $filter = "`BlogEntry`.Date < NOW()";
         } 
		 
		// 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']). "'";
		}
		
		$start = isset($_GET['start']) ? (int) $_GET['start'] : 0;
		
		$date = $this->SelectedDate();
		
		return $this->Entries("$start,$limit", $this->SelectedTag(), ($date) ? $date->Format('Y-m') : '', null, $filter);
	}

	/**
	 * This will create a <link> tag point to the RSS feed
	 */
	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
	 */
	function rss() {
		global $project_name;

		$blogName = $this->Name;
		$altBlogName = $project_name . ' blog';
		
		$entries = $this->Entries(20);

		if($entries) {
			$rss = new RSSFeed($entries, $this->Link(), ($blogName ? $blogName : $altBlogName), "", "Title", "ParsedContent");
			$rss->outputToBrowser();
		}
	}
	
	/**
	 * Protection against infinite loops when an RSS widget pointing to this page is added to this page
	 */
	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 String
	 */
	function SelectedTag() {
		return ($this->request->latestParam('Action') == 'tag') ? Convert::raw2xml($this->request->latestParam('ID')) : ''; 
	}
	
	/**
	 * Return the selected date from the blog tree
	 *
	 * @return Date
	 */
	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 = new Date();
				$date->setValue($year .'-'. $month);
				
				return $date;
			}
		}
			
		return false;
	}
}

Avatar
Invader_Zim

Community Member, 141 Posts

5 July 2011 at 6:08am

Hi Bstarr.

I am quite sure i totally miss what you are trying to do...
but if I hit only "Save" and not "Save and Publish" in my Blog, these entries are hidden from the website visitors
(even if i set the date to the future)...

Avatar
Bstarr

Community Member, 25 Posts

5 July 2011 at 6:21am

I essentially want to be able to publish blog entries for future dates and have them show up at the published date/time. The equivalent to scheduling posts in Wordpress or Blogger. When I write posts I usually write 5 or 6 at a time which get published over a few weeks. I also schedule Tweets & facebook posts at specific times to promote my blog entries. Currently I'd have to log into my site and publish each entry and post to social media manually. If published entries don't show up until their published date it is automated as it was when I had a WordPress blog. Sorry I wasn't as clear before.

Avatar
Bstarr

Community Member, 25 Posts

5 July 2011 at 6:22am

Also, this is the post I originally found. But the code he used isn't working for me.
http://silverstripe.org/blog-module-forum/show/12304#post304970#post304970

Avatar
Invader_Zim

Community Member, 141 Posts

5 July 2011 at 6:36am

Ahh, ok I see. Sorry for confusing you :-)

Sad thing is, I think I can't help you on this then.

But have you seen this module: CMS-Workflow?
It has this in it's description: "Set embargo and expiry dates for content"... maybe it helps,
but I have to step back for someone with deeper knowledge.

Cheers

Avatar
Bstarr

Community Member, 25 Posts

6 July 2011 at 4:18am

Thanks Invader_Zim, I was not familiar with the CMS Workflow Module, I just installed it and although it adds an extra step in the process it achieves the desired result of being able to schedule my posts. Thanks!

Avatar
mawk

Community Member, 4 Posts

4 January 2012 at 4:03pm

I had a similar issue and found that the problem was with the SS_DateTime::Now() method being used to create the new Zend_Date object in the BlogEntries method.

Instead of this:

$d = new Zend_Date(SS_Datetime::now()->getValue());

I used this:

$d = Zend_Date::now();

on a side note I also found that there was an issue with the limit filtering using the LandingPageFreshness value. This value is a drop field on the blog page but it's storing the values incorrectly and they're not being called correctly. First I changed the field values to two digit values. For example "2 MONTH" became "02". Then you'll want to dev/build. Then change the $this->LandingPageFreshness property references to $this->getLandingPageFreshness() method references. The method, as opposed to the property, deals with the INHERIT values by retrieving from the parent class or setting to empty.

Also in the BlogEntries method you'll want to change:

$d->sub($this->LandingPageFreshness);

to:

$d->sub($this->getLandingPageFreshness(), Zend_Date::MONTH);