[SOLVED] News Archives by Year/Month

Talk about writing modules and plugins for CMS Made Simple, or about specific core functionality. This board is for PHP programmers that are contributing to CMSMS not for site developers
sam_butler
Forum Members
Forum Members
Posts: 24
Joined: Sun Jul 20, 2008 3:36 pm
Location: Manchester, UK

[SOLVED] News Archives by Year/Month

Post by sam_butler »

This is a question/cry for help regarding the bundled News module.

My client wants to provide users with a list of links to news items by year; like a blog archive. So let's say there were 15 articles posted in 2004, 17 in 2005, etc. In 2008, I want to show the full (paginated) list, plus a simple list under my navigation menu which has something like "News Archives: 2008, 2007, 2006, 2005, 2004," and so on.

I'm sure I could delve into the News module, find all the variables, create a custom script or UDT, etc., but I'd rather not reinvent the wheel or spend extra time if someone has already done it or knows a quick way of doing it. What I thought is perhaps it could be done with a custom summary template.

So here's what I reckon I'll need:
1) Output an array of years (or months & years if possible) during which articles are in the db, with URLs for...
2) ...a page for each year that displays *only* the articles posted during that year (I would then style the summaries and they would link to each article).

I'm going to keep on trucking with everything else, but this is my first CMSMS project and I'm liking it. Hope someone can point me in the right direction! Cheers.
Last edited by sam_butler on Wed Jul 30, 2008 2:09 pm, edited 1 time in total.
stopsatgreen
Power Poster
Power Poster
Posts: 322
Joined: Sat Feb 04, 2006 1:24 am
Location: London, England

Re: News Archives by Year/Month

Post by stopsatgreen »

Here's how I did it recently; I set it to capture by month, but you could easily set it up by year instead:

1. Add a new line to your template to capture a date value you're going to supply:

Code: Select all

{content block='Date' oneline='true' assign='item_date'}
2. Create a new page for each year of the archive, and fill in the 'Date' block with the year you want it to cover.

3. Create a UDT called 'newsletter_date' to get the value of that field and pass it to the News summary template:

Code: Select all

global $gCms;
$myVar = $smarty->get_template_vars('item_date');
echo date('d F Y',strtotime($myVar));
4. Capture that value in the News summary template and filter the results based on that:

Code: Select all

{capture assign='thedate'}{newsletter_date}{/capture}
<ul>
{foreach from=$items item=entry}
{if $entry->postdate|date_format:'%m' == $thedate|date_format:'%m'}
<li>{$entry->titlelink}</li>
{/if}
{/foreach}
</ul>
This is probably a convoluted way of getting it working, so I'd love it if someone else could show a better way.
NaN

Re: News Archives by Year/Month

Post by NaN »

I've created a module called NewsMenu. (see attachement)
It is not documented and therefore it is not in the forge yet.
Additionally i did some modifications to the News module so i don't know if it will work as a general tool.

It just prints out a kind of menu wich filters news articles by years/months.

If you want to test it just download, install it and insert {cms_modue module="NewsMenu"} where you want a menu with years and months for the news.
Maybe that is what you're looking for.

Please report if there are errors or someone has some suggestions.

(rename .txt in .zip first)
Last edited by NaN on Wed Jul 23, 2008 2:54 am, edited 1 time in total.
NaN

Re: News Archives by Year/Month

Post by NaN »

I tried it myself and also get an error : unexpected end of archive.
I guess something went wrong when uploading it.
Just try again.
Attachments
NewsMenu.zip.jpg
NewsMenu.zip.jpg (20.53 KiB) Viewed 12022 times
Last edited by NaN on Wed Jul 23, 2008 7:28 pm, edited 1 time in total.
NaN

Re: News Archives by Year/Month

Post by NaN »

I tryed it several times but always the same. Before uploading it it works fine. after upload and download it file is broken ???
sam_butler
Forum Members
Forum Members
Posts: 24
Joined: Sun Jul 20, 2008 3:36 pm
Location: Manchester, UK

Re: News Archives by Year/Month

Post by sam_butler »

Hm, interesting stopsatgreen, I will try it out and get back to you. NaN I'll send you a private message so you can email me your mod, and I'll give it a try.

Thanks a lot for your help, I didn't notice you'd posted because email notifications didn't come through for some reason ???

The site is looking nice but I can't show you yet  ;) - I'll let you know when it's done.
NaN

Re: News Archives by Year/Month

Post by NaN »

This time it might work... (see post above for download)
sam_butler
Forum Members
Forum Members
Posts: 24
Joined: Sun Jul 20, 2008 3:36 pm
Location: Manchester, UK

Re: News Archives by Year/Month

Post by sam_butler »

Ok NaN, tried your mod. What changes did you make to the News mod? Because for me, while it outputs the list, it's not giving me any news items in the content block. Perhaps your News mod changes facilitated this?

Also, amusingly, in the module info you made a typo: {cms_modue...} instead of module. Lazy me copied and pasted and met a Smarty error!

Stopsatgreen, I tried your method and of course it works, but I will need to create archive pages for each year. Not impossible, but I'd need to include in the documentation for my client how to do it each year, assuming the site will continue to exist in a year! Good thing about CMSMS of course, is that the site can be changed while the content remains intact. So I want to plan for this.

Also with that method, I need to manually create the list that NaN's mod outputs, and have my client add to it when adding a news archive page. It increases their maintenance overhead but it does work, so thank you.

Keep those cogs whirring and let me know if you have any other bright ideas! I'll keep going with the rest of the project...
NaN

Re: News Archives by Year/Month

Post by NaN »

I'll have to take a look into my modified News Module. Maybe there is just a kind of params of the NewsMenu that the NewModule natively does not know.
These modifications were quite easy, I remember.
I'll post it here.
sam_butler
Forum Members
Forum Members
Posts: 24
Joined: Sun Jul 20, 2008 3:36 pm
Location: Manchester, UK

Re: News Archives by Year/Month

Post by sam_butler »

Cheers. Don't know where you are in the world but it's late here, so if I don't get a chance to try it tonight, I'll be on it first thing tomorrow.
NaN

Re: News Archives by Year/Month

Post by NaN »

It's late here, too, but i'm a fulltime workaholic...  8)

So here we go:

Line numbers in files depends on the modules version. So you will sometimes get better results when searching for the sample code.
The following modifications has been tested with NewsModule 2.6.1 and 2.8. Line numbers refers to the 2.8 version.

1st of all we need to add some params to the Newsmodule.
This is done in a kind of initial module file. In CMSms it is usually the [Name_of_the_module].module.php.
So open the file modules/News/News.module.php.
Look for a function called SetParameters() (near line 54).
Within that function there is an if-loop:

Sample:

Code: Select all


...

global $CMS_VERSION;
$res = version_compare( $CMS_VERSION, '1.1' );
if( $res >= 0 )
{
	#
	# For 1.1's enhanced security checking, each
	# parameter that is passed in a frontend url or
	# frontend form needs to be typed here.
	#

	...

Within that if-loop you just need to insert the following lines to set some additional params to the Newsmodule for the frontend:

Code: Select all


### Added by NaN for NewsMenu: ###
    $this->SetParameterType('newsmenu',CLEAN_STRING); // should be int, or boolean
    $this->SetParameterType('parent_item',CLEAN_INT); // should be int, or boolean
    $this->SetParameterType('active_item',CLEAN_INT); // should be int, or boolean
###

The comments "Added By NaN" are not for ads here but just to mark what code is no default code of the Newsmodule.
Since you need to modify your NewsModule every time you updated it, it could be useful to mark where you made what changes.

Save the file.

Next step is to tell the Newsmodule to show only articles where the newsdate is within the selected year/month.
The modules output is processed either in a function called DoAction() within the initial module file or in a separat default file that will be executed when the module is just called with the {cms_module module="Module_Name"} syntax.
The default file is always called action.default.php. The NewsModule uses the default file method.
So open modules/News/action.default.php.
Look for the following code (near line 112):

Sample:

Code: Select all


...

$query1 .= "(".$db->IfNull('start_time',$db->DBTimeStamp(1))." < ".$db->DBTimeStamp(time()).") ";
$query2 .= "(".$db->IfNull('start_time',$db->DBTimeStamp(1))." < ".$db->DBTimeStamp(time()).") ";
if (isset($params['showarchive']) && $params['showarchive'] == true) {
  $query1 .= " AND (end_time < ".$db->DBTimeStamp(time()).") ";
  $query2 .= " AND (end_time < ".$db->DBTimeStamp(time()).") ";
 }

...

Put the queries 1 and 2 of the first two lines into an if-loop:

Code: Select all


if($newsmenu == false) # <- if-loop added by NaN for NewsMenu; queries are original code
{
	$query1 .= "(".$db->IfNull('start_time',$db->DBTimeStamp(1))." < ".$db->DBTimeStamp(time()).") ";
	$query2 .= "(".$db->IfNull('start_time',$db->DBTimeStamp(1))." < ".$db->DBTimeStamp(time()).") ";
}

if (isset($params['showarchive']) && $params['showarchive'] == true) {
  $query1 .= " AND (end_time < ".$db->DBTimeStamp(time()).") ";
  $query2 .= " AND (end_time < ".$db->DBTimeStamp(time()).") ";
 }

Before that code (near line 112) just insert the following one:

Code: Select all


### added by NaN for NewsMenu: ###
$newsmenu = false;
if(isset($params['newsmenu']) && (strtolower($params['newsmenu'])=='true' || $params['newsmenu']==true))
{
	$news =& $this->GetModuleInstance('NewsMenu');
	if( !$news )
	{
		return;
	}

	$parent_item = '';
	if(isset($params['parent_item']))
		$parent_item = $params['parent_item'];
	else if(isset($news->smarty->params[$news->smarty->id.'parent_item']))
	{
		$parent_item = $params['parent_item'] = $news->smarty->params[$news->smarty->id.'parent_item'];
	}
	else
	{
		foreach($_GET as $key=>$val)
		{
			if(endswith($key,'parent_item'))
			{
				$parent_item = $params['parent_item'] = $val;
			}
		}
	}
	
	$active_item = '';
	if(isset($params['active_item']))
		$active_item = $params['active_item'];
	else if(isset($news->smarty->params[$news->smarty->id.'active_item']))
	{
		$active_item = $params['active_item'] = $news->smarty->params[$news->smarty->id.'active_item'];
	}
	else
	{
		foreach($_GET as $key=>$val)
		{
			if(endswith($key,'active_item'))
			{
				$active_item = $params['active_item'] = $val;
			}
		}
	}
	
	if($parent_item != '')
	{
		if($parent_item == $active_item)
		{
			$news_date_min = mktime(0, 0, 0, 1, 1, $parent_item);
			$news_date_max = mktime(0, 0, 0, 1, 1, $parent_item+1);
		}
		else
		{
			$news_date_min = mktime(0, 0, 0, $active_item, 1, $parent_item);
			$news_date_max = mktime(0, 0, 0, $active_item+1, 1, $parent_item);
		}
		$query1 .= "(".$db->IfNull('start_time',$db->DBTimeStamp(1))." > ".$db->DBTimeStamp($news_date_min)." AND ";
		$query1 .= $db->IfNull('start_time',$db->DBTimeStamp(1))." < ".$db->DBTimeStamp($news_date_max).") ";
		$query2 .= "(".$db->IfNull('start_time',$db->DBTimeStamp(1))." > ".$db->DBTimeStamp($news_date_min)." AND ";
		$query2 .= $db->IfNull('start_time',$db->DBTimeStamp(1))." < ".$db->DBTimeStamp($news_date_max).") ";
		$newsmenu=true;
	}
}
###

After that we just need to add some params to the details links.
Look for the following uncommented code (near line 350 before and near line 430 after modification):

Sample:

Code: Select all


...

#CreateLink($id, $action, $returnid='', $contents='', $params=array(), $warn_message='', $onlyhref=false, $inline=false, $addttext='', $targetcontentonly=false, $prettyurl='')
...

Before that code insert the following one:

Code: Select all


### Added by NaN for NewsMenu: ###
      if (isset($params['parent_item']))
      {
	$sendtodetail['parent_item'] = $parent_item;
      }
      if (isset($params['active_item']))
      {
	$sendtodetail['active_item'] = $active_item;
      }
###


The last thing is to call the NewsMenu with the new param we defined in the News.module.php:

Code: Select all


{news newsmenu=true}

I hope that's all.

PS: this only works if NewsMenu and NewsModule are called together.
E.g. call the News within your content and the NewsMenu within your menu area.

I think it would be a better idea to create a plugin or userdefined tag of the NewsMenu instead of a module since it doesn't need any tables etc. But i dunno how to create a plugin with that code since it's indeed late for today.

Greetings from Germany,
NaN.
sam_butler
Forum Members
Forum Members
Posts: 24
Joined: Sun Jul 20, 2008 3:36 pm
Location: Manchester, UK

Re: News Archives by Year/Month

Post by sam_butler »

Cheers NaN. I'll give these changes a whirl, hopefully today. Looks like I have to put together a submission for the client this morning. Lots of jpegs to add... I'll get back to you when I've created the beast with your code  ;D
stopsatgreen
Power Poster
Power Poster
Posts: 322
Joined: Sat Feb 04, 2006 1:24 am
Location: London, England

Re: News Archives by Year/Month

Post by stopsatgreen »

I will need to create archive pages for each year. Not impossible, but I'd need to include in the documentation for my client how to do it each year,
All they should have to do is add a new page, and in the 'Date' block enter the year of the archive. My method is a little convoluted, but it has the advantage of not breaking if the News module is upgraded, which happens with NaN's version.

Of course, it would be better if the developers could be persuaded to add parameters to filter by date:

http://dev.cmsmadesimple.org/tracker/index.php?func=detail&aid=1550&group_id=8&atid=112
sam_butler
Forum Members
Forum Members
Posts: 24
Joined: Sun Jul 20, 2008 3:36 pm
Location: Manchester, UK

Re: News Archives by Year/Month

Post by sam_butler »

Agreed, it should be native to the module. Some people use it as a blog, which reminds me of WordPress' archive which appears in the sidebar. I think it was something like this that my client was looking for. I got your solution to work by the way, and I just set up a 2007 archive. There's news from 2003 to 2008 so I will have to create a page for each and what I meant was that in future, the client or his whoever is administering the site will need to add another page each year. It's hardly the most difficult thing, which is why I said I would just have to include it in my documentation. I think we could be on to a winner. I'm still exploring NaN's idea though.

Cheers mate!
User avatar
blast2007
Power Poster
Power Poster
Posts: 508
Joined: Wed Aug 01, 2007 5:36 pm

Re: News Archives by Year/Month

Post by blast2007 »

sam_butler wrote: Agreed, it should be native to the module. Some people use it as a blog, which reminds me of WordPress' archive which appears in the sidebar. I think it was something like this that my client was looking for. I got your solution to work by the way, and I just set up a 2007 archive. There's news from 2003 to 2008 so I will have to create a page for each and what I meant was that in future, the client or his whoever is administering the site will need to add another page each year. It's hardly the most difficult thing, which is why I said I would just have to include it in my documentation. I think we could be on to a winner. I'm still exploring NaN's idea though.

Cheers mate!
Hi all
you can use thisworking patch to achieve what you needs. Parameters are startperiod and endperiod.

Calguy told me that we have to wait until 1.4 is out before these kind of patches will be integrated in the official module. We hope.

Regards
blast
Post Reply

Return to “Developers Discussion”