Add tags to the CGBlog or News module
Previous article Next articleIn this tutorial I will show you a simple method (using Smarty) to add a tagging feature to the CGBlog, News and other modules in CMS Made Simple. In CGBlog you can use categories for tags, but the options are limited.
1. Add Field Definition
Go to the CGBlog or News Admin page, open the tab "Field Definitions" and add a field definition:
- Name: tags
- Type: Text Input
- Public: Checked
When adding or editing articles you will find a new field where you can fill in your comma separated words. Example: tag,tag2,tag3 (Note: only letters and numbers, don't use spaces)
2. Sort Array modifier to alphabetize the output
To sort the tag lists alphabetically I used the sort array modifier described in another article.
NOTE: If you don't want to use it, remove |sort_array in the templates below, otherwise your templates will break and you get a "very nice" error message...
3. Summary template
Create a new summary template, named i.e. "summary_tags"
{foreach from=$items item=entry}
{if (($entry->fieldsbyname.tags->value|strpos:$tag) !== false)}
<li>
<a href="{$entry->detail_url}" title="{$entry->title|escape:htmlall}">{$entry->title|escape}</a>
</li>
{/if}
{/foreach}
</ul>
+ Click here to show the News module template
{foreach from=$items item=entry}
{if (($entry->fields.tags->value|strpos:$tag) !== false)}
<li>
<a href="{$entry->moreurl}" title="{$entry->title|escape:htmlall}">{$entry->title|escape}</a>
</li>
{/if}
{/foreach}
</ul>
4. Detail template
Create a new detail template, named i.e. "detail_tags" and set it as default template.
{$detail_page = 'blog'}
{$taglist = $entry->fieldsbyname.tags->value}
{$tagwords = ','|explode:$taglist}
<ul id="taglist">
{foreach from=$tagwords|sort_array item=tagword}
<li>
{cms_selflink page=$detail_page urlparam="?tag=$tagword" text=$tagword}
</li>
{/foreach}
</ul>
<div style="clear: both;"></div>
<!-- The rest of the detail template -->
+ Click here to show the News module template
{$detail_page = 'news'}
{$taglist = $entry->fields.tags->value}
{$tagwords = ','|explode:$taglist}
<ul id="taglist">
{foreach from=$tagwords|sort_array item=tagword}
<li>
{cms_selflink page=$detail_page urlparam="?tag=$tagword" text=$tagword}
</li>
{/foreach}
</ul>
<div style="clear: both;"></div>
<!-- The rest of the detail template -->
You can change the detail page alias in the top of the template.
The use in a Multilingual website
When you have a MLE website you will have multiple detail pages! In that case change the detail page line {$detail_page = 'news'} in the top of the template to:
Call the i.e. News module in you page like this:
In the module are the News categories created like: en, nl, de and fr...
5. Stylesheet
Attach this sample stylesheet to your HTML-template.
margin: 0;
}
ul#taglist li {
float: left;
height: 28px;
margin: 5px;
list-style-type: none;
}
ul#taglist li a {
padding: 5px 10px;
text-decoration: none;
color: #333;
background: #EAE9E8;
-moz-border-radius 6px;
border-radius: 6px;
border: #ccc solid 1px;
font-weight: bold;
}
ul#taglist li a:hover {
background: #161616;
text-decoration: none;
font-weight: bold;
color: #fff;
}
6. Content page
Go to Content >> Pages and create a new page and set WYSIWYG off. This page need to be set as default detail page in your CGBlog or News module.
{$tag = $smarty.get.tag|default:''}
{if $tag == ''}
<!-- Default Content -->
{else}
<h3>Articles tagged with "{$smarty.get.tag}"</h3>
{CGBlog summarytemplate='summary_tags'}
{/if}
+ Click here to show the News module page content
{$tag = $smarty.get.tag|default:''}
{if $tag == ''}
<!-- Default Content -->
{else}
<h3>Articles tagged with "{$smarty.get.tag}"</h3>
{News summarytemplate='summary_tags'}
{/if}
Optional extention: tagcloud
Tagcloud template
This was the tricky part. In a few steps I read all the tags, separate them and show them only ones. Perhaps there is an easier method, but this works for me.
Create a new summary template, named i.e. "tagcloud"
{$detail_page = 'blog'} {* Change to your detailpage alias (default: blog) *}
{$globaltaglist = ''}
{* +++++ TEMPLATE +++++ *}
{* Read all tags and create one large string *}
{foreach from=$items item=entry}
{$globaltaglist = "{$globaltaglist},{$entry->fieldsbyname.tags->value}"}
{/foreach}
{* Show available tags *}
{$tagwords = ','|explode:$globaltaglist}
<ul id="taglist">
{foreach from=$tagwords|sort_array item=tagword}
{if ($tagword != '') && (($cleanedtaglist|strpos:$tagword) == false)}
{$cleanedtaglist = "{$cleanedtaglist},{$tagword}"}
<li>
{cms_selflink page=$detail_page urlparam="?tag=$tagword" text=$tagword}
</li>
{/if}
{/foreach}
</ul>
<div style="clear: both;"></div>
+ Click here to show the News module template
{$detail_page = 'news'} {* Change to your detailpage alias (default: news) *}
{$globaltaglist = ''}
{* +++++ TEMPLATE +++++ *}
{* Read all tags and create one large string *}
{foreach from=$items item=entry}
{$globaltaglist = "{$globaltaglist},{$entry->fields.tags->value}"}
{/foreach}
{* Show available tags *}
{$tagwords = ','|explode:$globaltaglist}
<ul id="taglist">
{foreach from=$tagwords|sort_array item=tagword}
{if ($tagword != '') && (($cleanedtaglist|strpos:$tagword) == false)}
{$cleanedtaglist = "{$cleanedtaglist},{$tagword}"}
<li>
{cms_selflink page=$detail_page urlparam="?tag=$tagword" text=$tagword}
</li>
{/if}
{/foreach}
</ul>
<div style="clear: both;"></div>
You can change the default detail page alias in the top of the template.
Calculate and display the number of items
If you want to display the number of items in the tagcloud you can add inside the <li></li>
You should need to change the styling to your own wishes...
Page or Sidebar
In a separate page or i.e. in your pages sidebar you can call the tagcloud like:
or show only one or more categories
+ Click here to show the News module page content
Note: In large websites with many articles you might consider using cache here. This is provided by Calguy's CGExtentions module. Read the module help text for more info how to use!
Working example
CGBlog module:
Comment Form
ReviewManager
ReviewManager
25 Comments
One addition to this nice tutorial, one has to set a high number as "Default Page limit:" in the Option-tab, because after the count of this number of articles CGBlog will stop, even if there are still articles that meet the tag-criterium.
Hi Rolf,
Thanks for the tutorial, very useful and great work!
I have a couple of questions:
1. If I use {cms_selflink page=$detail_page urlparam="&tag=$tagword" text=$tagword} the tag is not displayed, however if I use {$tagword} it works just fine. Here is the page: http://www.scifi-films.com/news/12/William-Shatner-in-Talks-for-Star-Trek-3 any idea why?
2. If I wanted to display blog posts with only particular tags in the blog summary how would I go about doing this? The idea would be to create a section on this page: http://www.scifi-films.com/movies/10836/Edge-of-Tomorrow where I would only display blog posts relating to that movie.
Cheers in advance,
Pete
Rolf,
I apologize for not being clear enough....
I am using this tutorial for my News Module in CMSMS 1.11.1
The core issue I am facing:
Yes I created a public text input field for tags, and yes put in some tags within some articles, but...the $smarty.get.tag in my content page is coming up blank. The $tag within my summary template is also coming up blank.
What would be some reasons for these two variables to be coming up blank, if the field definition exist. For example, I can do the following within my summary template and see my tags:
my tag value is: {$entry->fields.tag->value}
...but $tag and $smarty.get.tag does not work.
Thanks for any advice.
Thank you for this tutorial.
I'm using CMSMS 1.11.1
I'm stuck in the middle of this process...When you say "Read tag parameter from page URL", I don't have that in my URL for my news summary or news details pages. My URL's don't have a tag parameter, they look like this...
http://mysite/index.php?page=training-home
or with mod_rewrite on, they look like this...
http://mysite/training/training-home/
So what step am I missing or overlooking in order to enable a tag parameter in my URLs?
thanks for any advice
This TAG method can also be used in multilingual websites! I added the explanation to the blog in the detail template section.
Thanks, Rolf
@Frank
That part is explained in #4 above...
News template is hidden in a toggle.
I'm wondering how you display the tags that belong to a news article, like in http://www.smakelijketenzonderzout.nl/recepten/kip-tandoori where only the tags gevogelte, hoofdgerecht and kippenvlees are displayed.
I just can't figure that out.
Frank
This is impressive stuff, thanks Rolf.
Do you think it would be possible to use this to set up a search that allowed searching for combinations of tags, rather than just one tag at a time?
Instead of a jump menu/list of hyperlinks:
A1
A2
A3
There could be checkboxes for:
A1
A2
A3
B1
B2
B3
Users could choose A1 + B1 to search for items tagged as both categories - this would make the search much more powerful (especially when using CGBlog for more of a database of items, and not just a blog).
I posted a similar request for help onto the CMSMS forum too, but then came across your excellent work on tags, and wondered whether you or anyone else has had any thoughts on this...
I added the calculation and display of the number of items to the article.
thanks rolf, much simpler then my cludge at it ;)
came up with an addition to get the count using array_count_values.
{assign var=tagCount value=$tagwords|@array_count_values}
and then call it later with {$tagCount[$tagword]}
The foreach is the only affected area of the 'tagcloud' summary template:
{foreach from=$tagwords|sort_array item=tagword}
{assign var=tagCount value=$tagwords|@array_count_values}
{if ($tagword != '') && (($cleanedtaglist|strpos:$tagword) == false)}
{capture assign='cleanedtaglist'}{$cleanedtaglist},{$tagword}{/capture}
{cms_selflink page=$detail_page urlparam="&tag=$tagword" text=$tagword|capitalize} ({$tagCount[$tagword]})
{/if}
{/foreach}
@geepers
Add to the output list line: {$globaltaglist|substr_count:$tagword}
It will calculate and display the number of items with this tag
one more question on this rolf, have you worked out a way to indicate the number of articles associated with a tagword in the tagcloud template?
yes, exactly like that ;)
@geepers
You mean like {CGBlog category='foo' summarytemplate='tagcloud'}
Great article Rolf - thank you for posting this.
Would be interested to know if you've managed it while restricting searched articles/posts for the tags/tagcloud by category? So, only checking articles within a given category of either CGBlog or News.
before I start digging into this as a possible solution... Do you think there's a way to reconfigure this to list "related stories" instead of just tags? I'm trying to figure out how to get a list of the top #? of news stories that match the news page the user is on. Something like:
Related Stories
-------
story title 1
story title 2
story title 3
@benhenda
I am referring here to:
http://docs.cmsmadesimple.org/layout/stylesheets#basic-usage
Hi
Thanks for this tutorial. Can you please tell more about step 5 Stylesheet. What do yu mean by "html-template" ? which one ?
Thanks
Ben
I have reproduced and fixed it.
Change in the tagcloud template line:
{if (($cleanedtaglist|strpos:$tagword) == false) && ($tagword != '')}
into:
{if ($tagword != '') && (($cleanedtaglist|strpos:$tagword) == false)}
and it does work with empty tags
Grtz. Rolf
Thanks for the feedback, Christina and Frank.
Strange you are both getting the errors messages, as you can see it works at my website. And before posting, it was tested by another CMSMS forum member...
I will do some more tests and try to reproduce the errors.
Will be continued!
Oh, now I understand Christina's last comment:
In CGBLOG: tagcloud change:
{foreach from=$tagwords|sort_array item=tagword}
{if (($cleanedtaglist|strpos:$tagword) == false) ...
to:
{foreach from=$tagwords|sort_array item=tagword}
{if ($tagword eq '')}{elseif(($cleanedtaglist|strpos:$tagword) == false) ...
This indeed works.
As Christina I get a whole lot (about 70!) of identical warnings:
Warning: strpos() [function.strpos]: Empty delimiter in /home/vhosts/mydomnain.nl/httpdocs/tmp/templates_c/^712500124ec2a373bdb907fffa18d0e1c618f9c1.module_db_tpl.News;summarybf-tagcloud.php on line 71
Under these lines the tag buttons are shown.
What can be the cause of these warnings? How do I get rid of them?
Frank
The comment requires all lower case, but this is not apparent.
Also, the tag cloud works now if you don't have a tag for each entry:
.....
{foreach from=$tagwords|sort_array item=tagword}
{if ($tagword eq '')}{elseif (($cleanedtaglist ....
Thank you big time.
Thank you so much for this! Deeply appreciated.
On the tag cloud, this is the error I get because I believe that I don't have tags on every article.
Warning: strpos() [function.strpos]: Empty needle in ...
If this happens to make it through, your captcha doesn't work. Even though the string matches, it says it does not.