<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>&lt;RSS Title&gt;</title>
		<link>http://www.ssbits.com/snippets/</link>
		

		
		<item>
			<title>A _config.php Cheatsheet</title>
			<link>http://www.ssbits.com/a-config-php-cheatsheet/</link>
			<description>&lt;p&gt;If your anything like me, you've probably found yourself going through your previous sites looking for that line of code to put in your _config.php file. Well, now you nolonger need to, simply bookmark this page and return to it any time you need to add a line to your config! And if I've missed out anything leave a comment and I'll make sure it gets added :)&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;line-height: normal; white-space: pre-wrap;&quot;&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;?php
/**********************
 * 
 * Errors / Dev
 * 
 **********************/
//
//Force enviroment to Dev ** REMOVE FOR LIVE SITES **
Director::set_environment_type(&quot;dev&quot;);
//
//Force cache to flush on page load if in Dev mode (prevents needing ?flush=1 on the end of a URL)
if (Director::isDev()) {
	SSViewer::flush_template_cache();
}
//(v2.4) Log errors to an email address
SS_Log::add_writer(new SS_LogEmailWriter('me@mydomain.com'), SS_Log::ERR); 
//
//(v2.4) Log errors to a file
SS_Log::add_writer(new SS_LogFileWriter('error_log.txt'), SS_Log::ERR); 
//
/**********************
 * 
 * CMS Rebranding
 * 
 **********************/
//
//Set the CMS application name, logo and loading image
LeftAndMain::setApplicationName(&quot;My application&quot;);
LeftAndMain::setLogo(&quot;themes/MyTheme/images/CMSLogo.png&quot;, &quot;margin-top: -3px;&quot;);
LeftAndMain::set_loading_image('themes/MyTheme/images/CMSLoading.gif');
//
/**********************
 * 
 * Security
 * 
 **********************/
//
//Set default login
Security::setDefaultAdmin('admin','pass');
//
//Define the password validator
$pwdValidator = new PasswordValidator();
$pwdValidator-&amp;gt;minLength(8);
$pwdValidator-&amp;gt;checkHistoricalPasswords(2);
$pwdValidator-&amp;gt;characterStrength(2,array('lowercase','digits'));
Member::set_password_validator($pwdValidator);
//
// Set the site locale
i18n::set_locale('en_UK');
//
/**********************
 * 
 * Templates / ULRs
 * 
 **********************/
//
//Remove Prototype / Behaviour validation and use your own
Validator::set_javascript_validation_handler('none'); 
//
// Set the theme
SSViewer::set_theme('FBO');
//Enable Search, use $SearchForm in template
FulltextSearchable::enable();
//
//Turn off # link rewriting
SSViewer::setOption('rewriteHashlinks', false);
//
//Force redirect to www.
Director::forceWWW();
//
//(v2.4) enable nested URLs for this site (e.g. page/sub-page/) 
SiteTree::enable_nested_urls();
//
// Set the Breadcrumb divider
SiteTree::$breadcrumbs_delimiter = &quot; &amp;gt;&amp;gt; &quot;;
//
// Set the resizing image quality
GD::set_default_quality(95);
//
/**********************
 * 
 * CMS UI
 * 
 **********************/
//
//Hide a main CMS Tab
LeftAndMain::remove_menu_item('Reports');
//
//Make a data objects sortable (for DOM)
SortableDataObject::add_sortable_classes(array(
		'DataObject',
		'AnotherDataObject'
));
//
//Set HTML EDitor Config
HtmlEditorConfig::get('cms')-&amp;gt;setOption('convert_fonts_to_spans', false);
//
HtmlEditorConfig::get('cms')-&amp;gt;enablePlugins('searchreplace');
//
HtmlEditorConfig::get('cms')-&amp;gt;insertButtonsAfter('pasteword', 'replace');
//
HtmlEditorConfig::get('cms')-&amp;gt;setOptions(array( 'content_css' =&amp;gt; 'static/css/editor.css' )); 
//
//Add requirments to the CMS
LeftAndMain::require_javascript('mysite/javascript/jquery.cms.js');
//
LeftAndMain::require_css('themes/mytheme/css/cms.css');
//
/**********************
 * 
 * Classes / Objects
 * 
 **********************/
//
//Add an extention to an object and DataObject
Object::add_extension('SiteConfig', 'CustomSiteConfig');
DataObject::add_extension('DataObject', 'DataObjectExtension');
//
// Use a custom class instead of a core one
Object::useCustomClass('MemberLoginForm', 'CustomLoginForm');
//
//Set allowed file types
File::$allowed_extensions[] = &quot;f4v&quot;;
//
/**********************
 * 
 * Emails
 * 
 **********************/
//
//Set the admin email address
Email::setAdminEmail('me@mydomain.com');
//
//Set to CC all emails to
Email::cc_all_emails_to('me@mydomain.com');
//
/**********************
 * 
 * Comments
 * 
 **********************/
//
//Enable comment spam protection
MathSpamProtection::setEnabled();
//
//Enable comment moderation
PageComment::enableModeration();
//
//Force user to be logged in to post a comment
PageCommentInterface::set_comments_require_login(true);&lt;/textarea&gt; &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 02 Jul 2010 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/a-config-php-cheatsheet/</guid>
		</item>
		
		<item>
			<title>Customise buttons in userforms module</title>
			<link>http://www.ssbits.com/customise-buttons-in-userforms-module/</link>
			<description>&lt;p&gt;I wanted more control over the styling of submit buttons in the userforms module. The standard button use either an &lt;strong&gt;&amp;lt;input&amp;gt;&lt;/strong&gt; tag or a &lt;strong&gt;&amp;lt;button&amp;gt;&lt;/strong&gt; tag. I needed an extra span so I could &lt;a href=&quot;http://www.filamentgroup.com/lab/styling_the_button_element_with_sliding_doors/&quot;&gt;style the button super pretty&lt;/a&gt;, &lt;span class=&quot;hw&quot;&gt;&amp;agrave; la:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;button&amp;gt;&amp;lt;span&amp;gt;Submit!&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&lt;/textarea&gt; &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So I extended UserDefinedForm by putting the file 'MyForm' in mysite/code:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class MyForm extends UserDefinedForm {
	
}
class MyForm_Controller extends UserDefinedForm_Controller {
	
	/**
	 * Customise User Defined Form. Add a prettier submit button
	 *
	 * (Actually overriding the model, but template calls this controller function)
	 *
	 * @return Form
	 */
	public function Form() {
		$form = parent::Form();
		
		$submit = new FormAction(&quot;process&quot;, $form-&amp;gt;SubmitButtonText);
		$submit-&amp;gt;useButtonTag = true;
		$submit-&amp;gt;setButtonContent('&amp;lt;span&amp;gt;Submit&amp;lt;/span&amp;gt;');
		
		$form-&amp;gt;actions = new FieldSet($submit);
		
		return $form;
	}
	
}&lt;/textarea&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 12 Jun 2010 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/customise-buttons-in-userforms-module/</guid>
		</item>
		
		<item>
			<title>Customize the Redirect after a successful Member Login</title>
			<link>http://www.ssbits.com/customize-the-redirect-after-a-successful-member-login/</link>
			<description>&lt;p&gt;The Member system that comes with SilverStripe offers substantial control over your site's authentication capabilities. &amp;nbsp;It often requires the developer to build out or extend most common functionality to websites. &amp;nbsp;This is great in that you are never &quot;stuck&quot; with the out-of-the-box offerings, but as any SS dev knows you end up with a little bag of Member tricks that gets used across many projects. &amp;nbsp;Presented here is one that I use often.&lt;/p&gt;
&lt;p&gt;When a Member logs in to /Security/login without a ?BackURL= specified, they are always redirected back to the form with a success message and form without any fields. &amp;nbsp;While this works great to keep the code/form tight, it is a less than ideal use experience. &amp;nbsp;Modifying this behavior is a little tricky as much of the controller and rendering actions are fixed in the Security class. &amp;nbsp;This is further complicated by the use of &lt;em&gt;Director::redirect&lt;/em&gt; calls that set response headers when the login form is processed. &amp;nbsp;I find by overriding the form and replacing it with the excellent&amp;nbsp;&lt;em&gt;useCustomClass&lt;/em&gt; call works well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Base /Security/login form redirects to itself on success, always tagging &lt;em&gt;?BackURL=/home&lt;/em&gt; looks sort of messy across your site.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Make the base &lt;em&gt;MemberLoginForm&lt;/em&gt; redirect somewhere useful on success.&lt;/p&gt;
&lt;p&gt;We begin by extending the &lt;em&gt;MemberLoginForm&lt;/em&gt; and the method that does all the dirty work; &lt;em&gt;dologin()&lt;/em&gt;. &amp;nbsp;Create the file &lt;strong&gt;GoHomeLoginForm.php&lt;/strong&gt; and add the following code:&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;?php
/**
 * Overriding the base login form to redirect somewhere useful,
 * in this case to the site index
 */
class GoHomeLoginForm extends MemberLoginForm {
	public function dologin($data) {
		parent::dologin($data);
		if( Director::redirected_to() and Member::currentUserID() ) {
			$this-&amp;gt;controller-&amp;gt;response-&amp;gt;removeHeader('Location');
			Director::redirect(Director::baseURL());
		}
	}
}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Now we need to override the &lt;em&gt;MemberLoginForm&lt;/em&gt; with our &lt;em&gt;GoHomeLoginForm&lt;/em&gt; in our &lt;strong&gt;_config.php&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;/*	Always redirect somewhere meaningful */
Object::useCustomClass('MemberLoginForm', 'GoHomeLoginForm');&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Now do a &lt;em&gt;/dev/build/flush=all&lt;/em&gt; and you're gold.&lt;/p&gt;
&lt;p&gt;Testing for a redirect being set and a current member set in the session ensures that only users who have successfully logged in will get our custom destination. &amp;nbsp;You can override with any destination you please, such as a '&lt;em&gt;/myaccount/&lt;/em&gt;' section or even plain old '/'.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This has been tested on SS 2.3 and 2.4 using the default Member Authenticator.&lt;/em&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 31 May 2010 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/customize-the-redirect-after-a-successful-member-login/</guid>
		</item>
		
		<item>
			<title>Controlling the order of CSS includes</title>
			<link>http://www.ssbits.com/controlling-the-order-of-css-includes/</link>
			<description>&lt;p&gt;Usually CSS developers are lazy -even more so than php developers! What usually happens is (as you can see in firebug) that styles get redefined by sub CSS files depeding on a parent containing div -so it's important to include these CSS files in the correct order, otherwise they will be overwritten incorrectly and the style wont appear as you wish.&lt;/p&gt;
&lt;p&gt;Your probably already using Requirements::themedCSS but there is another function called Requirements::insertHeadTags. This is great for including custom style sheets because you can call it AFTER your usuall CSS. An example would be something like;&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class Page_Controller extends ContentController {
	public function init() {
		parent::init();
        Requirements::themedCSS(&quot;main&quot;);
        Requirements::themedCSS(&quot;panels&quot;);
        
         // Include the conditional css for ie6 &amp;amp; ie7
        $tags = '&amp;lt;!--[if lte IE 6]&amp;gt;
        &amp;lt;mce:style type=&quot;text/css&quot;&amp;gt;&amp;lt;!--
        @import url(/themes/myamazingtheme/css/ie6.css);
        
--&amp;gt;&amp;lt;/mce:style&amp;gt;&amp;lt;style type=&quot;text/css&quot; mce_bogus=&quot;1&quot;&amp;gt;        @import url(/themes/myamazingtheme/css/ie6.css);
        &amp;lt;/style&amp;gt;
        &amp;lt;![endif]--&amp;gt;
        
        &amp;lt;!--[if IE 7]&amp;gt;
        &amp;lt;mce:style type=&quot;text/css&quot;&amp;gt;&amp;lt;!--
        @import url(/themes/myamazingtheme/css/ie7.css);
        
--&amp;gt;&amp;lt;/mce:style&amp;gt;&amp;lt;style type=&quot;text/css&quot; mce_bogus=&quot;1&quot;&amp;gt;        @import url(/themes/myamazingtheme/css/ie7.css);
        &amp;lt;/style&amp;gt;
        &amp;lt;![endif]--&amp;gt;';
        Requirements::insertHeadTags($tags);
	}
}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;This is not very often picked up on as developers use firefox (and 
firebug) without any real IE6/7 testing, and if you view source on this site you will see that ie6/7 css are being included &lt;strong&gt;after&lt;/strong&gt; standard stylesheets. This means any special styles that overwrite previous styles to create a fix wont work -as they are being called in the wrong order.&lt;/p&gt;
&lt;p&gt;Hopefully this helps someone, as Id spent alot of time editing stylesheets and flushing all only to see no change -its useful to note when creating complex design sites.&lt;/p&gt;</description>
			<pubDate>Fri, 23 Apr 2010 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/controlling-the-order-of-css-includes/</guid>
		</item>
		
		<item>
			<title>Automatically ?flush when in 'dev' mode</title>
			<link>http://www.ssbits.com/automatically-flush-when-in-dev-mode/</link>
			<description>&lt;p&gt;Often when doing development work on a website - and particularly the templates - it can be a pain having to remember to add &lt;strong&gt;?flush&lt;/strong&gt;&amp;nbsp;to the end of the URL to make sure all of your changes have come through.&lt;/p&gt;
&lt;p&gt;I'm sure that all of us have had that &quot;d'oh&quot; moment when we have spent too much time wondering why our changes weren't working, only to find a simple flush fixed it.&lt;/p&gt;
&lt;p&gt;If you have set up a domain in your &lt;strong&gt;set_dev_servers&lt;/strong&gt; array or added &lt;strong&gt;Director::set_environment_type('dev') &lt;/strong&gt;to your &lt;strong&gt;_config.php&lt;/strong&gt; file then you can also add:&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;if (Director::isDev()) {
SSViewer::flush_template_cache();
}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;This will flush the template cache on every page load.&lt;/p&gt;
&lt;p&gt;NB: This will not regenerate cached images, if you want to do that you will have to add &lt;strong&gt;$_GET['flush'] = 1;&lt;/strong&gt; inside the above conditional statement.&lt;/p&gt;</description>
			<pubDate>Thu, 15 Apr 2010 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/automatically-flush-when-in-dev-mode/</guid>
		</item>
		
		<item>
			<title>Using other systems together with Silverstripe</title>
			<link>http://www.ssbits.com/using-other-systems-together-with-silverstripe/</link>
			<description>&lt;p&gt;&lt;span style=&quot;color: #000000; font-family: Times; font-size: medium; line-height: normal;&quot;&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ffffff; background-position: initial initial; margin: 8px;&quot;&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;Silverstripe uses mod_rewrite to catch all calls to your website in the form of urls and route them to&amp;nbsp;sapphire/main.php. This behavior is implemented with the rules in your &lt;strong&gt;.htaccess&lt;/strong&gt; file in the root of your site. This can become a problem when you want to use other systems together with Silverstripe because you simply can not reach the url of those other systems.&lt;/p&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;&lt;strong style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;An example:&lt;/strong&gt;&amp;nbsp;if your want to use&amp;nbsp;&lt;a style=&quot;text-decoration: none; color: #2f98d4; font-family: Verdana, Lucida, sans-serif;&quot; href=&quot;http://www.phplist.com/&quot;&gt;phplists&lt;/a&gt;&amp;nbsp;as a newsletter system, it is usually installed under yoursite.com/lists. However, under normal circumstances you can not have your visitors reach yoursite.com/lists when using Silverstripe because it is rerouted to&amp;nbsp;sapphire/main.php?url=lists.&lt;/p&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;This behavior can be changed by adding a rule to your &lt;strong&gt;.htaccess&lt;/strong&gt; file. I use this one:&lt;/p&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;RewriteCond %{REQUEST_URI} !^/_.*/.*&lt;/textarea&gt;&lt;/p&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;(This snippet has to appear before the&amp;nbsp;&lt;span style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;&lt;strong&gt;RewriteRule&lt;/strong&gt;&lt;/span&gt;&amp;nbsp;that routes everything to&amp;nbsp;sapphire/main.php otherwise it wont work.)&lt;/p&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;&lt;strong style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;What does this do?&lt;/strong&gt;&amp;nbsp;If someone tries to access an address on your site in a folder starting with an underscore (_) do not apply rules to it (and therefore do not route it to&amp;nbsp;sapphire/main.php).&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;&lt;strong style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;What can you do with it?&lt;/strong&gt;&amp;nbsp;If you create a folder in your site starting with an underscore (for example:&amp;nbsp;&lt;em style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;_lists&lt;/em&gt;) it will be ignored by silverstripe. So if you install phplists there (or any other system or a static html/flash site) you can simply use it without problem along with Silverstripe in the same site.&lt;/p&gt;
&lt;p style=&quot;font-family: Verdana, Lucida, sans-serif; color: #555555; line-height: 1.6em; font-size: 1.4em; padding-top: 10px; padding-right: 0px; padding-bottom: 10px; padding-left: 0px;&quot;&gt;I have tested this with Silverstripe 2.3+ and 2.4 Beta1&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Mon, 22 Mar 2010 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/using-other-systems-together-with-silverstripe/</guid>
		</item>
		
		<item>
			<title>Securing your site</title>
			<link>http://www.ssbits.com/securing-your-site/</link>
			<description>&lt;p&gt;PHP has a very shallow learning curve, it's free and anyone can have a go at making a website by following a few tutorials and implementing their experience with other languages. However, coding for the web can be a risky business, especially with dynamic websites that take some kind of user (or external) input and use that to get data from a database.&lt;/p&gt;
&lt;p&gt;Old school websites will use an id to get a pages content, eg: www.example.com/index.php?id=3. This can lead to a few problems if the id is not sanitised before being added to an SQL query.&lt;/p&gt;
&lt;h3&gt;Sanitising Variables&lt;/h3&gt;
&lt;p&gt;Here is how it would work if calling &lt;strong&gt;/index?id=1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;strong&gt;&amp;lt;?PHP $id = $_GET['id']; $sql = 'SELECT `Content` FROM `Page` WHERE ID = ' . $id;&lt;/strong&gt; ... &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This leaves us in a very sticky situation. If someone were to put in a non-numeric id into the GET var or were to do something worse like '&lt;strong&gt;1; DROP TABLE `Page`;&lt;/strong&gt;' then you will find yourself with a big mess to clean up.&lt;/p&gt;
&lt;h3&gt;SQL Injection&lt;/h3&gt;
&lt;p&gt;This is known as SQL Injection and is just one of the &lt;a href=&quot;http://www.smashingmagazine.com/2010/01/14/web-security-primer-are-you-part-of-the-problem/&quot;&gt;many security holes&lt;/a&gt; that people can get into. If a user submits data you should always make sure it is valid and sanitised.&lt;/p&gt;
&lt;h2&gt;Solving the problem&lt;/h2&gt;
&lt;p&gt;Validating your inputs is very simple and effective way of stopping this problem for the id example, if you are expecting a number, check it is by using the is_numeric function.&lt;/p&gt;
&lt;p&gt;Sanitise your variables before they are put into the SQL query by using silverstripes &lt;a href=&quot;http://api.silverstripe.org/sapphire/misc/Convert.html&quot;&gt;Convert class&lt;/a&gt;. The Convert class converts strings from one format to another so that they can be included in different document types without security or parsing implications.&lt;/p&gt;
&lt;p&gt;Here is how to deal with a typical situation in SilverStripe, when getting a DataObject from the DB depending on an actions URL:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;	function getPageByIDParam() { 
	
		$action = Director::urlParam('ID'); // in this case it is a string 
		
		return DataObject::get('Page','URLSlug = &quot;' . Convert::raw2sql($action) . '&quot;',null,null,1); 
	} &lt;/textarea&gt;  &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now you wont be a victim of SQL injection.&lt;/p&gt;
&lt;h2&gt;&lt;span style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;Controller Actions&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;In SilverStripe, methods in the controller are called by using the action part of the URI (&lt;strong&gt;www.example.com/URLSegment/Action/ID/OtherID&lt;/strong&gt;) and this can be bad for security as we don't really want people to be able to call any method via the action.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;To stop users from being able to call any action, use the Controllers Static var &lt;a href=&quot;http://doc.silverstripe.org/doku.php?id=security#limiting_url-access_to_controller_methods&quot;&gt;$allowed_actions&lt;/a&gt;. Which is an array that lists the actions that can be called through the action parameter in the URL:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Verdana, Lucida, sans-serif;&quot;&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class Page_Controller extends ContentController { 
	static $allowed_actions = array(
		'SomeFunction',
		'AnotherFunction'
	);
}&lt;/textarea&gt; &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;More information&lt;/h2&gt;
&lt;p&gt;SilverStripe have great information on secruity:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://doc.silverstripe.org/doku.php?id=secure-development&quot;&gt;http://doc.silverstripe.org/doku.php?id=secure-development&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://doc.silverstripe.org/doku.php?id=security&quot;&gt;http://doc.silverstripe.org/doku.php?id=security&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Fri, 12 Mar 2010 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/securing-your-site/</guid>
		</item>
		
		<item>
			<title>Database Configuration Management</title>
			<link>http://www.ssbits.com/database-configuration-management/</link>
			<description>&lt;p&gt;Wouldn't it be easy to have a single environment configuration for all your SilverStripe sites without having to reconfigure each one individually? Wouldn't it be great not to have to change environment settings when you push your site from development to live servers? This is easy to achieve using the SilverStripe &quot;ConfigureFromEnv&quot; script.&lt;/p&gt;
&lt;p&gt;To set this up, remove your $databaseConfig line from your site &lt;strong&gt;_config.php&lt;/strong&gt; and add:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mysite/_config.php&lt;/strong&gt;&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;require_once(&quot;conf/ConfigureFromEnv.php&quot;);&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Then create a new &lt;strong&gt;_ss_environment.php&lt;/strong&gt; file. This can live in your web root, in it's parent or it's parent parent folder. Define the following constants:&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;_ss_enviroment.php&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;/* What kind of environment is this: development, test, or live (ie, production)? */
define('SS_ENVIRONMENT_TYPE', 'dev/test/live');

/* Database connection */
define('SS_DATABASE_SERVER', 'localhost');
define('SS_DATABASE_USERNAME', 'root');
define('SS_DATABASE_PASSWORD', '');

/* Configure a default username and password to access the CMS on all sites in this environment. */
define('SS_DEFAULT_ADMIN_USERNAME', 'username');
define('SS_DEFAULT_ADMIN_PASSWORD', 'password');&lt;/textarea&gt; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now your &lt;strong&gt;_config.php&amp;nbsp;&lt;/strong&gt;file only needs one setting, a &lt;strong&gt;$database&lt;/strong&gt; parameter that points SilverStripe to the correct database for this server!&lt;/p&gt;</description>
			<pubDate>Wed, 17 Feb 2010 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/database-configuration-management/</guid>
		</item>
		
		<item>
			<title>Disable Default JavaScript Behaviours</title>
			<link>http://www.ssbits.com/disable-default-javascript-behaviours/</link>
			<description>&lt;p&gt;By default SilverStripe uses bulky and sometimes unwanted JavaScript libraries to handle form validation and AJAX page commenting features. Often you want to disable this behaviour so you can integrate your own JavaScript code. This is easily achieved with the following two lines in you site configuration file:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mysite/_config.php&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;Validator::set_javascript_validation_handler('none');
PageCommentInterface::set_use_ajax_commenting(false);&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Now you are free to add the behaviours you want to your view (templates) without the hassle of unpredictable SilverStripe JavaScript includes.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Mon, 15 Feb 2010 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/disable-default-javascript-behaviours/</guid>
		</item>
		
		<item>
			<title>Add attachments to Silverstripe Form submissions</title>
			<link>http://www.ssbits.com/add-attachments-to-silverstripe-form-submissions/</link>
			<description>&lt;p&gt;Today I was trying to add a CV file to a silverstripe form for a project and noticed that is not that easy as it sounds. Well with the help of Martijn we figured it out:&lt;/p&gt;
&lt;p&gt;First the form&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;function ApplyForm(){                                
	return new Form($this, &quot;ApplyForm&quot;,
		new FieldSet(
			new TextField('FullName','Full Name'),
			new EmailField('Email'),		
			new FileField('CV','upload your CV')
		),
		new FieldSet(
			new FormAction(&quot;ApplyAction&quot;, &quot;submit your cv&quot;)
		), new RequiredFields(
     		&quot;FullName&quot;
		)
	);
}
&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;It's a really simple form but it takes the information we want. Now the function that sends the mail:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;function ApplyAction($data, $form) {
	$email = new Email();
	$email-&amp;gt;setTemplate('Job_Applicant');
	$email-&amp;gt;populateTemplate($data);
	$email-&amp;gt;setTo(&quot;fa@dospuntocero.cl&quot;);  
	$email-&amp;gt;setFrom(&quot;postulaciones@sehop.org&quot;);  		
	$email-&amp;gt;setSubject('New job applicant');
	$email-&amp;gt;populateTemplate($data);
	// thats the tricky part for the files attaced
    if (isset($_FILES[&quot;CV&quot;]) &amp;amp;&amp;amp; is_uploaded_file($_FILES[&quot;CV&quot;][&quot;tmp_name&quot;])) {
       $email-&amp;gt;attachFile($_FILES[&quot;CV&quot;][&quot;tmp_name&quot;], $_FILES[&quot;CV&quot;][&quot;name&quot;]);
    }
	$email-&amp;gt;send();			  
					
	$form-&amp;gt;sessionMessage(&quot;el mail de postulaci&amp;oacute;n ha sido enviado correctamente&quot;, 'important');
	Director::redirectBack();
}	
&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;With the use of this little function you will get the file uploaded and attached to your email.&lt;/p&gt;
&lt;p&gt;amazingly simple isn't it?&lt;/p&gt;</description>
			<pubDate>Tue, 05 Jan 2010 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/add-attachments-to-silverstripe-form-submissions/</guid>
		</item>
		
		<item>
			<title>Select a theme using a URL parameter</title>
			<link>http://www.ssbits.com/select-a-theme-using-a-url-parameter/</link>
			<description>&lt;p&gt;When I develop SilverStripe sites, I usually get functionality working in the default theme &lt;em&gt;blackcandy&lt;/em&gt; before getting it working in the final templates. This way, authors can start adding content and seeing how it looks on the page, and I can get early feedback about the functionality. Also, as a developer I get to see real content in the browser early in the process. So does the designer.&lt;/p&gt;
&lt;p&gt;I'm sure this process is nothing new - and I realise form-first vs function-first is an old debate - but one thing I wanted to share is some code my team and the client found useful in a recent project.&lt;/p&gt;
&lt;p&gt;I added the ability to select a theme based on a parameter in the URL, either for the current page request or for session. This meant we were able to throw around URLs specifying the theme, choosing a theme depending on whether we were discussing the (visual) design or the functionality and content.&lt;/p&gt;
&lt;p&gt;http://www.mywebsite.com/myurlsegment/&lt;strong&gt;?theme=blackcandy&lt;/strong&gt;&lt;br /&gt;sets the theme for a single request.&lt;/p&gt;
&lt;p&gt;http://www.mywebsite.com/myurlsegment/&lt;strong&gt;?setTheme=blackcandy&lt;/strong&gt;&lt;br /&gt;sets the theme for the session.&lt;/p&gt;
&lt;p&gt;Early in the client project, I made sure all the functionality and content worked in both themes, but as more pages worked in the real theme, we left &lt;em&gt;blackcandy&lt;/em&gt; behind.&lt;/p&gt;
&lt;p&gt;Having said that, I kept the most involved pages working in &lt;em&gt;blackcandy&lt;/em&gt; right until the end, so we could always view the new content, such as a large image due to be displayed in a lightbox, or content due to be included in a slider effect was implemented. That way, we kept the feedback coming: by the time the lightbox effect worked, we already knew the image was getting all the way from author to browser, appropriately downsampled and compressed, and everyone was already happy with the size and quality of the large image.&lt;/p&gt;
&lt;p&gt;Here's the essence of code, suitably unrefactored for your viewing pleasure.&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class Page_Controller extends ContentController {

  function init() {
    parent::init();

    if (isset($_GET['setTheme'])) {
      if (Director::isDev() || Permission::check('ADMIN')) {
        Session::set('theme', $_GET['setTheme']);
      } else {
        Security::permissionFailure(null,
          'Please log in as an administrator to switch theme.');
      }
    }

    if (isset($_GET['theme'])) {
      if (Director::isDev() || Permission::check('ADMIN')) {
        SSViewer::set_theme($_GET['theme']);
      } else {
        Security::permissionFailure(null,
          'Please log in as an administrator to set the theme.');
      }

    } elseif (Session::get('theme')) {
      SSViewer::set_theme(Session::get('theme'));
    }

  }&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;See also Martijn van Nieuwenhoven's SSbits snippet:&lt;br /&gt;
&lt;a href=&quot;http://www.ssbits.com/../create-a-front-end-theme-switcher/&quot; target=&quot;_self&quot;&gt;http://www.ssbits.com/create-a-front-end-theme-switcher/&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 21 Dec 2009 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/select-a-theme-using-a-url-parameter/</guid>
		</item>
		
		<item>
			<title>Using a Print Stylesheet</title>
			<link>http://www.ssbits.com/using-a-print-stylesheet/</link>
			<description>&lt;p&gt;Often people want to be able to print webpages without all the menus and graphics and with all the content fitting correctly onto a page. To do this you need to create a separate print stylesheet. It would look something like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;themes/YOURTHEME/css/print.css&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;#sidebar, 
#header, 
#navbar, 
#footer {
	display: none;
}
#container, 
#content{
	width: 100%; 
	margin: 0; 
	float: none;
}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Then all you need to do to include this in your page is to run a seperate &lt;strong&gt;Requirements&lt;/strong&gt; call and specify that it is for &lt;strong&gt;print &lt;/strong&gt;within the&lt;strong&gt; init() &lt;/strong&gt;function of your &lt;strong&gt;Page_controller&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mysite/code/Page.php&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;Requirements::css(&quot;themes/YOURTHEME/css/print.css&quot;,&quot;print&quot;);	&lt;/textarea&gt; &lt;/p&gt;</description>
			<pubDate>Wed, 16 Dec 2009 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/using-a-print-stylesheet/</guid>
		</item>
		
		<item>
			<title>Extend Meta description beyond 255 character limit</title>
			<link>http://www.ssbits.com/extend-meta-description-beyond-255-character-limit/</link>
			<description>&lt;p&gt;Search engines prefer to display a description in their result pages that include the keywords searched for, to ensure they pick and mix sentences from your meta description rather than random bits from your page it can be helpful to have a longer meta description. This allows for more room to include your keywords.&lt;/p&gt;
&lt;p&gt;Changing the field length couldn't be simpler, in the file &lt;strong&gt;mysite/code/Page.php&lt;/strong&gt; add the MetaDescription type as Text.&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class Page extends SiteTree {

    public static $db = array(     
        'MetaDescription' =&amp;gt; 'Text'   // Change field to use 'Text'
    );

}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Wed, 25 Nov 2009 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/extend-meta-description-beyond-255-character-limit/</guid>
		</item>
		
		<item>
			<title>Add Syntax Highlighting to the SS Forums</title>
			<link>http://www.ssbits.com/add-syntax-highlighting-to-the-ss-forums/</link>
			<description>&lt;p&gt;Get &lt;a href=&quot;http://www.mozilla-europe.org/en/firefox/&quot;&gt;Firefox&lt;/a&gt;, install &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/748&quot; target=&quot;_blank&quot;&gt;Greasemonkey&lt;/a&gt;, Then install the following userscript:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.silverstripe.org/assets/Uploads/silverstripeforumscode0.1.user.js&quot;&gt;http://www.silverstripe.org/assets/Uploads/silverstripeforumscode0.1.user.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://img190.imageshack.us/img190/476/ssforumcodehighlighting.png&quot; alt=&quot;Silverstripe Forums Code Highlighting&quot; width=&quot;651&quot; height=&quot;275&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Updates and more here: &lt;a href=&quot;http://www.silverstripe.org/general-questions/show/272688&quot;&gt;http://www.silverstripe.org/general-questions/show/272688&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 11 Nov 2009 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/add-syntax-highlighting-to-the-ss-forums/</guid>
		</item>
		
		<item>
			<title>Using dates in foreign Languages</title>
			<link>http://www.ssbits.com/using-dates-in-foreign-languages/</link>
			<description>&lt;p&gt;With all the translatable, i18n and other translation related stuff in silverstripe, I think more than one is wondering how to achieve something simple as using dates in a foreign language... Actually, it's ultra easy if you add this 2 lines in your silverstripe powered website: (my spanish example)&lt;/p&gt;
&lt;p&gt;in _config.php: &lt;strong&gt;&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;setlocale(LC_ALL, 'es_ES');   &lt;/textarea&gt; &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;in your template:&lt;strong&gt;&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;$Date.FormatI18N(%A %e de %B de %Y)&lt;/textarea&gt; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;this will render: &lt;strong&gt;&lt;em&gt;&lt;br /&gt;mi&amp;eacute;rcoles 21 de octubre de 2009&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;</description>
			<pubDate>Sat, 07 Nov 2009 00:00:00 -0600</pubDate>
			
			
			<guid>http://www.ssbits.com/using-dates-in-foreign-languages/</guid>
		</item>
		
		<item>
			<title>Overriding Silverstripes language files with your own</title>
			<link>http://www.ssbits.com/overriding-silverstripes-language-files-with-your-own/</link>
			<description>&lt;h3&gt;The problem&lt;br /&gt;&lt;/h3&gt;
&lt;p&gt;In my most recent project I've had to run a site in another language (Swedish) and run into some issues which I thought I'd share with all of you.&lt;/p&gt;
&lt;p&gt;Now Silverstripe probably comes with a translation for your language but even if it does, you probably want to change the wording of some of the phrases, so what to do?&lt;/p&gt;
&lt;p&gt;You could of course hit up the language files for the relevant module or the ones in cms and sapphire but you really don't want to touch these files if you can help it.&lt;/p&gt;
&lt;h3&gt;The solution&lt;/h3&gt;
&lt;p&gt;The way Silverstripe reads the language files is by going through the directory looking for directories with a &lt;strong&gt;_config.php&lt;/strong&gt; file and a lang directory. Later files in the chain overwrite the earlier files if they contain the same info so the solution is to create a folder which ends up last in the chain.&lt;/p&gt;
&lt;p&gt;Personally I created a folder called &lt;strong&gt;zlang&lt;/strong&gt;, put a &lt;strong&gt;_config.php&lt;/strong&gt; file in the folder with just open and close PHP tags and then putting my language file in &lt;strong&gt;zlang/lang&lt;/strong&gt;. After having done this I can override any translation I want to without touching the core files. You can of course name your folder whatever you want.&lt;/p&gt;
&lt;p&gt;There is however one big bug in Silverstripes translations, namely that Silverstripe currently does not resolve nested include templates correctly. This means that if a template is included which in turn includes other templates Silverstripe will look for the translation in the included template and not the nested one.&lt;/p&gt;
&lt;p&gt;An example of this is the &lt;strong&gt;PageComment-template&lt;/strong&gt; which includes&lt;strong&gt; PageComment_single.ss&lt;/strong&gt;. In order to guarantee that your translation works you will have to translate both &lt;strong&gt;PageComment_single.ss&lt;/strong&gt; and then add that info to &lt;strong&gt;PageComment.ss&lt;/strong&gt; as well.&lt;/p&gt;</description>
			<pubDate>Wed, 28 Oct 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/overriding-silverstripes-language-files-with-your-own/</guid>
		</item>
		
		<item>
			<title>Extending $LinkingMode to handle controller actions</title>
			<link>http://www.ssbits.com/extending-linkingmode-to-handle-controller-actions/</link>
			<description>&lt;p&gt;As some of you might have noticed, as soon as you step outside of the standard SiteTree structure you're pretty much on your own. Today I had to make a menu that mixed normal SiteTree pages and controller actions.&lt;/p&gt;
&lt;p&gt;I wanted to be able to use &lt;strong&gt;LinkingMode&lt;/strong&gt; to check if this is the currently viewed page and unfortunately the standard function does not take controller actions into account.&lt;/p&gt;
&lt;h3&gt;The Snippet&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function LinkingMode($action = null) {
  $controllerAction = Director::urlParam('Action');
  if (is_null($controllerAction) &amp;amp;&amp;amp; is_null($action))
    return parent::LinkingMode();
  
  if ($action == $controllerAction)
    return 'current';
  else
    return $this-&amp;gt;LinkOrSection();
}&lt;/textarea&gt; &lt;/h3&gt;
&lt;h3&gt;What it does&lt;/h3&gt;
&lt;p&gt;First of all we give the &lt;strong&gt;LinkingMode&lt;/strong&gt; an optional parameter called &lt;strong&gt;$action&lt;/strong&gt; which is set to null by default. &lt;strong&gt;Director::urlParam('Action')&lt;/strong&gt; will return null if you are on the default or index action so if &lt;strong&gt;urlParam&lt;/strong&gt; is null and no action has been given we simply return the results from the original &lt;strong&gt;LinkingMode&lt;/strong&gt; function.&lt;/p&gt;
&lt;p&gt;However if an action is entered into the function it checks whether this action matches the urlParam. If it does it returns current, otherwise we return the results from the &lt;strong&gt;LinkOrSection&lt;/strong&gt; function. This means that the controller which the action resides in will get the class section if it's in the same menu as the action.&lt;/p&gt;
&lt;h3&gt;Use Case&lt;/h3&gt;
&lt;p&gt;Below is an example of how to use the snippet in your templates. The Link function accepts an optional action parameter which will return the appropriate url for a controller action. As you can see, the new &lt;strong&gt;LinkingMode&lt;/strong&gt; function works the same way. Note that if you're outputting a normal menu no parameter should be passed.&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;% control Menu(1) %&amp;gt;  
  &amp;lt;a href=&quot;$Link&quot; mce_href=&quot;$Link&quot; class=&quot;$LinkingMode&quot;&amp;gt;$MenuTitle&amp;lt;/a&amp;gt;
&amp;lt;% end_control %&amp;gt;
&amp;lt;a href=&quot;$Link(blog)&quot; mce_href=&quot;$Link(blog)&quot; class=&quot;$LinkingMode(blog)&quot;&amp;gt;Blog&amp;lt;/a&amp;gt;&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Put the new LinkingMode function in your base Page class and you are good to go.&lt;/p&gt;</description>
			<pubDate>Tue, 20 Oct 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/extending-linkingmode-to-handle-controller-actions/</guid>
		</item>
		
		<item>
			<title>Making a hierarchy aware templating system</title>
			<link>http://www.ssbits.com/making-a-hierarchy-aware-templating-system/</link>
			<description>&lt;p&gt;Something that has been bothering me when building larger sites with SilverStripe is that I often find myself creating new classes not to add functionality, but to just get a new template.&lt;/p&gt;
&lt;p&gt;You can set separate templates for different actions manually but that's not what I want in this case, I want different templates for the same action on the same class.&lt;/p&gt;
&lt;p&gt;After thinking about this for awhile I came up with a two part solution and the first part is to make the template choosing aware of the &lt;strong&gt;Sitetree&lt;/strong&gt; hierarchy.&lt;/p&gt;
&lt;p&gt;In order to get this to work I have sub classed &lt;strong&gt;ContentController&lt;/strong&gt; with a class I call &lt;strong&gt;HierarchyController&lt;/strong&gt;. This class only contains two methods, namely a &lt;strong&gt;__construct()&lt;/strong&gt; method to kick start the parent and a method called getViewer which overrides the &lt;strong&gt;getViewer&lt;/strong&gt; method of the &lt;strong&gt;Controller&lt;/strong&gt; class.&lt;/p&gt;
&lt;p&gt;The code in getViewer consists of the code from the parent method with my own code added at the end. The reason I copy the code from the parent is that I want to do the same processing it does first and then do my own. Since the parent method returns an &lt;strong&gt;SSViewer&lt;/strong&gt; object with the templates already set it's too late for me to step in and make the needed changes (I think).&lt;/p&gt;
&lt;h3&gt;The Snippet&lt;br /&gt;&lt;/h3&gt;
&lt;p&gt;So the added code is as follows:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;...
if ($this-&amp;gt;dataRecord) {
	$hierarchyTemplate = $templates[0];
	$current = $this-&amp;gt;dataRecord;
	while ($current-&amp;gt;ParentID &amp;gt; 0) {
		$hierarchyTemplate = $current-&amp;gt;ClassName.'_'.$hierarchyTemplate;
		array_unshift($templates, $hierarchyTemplate);
		$current = $current-&amp;gt;Parent();
	}
}&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;The code above gets added just after&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;$templates = array_unique($templates);&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;in the original &lt;strong&gt;getViewer&lt;/strong&gt; method.&lt;/p&gt;
&lt;h3&gt;The Results&lt;br /&gt;&lt;/h3&gt;
&lt;p&gt;So what does this code do? Essentially it grabs the parent classes (hierarchy wise) of the current page and adds them to the template list with the current class last in the chain.&lt;/p&gt;
&lt;p&gt;As an example, if you have a Page that is a sub page to another Page then the first template choice becomes &lt;strong&gt;Page_Page.ss&lt;/strong&gt;. If you have page that's a sub page of a sub page it becomes &lt;strong&gt;Page_Page_Page.ss&lt;/strong&gt; if all the pages are of the &lt;strong&gt;Page&lt;/strong&gt; class. It then falls back to &lt;strong&gt;Page_Page.ss&lt;/strong&gt; and after that &lt;strong&gt;Page.ss&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I want to hear from everyone here if you think this is a useful idea (I of course do :P). If anyone knows of a better way to implement this I would also really like to know. Also, what do you think about the fallback routine? Should it fall back to the base choice directly or walk it's way up the hierarchy like it's doing now?&lt;/p&gt;
&lt;p&gt;The next part (which I haven't tackled yet) will be adding the ability to choose a custom template for a page in the CMS. If someone has already done this then please post it as a snippet!&lt;/p&gt;
&lt;p&gt;Below is all the code for the &lt;strong&gt;HierarchyController&lt;/strong&gt;. In order to use it, copy the code and put it in a file called &lt;strong&gt;HierarchyController.php&lt;/strong&gt; in &lt;strong&gt;mysite/code&lt;/strong&gt;. After that make sure that your &lt;strong&gt;Page_Controller&lt;/strong&gt; extends &lt;strong&gt;HierarchyController&lt;/strong&gt; and you should be good to go!&lt;/p&gt;
&lt;h3&gt;All the Code&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class HierarchyController extends ContentController {
	
	public function __construct($dataRecord = null) {
		parent::__construct($dataRecord);
	}
		
	function getViewer($action) {
		// Hard-coded templates
		if($this-&amp;gt;templates[$action]) {
			$templates = $this-&amp;gt;templates[$action];
		}	else if($this-&amp;gt;templates['index']) {
			$templates = $this-&amp;gt;templates['index'];
		}	else if($this-&amp;gt;template) {
			$templates = $this-&amp;gt;template;
		} else {
			// Add action-specific templates for inheritance chain
			$parentClass = $this-&amp;gt;class;
			if($action &amp;amp;&amp;amp; $action != 'index') {
				$parentClass = $this-&amp;gt;class;
				while($parentClass != &quot;Controller&quot;) {
					$templates[] = strtok($parentClass,'_') . '_' . $action;
					$parentClass = get_parent_class($parentClass);
				}
			}
			// Add controller templates for inheritance chain
			$parentClass = $this-&amp;gt;class;
			while($parentClass != &quot;Controller&quot;) {
				$templates[] = strtok($parentClass,'_');
				$parentClass = get_parent_class($parentClass);
			}
			// remove duplicates
			$templates = array_unique($templates);
			if ($this-&amp;gt;dataRecord) {
				$hierarchyTemplate = $templates[0];
				$current = $this-&amp;gt;dataRecord;
				while ($current-&amp;gt;ParentID &amp;gt; 0) {
					$hierarchyTemplate = $current-&amp;gt;ClassName.'_'.$hierarchyTemplate;
					array_unshift($templates, $hierarchyTemplate);
					$current = $current-&amp;gt;Parent();
				}
			}
		}
		return new SSViewer($templates);			
	}	
}&lt;/textarea&gt; &lt;/h3&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Mon, 21 Sep 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/making-a-hierarchy-aware-templating-system/</guid>
		</item>
		
		<item>
			<title>Hide pages in Sitetree that a user can't edit</title>
			<link>http://www.ssbits.com/hide-pages-in-sitetree-that-a-user-can-t-edit/</link>
			<description>&lt;p&gt;Very short snippet here - sometimes you want to hide pages in the Sitetree that members logged into the CMS don't have permission to edit. This is really simple in because they already have a css style applied to them you can just hide that class. You need to include this snippet in your typography.css file so that it is included in the CMS.&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;ul.tree li.disabled { display: none; }&lt;/textarea&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;note. &lt;/strong&gt;this will also hide child pages even if they are accessible.&lt;/p&gt;</description>
			<pubDate>Tue, 15 Sep 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/hide-pages-in-sitetree-that-a-user-can-t-edit/</guid>
		</item>
		
		<item>
			<title>Using a Thickbox Modal Window with AJAX</title>
			<link>http://www.ssbits.com/using-a-thickbox-modal-window-with-ajax/</link>
			<description>&lt;p&gt;&lt;a href=&quot;http://jquery.com/demo/thickbox/&quot;&gt;Thickbox&lt;/a&gt; is a great javascript plugin to jQuery that you can use to create &lt;a href=&quot;http://www.smashingmagazine.com/2009/05/27/modal-windows-in-modern-web-design/&quot;&gt;modal windows&lt;/a&gt; within SilverStripe pages.&amp;nbsp; You can de-clutter your interfaces and re-use small snippets of common functions when you add in AJAX.&amp;nbsp; Before we begin there is a little homework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read the &lt;a href=&quot;http://doc.silverstripe.org/doku.php?id=recipes:ajax_basics&quot;&gt;AJAX Basics Recipe&lt;/a&gt; on the Doc Wiki&lt;/li&gt;
&lt;li&gt;Its a good idea to use some kind of naming convention with your methods and template so you don't get them confused.&amp;nbsp; I typically prepend them with lower case &lt;em&gt;ajax&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this example we will be creating a simple Clock that will be returning the time through a custom template in a Thickbox.&amp;nbsp; This is not very complex but it does illustrate the possibilities with modals and AJAX calls.&lt;/p&gt;
&lt;p&gt;We will start with a standard &lt;em&gt;Page&lt;/em&gt; type that has been created.&amp;nbsp; The Absolute URL to access our page is &lt;strong&gt;/my-page/&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Lets begin&lt;/h2&gt;
&lt;p&gt;First, lets create the template we will be using to populate our Thickbox window.&amp;nbsp; You will need to create this at the top level of your template directory, as we will be using &lt;strong&gt;renderWith()&lt;/strong&gt; to send the content to the browser.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;/mysite/templates/ajaxClock.ss&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;h1&amp;gt;Clock&amp;lt;/h1&amp;gt;
$Time
&amp;lt;a href=&quot;#&quot; false&quot;&amp;gt;Close This&amp;lt;/a&amp;gt;&lt;/textarea&gt;&lt;/p&gt;
&amp;nbsp;
&lt;p&gt;Notice the javascript onClick event, the function &lt;strong&gt;tb_remove()&lt;/strong&gt; is required to close the Thickbox window when using the optional &lt;strong&gt;modal=true&lt;/strong&gt; setting.&lt;/p&gt;
&lt;p&gt;Next, lets get our requirements squared away.&amp;nbsp; The best place to do this is in the &lt;strong&gt;init()&lt;/strong&gt; function of the &lt;strong&gt;Controller&lt;/strong&gt; you will be using Thickbox from.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;/mysite/code/model/Page.php (Page_Controller class):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;    public function init() {
        parent::init();
        Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery-packed.js');
        Requirements::javascript(THIRDPARTY_DIR . '/jquery/plugins/thickbox/thickbox-code/thickbox.js');
        Requirements::css(THIRDPARTY_DIR . '/jquery/plugins/thickbox/thickbox-code/thickbox.css');
    }&lt;/textarea&gt;&lt;/p&gt;
&amp;nbsp;
&lt;p&gt;And lets add the function to return the template and data in that same class:&lt;/p&gt;
&lt;p&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function ajaxTime() {
	if( Director::is_ajax() ) {
		$time = date();
		$return = array('Time' =&amp;gt; $time);
		return $this-&amp;gt;renderWith('ajaxClock',$return);
	}
}&lt;/textarea&gt;&lt;/p&gt;
&amp;nbsp;
&lt;p&gt;Now from our Page AJAX calls will have access to &lt;strong&gt;/my-page/ajaxTime&lt;/strong&gt; after we flush.&amp;nbsp;&amp;nbsp; You can use Firebug to check out what happens.&lt;/p&gt;
&lt;p&gt;The last step is to add the proper link to our regular Page template to invoke our Thickbox Clock.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;/mysite/templates/Page.ss:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;...
&amp;lt;!-- Somewhere, anywhere really --&amp;gt;
&amp;lt;a href=&quot;$URLSegment/ajaxTime?height=200&amp;amp;width=300&amp;amp;modal=true&quot; class=&quot;thickbox&quot;&amp;gt;What time is it?&amp;lt;/a&amp;gt;
...&lt;/textarea&gt;&lt;/p&gt;
&amp;nbsp;
&lt;p&gt;After flushing you should see these links included in your Pages.&amp;nbsp; Clicking on the link above will bring up a nice Thickbox with your content.&amp;nbsp; Merely adding the &lt;strong&gt;class=&quot;thickbox&quot;&lt;/strong&gt; will make everything work (thanks to the magic of the jQuery team and &lt;a href=&quot;http://codylindley.com/Javascript/257/thickbox-one-box-to-rule-them-all&quot;&gt;Cody Lindley&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;That's all!&lt;/h2&gt;
&lt;p&gt;Thickbox working smoothly within your SS pages with AJAX.&amp;nbsp; Go ahead and add all those nerdy frameworks and acronyms to your resume.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you want to use the Loading Bar animation that comes with Thickbox, you will have make the following change to the core jsparty library.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;/jsparty/jquery/plugins/thickbox/thickbox-code/thickbox.js:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;var tb_pathToImage = &quot;/jsparty/jquery/plugins/thickbox/images/loadingAnimation.gif&quot;;&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Fri, 11 Sep 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/using-a-thickbox-modal-window-with-ajax/</guid>
		</item>
		
		<item>
			<title>Spice up your CMS Sitetree!</title>
			<link>http://www.ssbits.com/spice-up-your-cms-sitetree-/</link>
			<description>&lt;p&gt;So you have created your own page types, but they all look the same in your CMS site tree. Time to make them more recognizable!&lt;br /&gt;This is quite easy, but it can make your site tree a lot more attractive.&lt;/p&gt;
&lt;p&gt;First &lt;a href=&quot;http://www.google.nl/search?q=free+icons&quot; target=&quot;_blank&quot;&gt;grab&lt;/a&gt; &lt;a href=&quot;http://www.google.nl/search?q=free+icon+pack&quot; target=&quot;_blank&quot;&gt;some&lt;/a&gt; icons, &lt;a href=&quot;http://www.istockphoto.com/file_search.php?text=icons&amp;amp;action=file&quot; target=&quot;_blank&quot;&gt;buy&lt;/a&gt; them or &lt;a href=&quot;http://www.google.nl/search?hl=nl&amp;amp;q=icon+creator&quot; target=&quot;_blank&quot;&gt;create&lt;/a&gt; you own custom aesthetic icon set. They only thing you have to keep in mind, is that your icons need to be saved as youriconname-file.gif.&lt;/p&gt;
&lt;p&gt;Next create a folder in &lt;strong&gt;mysite&lt;/strong&gt;, like &lt;strong&gt;/images/icons&lt;/strong&gt;, to store your icons.&lt;/p&gt;
&lt;p&gt;To assign a icon to your page class, add the a static &lt;strong&gt;$icon&lt;/strong&gt; var to your page class like:&lt;/p&gt;
&lt;p&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class MyCustomPage extends Page {

    static $icon = 'mysite/images/icons/mycustomicon';
}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;float: left; margin-left: 20px; margin-right: 20px;&quot; src=&quot;http://www.ssbits.com/assets/Uploads/spiceyoursitetree.png&quot; alt=&quot;&quot; /&gt;See that I don't add &lt;strong&gt;-file.gif&lt;/strong&gt; to it.&lt;/p&gt;
&lt;p&gt;Now go to your your CMS admin and see the result.&lt;/p&gt;
&lt;p&gt;I maybe overdone it a little bit, but on the left is how my sandbox tree looks.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Thu, 27 Aug 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/spice-up-your-cms-sitetree-/</guid>
		</item>
		
		<item>
			<title>How to access your admin account when you've forgotten the password</title>
			<link>http://www.ssbits.com/how-to-access-your-admin-account-when-you-ve-forgotten-the-password/</link>
			<description>&lt;p&gt;I managed to forget my admin password and found quite a few ways to unlock an SS install.&amp;nbsp; I originally thought about poking around the database and changing the hashes myself.&amp;nbsp; After reviewing the Security and password encryption code, I would recommend against doing that.&amp;nbsp; SilverStripe uses salted SHA1 encryption which is no fun to try and create yourself.&amp;nbsp; Also you'd have to update multiple tables to get the password changed.&lt;br /&gt;&lt;br /&gt;Luckily the SS Core team has included multiple features for accomplishing this.&amp;nbsp; The options below assume you have access to your webserver to use some PHP code.&lt;/p&gt;
&lt;h3&gt;Option 1 - Set a Default Admin Login&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;From:// http//doc.silverstripe.com/doku.php?id=security#system_configuration&quot;&gt;From: http://doc.silverstripe.com/doku.php?id=security#system_configuration&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Add the following to your &lt;strong&gt;_config.php&lt;/strong&gt;:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;Security::setDefaultAdmin('adminuser', 'password');&lt;/textarea&gt; &lt;/p&gt;
&lt;h3&gt;Option 2 - Use an Environment Configuration file&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;From:// http//doc.silverstripe.com/doku.php?id=environment-management&quot;&gt;From: http://doc.silverstripe.com/doku.php?id=environment-management&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At the top level of your site folder create the file &lt;strong&gt;_ss_environment.php&lt;/strong&gt; with the following code:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;?php
define('SS_DEFAULT_ADMIN_USERNAME', 'adminuser');
define('SS_DEFAULT_ADMIN_PASSWORD', 'password');
?&amp;gt;&lt;/textarea&gt; &lt;/p&gt;
&lt;h3&gt;Option 3 - Use a Member DataObject&lt;/h3&gt;
&lt;p&gt;In some page controller, config, or any interpreted php file:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;$m = DataObject::get_one('Member', &quot;Email = 'youradminaddress@email.com'&quot;);
$m-&amp;gt;changePassword('password');&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Note: You could also grab MemberID 1 if you also forgot your email address.&amp;nbsp; Member ID 1 &lt;em&gt;should&lt;/em&gt; be the admin in most cases.&lt;/p&gt;
&lt;h3&gt;That's it!&lt;/h3&gt;
&lt;p&gt;You should be able to get back in your admin account using any of the above examples.&amp;nbsp; Now be a little more careful with those passwords, eh?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Sat, 22 Aug 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/how-to-access-your-admin-account-when-you-ve-forgotten-the-password/</guid>
		</item>
		
		<item>
			<title>Create a front end theme switcher</title>
			<link>http://www.ssbits.com/create-a-front-end-theme-switcher/</link>
			<description>&lt;p&gt;So you wanna make a demo site for your customers to show all your template skills in one site. A simple theme switcher can come in handy. It's quite easy to implement this.&lt;/p&gt;
&lt;p&gt;First add two new functions to your &lt;strong&gt;Page_Controller&lt;/strong&gt; :&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;Page_Controller :
function themeSwitcher(){    
        $folders = scandir(Director::baseFolder().&quot;/themes&quot;);
        $exclude = array(&quot;.&quot;, &quot;..&quot;, &quot;.DS_Store&quot;, &quot;_notes&quot;);
        $themes = array_diff($folders, $exclude);
        $selected = Session::get('theme');
        
        $fields = new FieldSet(
          $fields =      new DropdownField('theme','theme', $themes, $selected, '', 'Select Theme')
      );
        $actions = new FieldSet(
          new FormAction('switchTheme', 'Switch')
      );
      return new Form($this, &quot;switchTheme&quot;, $fields, $actions); 
    }
    
    function switchTheme($data){        
        if($data['theme']){
            Session::set('theme', $data['theme']);    
        } else {
            unset($_SESSION['theme']);
        }
        Director::redirect(Director::baseURL(). $this-&amp;gt;URLSegment);
    }&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;The first function &lt;strong&gt;themeSwitcher() &lt;/strong&gt;will scan the themes folder for themes and create a dropdown menu with all templates. The exclude array and array_diff will exclude the dots and Apple DS_Store files and Dreamweaver _notes folders. You could use this array to add themes you want to exclude in the switch.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Session::get('theme')&lt;/strong&gt; will get the selected theme which will be set in the second function. The last part creates the dropdown field and form.&lt;/p&gt;
&lt;p&gt;The second function &lt;strong&gt;switchTheme($data) &lt;/strong&gt;will process the form and set the selected theme as session data, so the theme change will be remembered when you navigate through your site. I added an if/else to unset the theme session variable. This is done to prevent errors when &lt;em&gt;'Select Theme&lt;/em&gt;' is selected, which returns 0. The default theme that is set in your &lt;strong&gt;_config.php&lt;/strong&gt; will be used by default.&lt;/p&gt;
&lt;p&gt;The Director rule will bring you back to the page where you selected a new theme.&lt;/p&gt;
&lt;p&gt;The last bit of code will be placed in the function &lt;strong&gt;init()&lt;/strong&gt; of your Page_Controller before the Requirements rules.&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;$theme = Session::get('theme');
        if($theme){
            $folders = scandir(Director::baseFolder().&quot;/themes&quot;);
            $exclude = array(&quot;.&quot;, &quot;..&quot;, &quot;.DS_Store&quot;, &quot;_notes&quot;);
            $themes = array_diff($folders, $exclude);
            
            SSViewer::set_theme($themes[$theme]);
        }&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Since the dropdown field created by Silverstripe populate the option values with integers, we need to translate those integers with the actual theme name. That's why we scan the theme folder again.&lt;/p&gt;
&lt;p&gt;First we get the selected theme from the session variable, check if it is set to prevent errors and set the new theme with SSViewer.&amp;nbsp; Since the &lt;strong&gt;$themes&lt;/strong&gt; is an array we only need to pick the selected folder name with &lt;strong&gt;$themes[$theme]&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now you only need to place the form somewhere in your templates by using the variable &lt;strong&gt;$themeSwitcher&lt;/strong&gt; and you are able to change your themes with a simple form.&lt;/p&gt;
&lt;p&gt;Note: remember to add &lt;strong&gt;$themeSwitcher&lt;/strong&gt; in all your themes you have in your dropdown field.&lt;/p&gt;</description>
			<pubDate>Mon, 17 Aug 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/create-a-front-end-theme-switcher/</guid>
		</item>
		
		<item>
			<title>Clearing the Search field on click with jQuery</title>
			<link>http://www.ssbits.com/clearing-the-search-field-on-click-with-jquery/</link>
			<description>&lt;p&gt;As with everything, it's attention to detail that makes great sites.
One thing that really bugs me is when a site has a search box with the
word 'search' inside it but which does not clear it self when clicked,
meaning I have to clear it before I can search. Given it can be
achieved with a few lines of jQuery, it's a real surprise how many
sites fail to implement this, or that still use the 'onclick' inline
javascript. For an example of this in action, simply click the search
box to your right.&lt;/p&gt;
&lt;p&gt;To implement this on a SilverStripe site, create a file called &lt;strong&gt;jquery.clear.search.js&lt;/strong&gt; and place it in your &lt;strong&gt;mysite/javascript &lt;/strong&gt;directory. Then in your &lt;strong&gt;Page.php&lt;/strong&gt; &lt;strong&gt;innit() &lt;/strong&gt;function (in the controller class) add the following line:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;Requirements::javascript(&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;);
Requirements::javascript(&quot;mysite/javascript/jquery.clear.search.js&quot;);&lt;/textarea&gt;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;This will include our file in the page as well as the latest jQuery
compacted library, which is kindly hosted for us by google, meaning
there is a good change that the user may have it cached already. So now
lets actually add some jQuery to the file &lt;strong&gt;jquery.clear.search.js&lt;/strong&gt;:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;jQuery(document).ready(function() { 
	defaultValue = jQuery('#SearchForm_SearchForm_Search').val();	
	jQuery('#SearchForm_SearchForm_Search').click(function() { 
		if( this.value == defaultValue ) { 
			jQuery(this).val(&quot;&quot;);
		} 
	}); 
});&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;If you are new to jQuery this may look a little daunting, but once
you get familiar it really is very simple. The first line just tells
jQuery to wait until the document is loaded before running the script.
The next line gets the value of the search field when the page loads. Then we apply a
function to the field it each time it is clicked. This function checks to see if
the value of the field matches the default
value and if it does, it clears it.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That's it! You now have a self clearing search box which picks up
the value to clear dynamically, so should also work fine with
multilingual sites.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note.&lt;/strong&gt; We use the full jQuery call instead of the abbreviated
$ to avoid conflicts with prototype. You could instead wrap your code
in &lt;strong&gt;(function($) {&lt;/strong&gt; [code here] &lt;strong&gt;}(jQuery);&lt;/strong&gt; which would allow you to use the $ variable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special thanks to &lt;/strong&gt;&lt;strong&gt;Lerni for suggesting the post and providing the jQuery code.&lt;/strong&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 05 Aug 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/clearing-the-search-field-on-click-with-jquery/</guid>
		</item>
		
		<item>
			<title>Autofill MetaDescription and MetaKeywords on page save</title>
			<link>http://www.ssbits.com/autofill-metadescription-and-metakeywords-on-page-save/</link>
			<description>&lt;p&gt;Most of my customers don't want to add meta info manually, so I
add an &lt;strong&gt;onBeforeWrite()&lt;/strong&gt; function to update the Meta Description field and
count the keyword density of the content with a separate function and
add these keywords to the Meta Keywords fields when a page is saved.&lt;/p&gt;
&lt;p&gt;In my humble SEO opinion every page needs an unique Meta
Description. Keywords seems to be less important for search engines,
but why not add them automatically anyway! The function counts how many
times each word exist in the Content, order the words by occurrence and
glues the words to a comma separated string. In this function only
words with more then 4 characters are counted, but you can adjust that
if you like.&lt;/p&gt;
&lt;p&gt;To do this, add an &lt;strong&gt;onBeforeWrite() &lt;/strong&gt;function in your Page class (&lt;strong&gt;mysite/Page.php&lt;/strong&gt;).&lt;br /&gt;This will fill in the Meta Description with the Content (The Meta Description Field is limited to 255 characters).&lt;/p&gt;
&lt;p&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function onBeforeWrite () {
        parent::onBeforeWrite ();
        if($this-&amp;gt;ID){
            // fill in MetaDescription without any tags
            if($this-&amp;gt;record['Content']){
                $this-&amp;gt;record['MetaDescription'] = strip_tags($this-&amp;gt;record['Content']);
            }
            // fill in MetaKeywords
            if($this-&amp;gt;record['Content']){
                $this-&amp;gt;record['MetaKeywords'] = self::calculateKeywords($this-&amp;gt;record['Content'], 4, 15);
            }
        }
    }&lt;/textarea&gt;&lt;/p&gt;
&amp;nbsp;
&lt;p&gt;For the keywords we need two extra functions to calculate the keyword density (borrowed from  &lt;a href=&quot;http://www.bitrepository.com/word-popularity-script.html&quot; target=&quot;_blank&quot;&gt;Gabriel Comarita&lt;/a&gt;):&lt;br /&gt;Add the following functions to your Page class (&lt;strong&gt;mysite/Page.php&lt;/strong&gt;)&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;/**
     * Extract Keywords
     * Returns a lowercase string with keywords ordered by occurance in content seperated with comma's
     * @var $string
     * @var $min_word_char
     * @var $keyword_amount
     * @var $exclude_words
     */
    private function calculateKeywords($string = '', $min_word_char = 4, $keyword_amount = 15,  $exclude_words = '' ) {
        
        $keystring = '';
        $exclude_words = explode(&quot;, &quot;, $exclude_words);
        // get rid off the htmltags
        $string = strip_tags($string);
        
        // count all words
        $initial_words_array  =  str_word_count($string, 1);
        $total_words = sizeof($initial_words_array);
        
        $new_string = $string;
        
        // strip excluded words
        foreach($exclude_words as $filter_word)    {
            $new_string = preg_replace(&quot;/\b&quot;.$filter_word.&quot;\b/i&quot;, &quot;&quot;, $new_string); 
        }
        
        // calculate words again without the excluded words
        $words_array = str_word_count($new_string, 1);
        $words_array = array_filter($words_array, create_function('$var', 'return (strlen($var) &amp;gt;= '.$min_word_char.');'));
        
        $popularity = array();
        $unique_words_array = array_unique($words_array);
        
        // create density array
        foreach($unique_words_array as  $key =&amp;gt; $word)    {
            preg_match_all('/\b'.$word.'\b/i', $string, $out);
            $count = count($out[0]);    
            $popularity[$key]['count'] = $count;
            $popularity[$key]['word'] = $word;
            
        }
        
        usort($popularity, array($this,'cmp'));
        
        // sort array form higher to lower
        krsort($popularity);
        
        // create keyword array with only words
        $keywords = array();
        foreach($popularity as $value){
                        $keywords[] = $value['word']; 
                    }
                    
        // glue keywords to string seperated by comma, maximum 15 words
        $keystring =  strtolower(implode(', ', array_slice($keywords, 0, $keyword_amount)));
        
        // return the keywords
        return $keystring;
    }
    
    /**
     * Sort array by count value
     */
    private static function cmp($a, $b) {
        return ($a['count'] &amp;gt; $b['count']) ? +1 : -1;
    }&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Now every time a Page (or an extended page type like the Blog Page) is saved, it updates the Meta Description or Meta Keywords fields.&lt;/p&gt;
&lt;p&gt;Since the CMS forms are posted with Ajax, you need to refresh the page to see the results immediately. You can automate this by adding a &lt;strong&gt;onAfterWrite &lt;/strong&gt;function to you Page class:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function onAfterWrite(){
        parent::onAfterWrite ();
        LeftAndMain::ForceReload ();
  }&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;You could extend this by adding a check-box field, so you can choose if you want to update the meta fields or not each time you save a page.&lt;/p&gt;
&lt;p&gt;With this idea I made a separate Decorator extension with its own _config.php file for the configuration options.&lt;/p&gt;
&lt;p&gt;The code to update the meta fields is slightly different then this tutorial and I added some options to suppress the confirm dialog each time you change the page title and to hide some of the meta fields. Put the files in the Metamanager package to you siteroot so you get siteroot/metamanager/ . Change the settings in the config file to suit you needs and voila Automated meta info!&lt;/p&gt;</description>
			<pubDate>Tue, 28 Jul 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/autofill-metadescription-and-metakeywords-on-page-save/</guid>
		</item>
		
		<item>
			<title>Customising the WYSYWIG editor in v2.3.2 (TinyMCE)</title>
			<link>http://www.ssbits.com/customising-the-wysywig-editor-in-v2-3-2-tinymce/</link>
			<description>&lt;p&gt;The&amp;nbsp; default install of SilverStripe contains an array of buttons
for the TinyMCE HTML editor. However usually your client will need some
extra functionality or you may want to keep things simple for them by
removing some of the buttons. As of SilverStripe &lt;strong&gt;2.3.2&lt;/strong&gt; this is very easy and can be achieved by adding some code to the &lt;strong&gt;_config.php&lt;/strong&gt; file.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note.&lt;/strong&gt; if you are using a version &amp;lt;2.3.2 you must edit the file cms/javascript/tinymce.template.js.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To find out all the wonderful buttons that are available by default in the TinyMCE 3 install visit the &lt;a href=&quot;http://tinymce.moxiecode.com/examples/full.php&quot; target=&quot;_blank&quot;&gt;example page here&lt;/a&gt; and click the 'view source tab'. There are also tons of plugins available to do all sorts of things. &lt;/p&gt;
&lt;h2&gt;Adding Buttons&lt;br /&gt;
&lt;/h2&gt;
&lt;p&gt;So
lets say for example you wanted to add font color settings to the
editor. All you need to do is add this line to your class or
_config.php file:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;toolbar:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;HtmlEditorConfig::get('cms')-&amp;gt;insertButtonsAfter('formatselect', 'forecolor');&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;So this line will insert the font color button after the format
select dropdown in the toolbar. Because font color ships with TinyMCe
that's all there is to it! There are literally dozens of extra buttons
you can add to your editor in this way, just check out the link above
to see all the buttons that ship with TinyMCE.&lt;/p&gt;
&lt;p&gt;Here are all the functions for adding buttons:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;insertButtonsAfter('ButtonA', 'ButtonB', 'ButtonC', 'ButtonD')&lt;/strong&gt; - This will insert buttons B, C and D &lt;strong&gt;after&lt;/strong&gt; button A.&lt;br /&gt;&lt;strong&gt;insertButtonsBefore('ButtonA', 'ButtonB', 'ButtonC', 'ButtonD')&lt;/strong&gt; - This will insert buttons 2, 3 and 4 &lt;em&gt;before&lt;/em&gt; button A.&lt;br /&gt;
&lt;strong&gt;addButtonsToLine(1, 'ButtonA', 'ButtonB') &lt;/strong&gt;- This will add buttons A and B to the&lt;em&gt; end &lt;/em&gt;of line 1.&lt;br /&gt;
&lt;strong&gt;setButtonsForLine( 1, 'ButtonA', 'ButtonB', 'ButtonC') &lt;/strong&gt;- This will set the entire row of buttons to ButtonsA, B and C.&lt;/p&gt;
&lt;h2&gt;Removing Buttons&lt;/h2&gt;
&lt;p&gt;When you want to remove buttons is just as simple as adding them:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;toolbar:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;HtmlEditorConfig::get('cms')-&amp;gt;removeButtons('tablecontrols');&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;This will remove the table controlls buttons which are grouped together in the tinyMCE code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;removeButtons('ButtonA', 'ButtonB') - &lt;/strong&gt;this will remove buttons A and B from the editor.&lt;/p&gt;
&lt;h2&gt;Adding / Removing Plugins&lt;/h2&gt;
&lt;p&gt;If you can't find what your looking for in the inbuilt TinyMCE
controls then you may well be able to find it by using a plugin (or
even write your own). To add a particular plugin add this line of code:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;toolbar:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;HtmlEditorConfig::get('cms')-&amp;gt;enablePlugins('blockquote');&lt;/textarea&gt; &lt;br /&gt;This
will enable the blockquote plugin, but remember you will need to add
the appropriate button separately using one of the methods described
above.&lt;/p&gt;
&lt;p&gt;You can also disable plugins using, you guessed it, &lt;strong&gt;disablePlugins() &lt;/strong&gt;which as with enablePlugins requires you to remove the button separately.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;enablePlugins('PluginA', '../../customPlugins/pluginB') &lt;/strong&gt;- this will enable the plugins A and B.&lt;br /&gt;
&lt;strong&gt;disablePlugins('PluginA', '../../customPlugins/pluginB') &lt;/strong&gt;- this will disable the plugins A and B.&lt;/p&gt;
&lt;h2&gt;Setting Options&lt;/h2&gt;
&lt;p&gt;You can also set the TinyMCE options in the same way, so say I wanted to enable the&lt;strong&gt; auto_resize&lt;/strong&gt; option I would add this code:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;toolbar:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;HtmlEditorConfig::get('cms')-&amp;gt;setOption('auto_resize', 'true');&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;You can also set a group of options at once using the setOptions() call.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;setOptions(array('Option1' =&amp;gt; 'Value1', 'Option2' =&amp;gt; 'Value2')) &lt;/strong&gt;- sets an array of options.&lt;br /&gt;
&lt;strong&gt;setOptions('Option', 'Value')&lt;/strong&gt; - sets an option.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Note.&lt;/h3&gt;
&lt;h3&gt;It appears that the settings inside LeftAndMain.php are included after those in _config.php. For this reason if you are trying to change a setting that is set in LeftAndMain.php, you must do it in the getCMSFields() function in your Page.php file. &lt;/h3&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Special thanks to &lt;strong&gt;Martijn van Nieuwenhoven&lt;/strong&gt; for some suggestions regarding this post.&lt;/p&gt;</description>
			<pubDate>Fri, 24 Jul 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/customising-the-wysywig-editor-in-v2-3-2-tinymce/</guid>
		</item>
		
		<item>
			<title>Manipulating every Nth item in a &lt;% control %&gt; loop</title>
			<link>http://www.ssbits.com/manipulating-every-nth-item-in-a-control-loop/</link>
			<description>&lt;p&gt;Often you will want to manipulate every &lt;strong&gt;n&lt;/strong&gt;th item inside a &lt;strong&gt;&amp;lt;% control %&amp;gt;&lt;/strong&gt;
loop. For example say you had a gallery and you wanted every 3rd image
to start on a new line, you need to be able to test each item from the
template to see if it is divisible by 3 and should therefore have the &lt;strong&gt;clear&lt;/strong&gt; CSS class added to it.&lt;/p&gt;
&lt;p&gt;Using &lt;strong&gt;iteratorPos % &lt;/strong&gt;we
can very easily achieve this. First we need to add the test function to
the object we will be iterating through, so for example if you are
iterating through a number of ImageItem DataObjects, we would add this
function to our &lt;strong&gt;ImageItem&lt;/strong&gt; class:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;	public function IsThird(){	
		return ($this-&amp;gt;iteratorPos % 3) == 0;
	}&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;%&lt;/strong&gt; operator calculates the &lt;em&gt;modulous&lt;/em&gt;
or Remainder after dividing by the number that follows it (in this case
3). If there is a remainder then we know that the item is not divisible
by 3 and so should not be cleared, but if the modulous is equal to 0 then we know it is divisible by 3 and should therefore clear a new line.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
We can now use &amp;lt;% if IsThird %&amp;gt; to clear the third image in our control loop like so:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;% control ImageItems %&amp;gt; 
     &amp;lt;li &amp;lt;% if IsThird %&amp;gt;class=&quot;clear&quot;&amp;lt;% end_if %&amp;gt; &amp;gt;  
          Image
     &amp;lt;/li&amp;gt;
&amp;lt;% end_control %&amp;gt;&amp;lt;br&amp;gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;h2&gt; 
&lt;/h2&gt;</description>
			<pubDate>Thu, 16 Jul 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/manipulating-every-nth-item-in-a-control-loop/</guid>
		</item>
		
		<item>
			<title>Working with banners</title>
			<link>http://www.ssbits.com/working-with-banners/</link>
			<description>&lt;p&gt;Most of the sites I work on are for corporate/business clients and
there is not typically a lot of fancy motion graphics going
on. I do like to ensure there is some dynamic element going on,
just to provide a bit of interest and one of the simplest ways to
achieve this is by some variation of the random/rotating banners scenario.
Of course this could equally apply to other parts of the page, not just
banner graphics.&lt;/p&gt;
&lt;p&gt;Over the course of a few projects, trawling the SS forums and
hacking together my own interpretations, I have ended up with a few
different ways of doing this in SilverStripe.&lt;/p&gt;
&lt;h2&gt;A random rotating banner&lt;br /&gt;&lt;/h2&gt;
&lt;p&gt;This function gets a set of random banners from a specified folder - in this case &lt;strong&gt;BannerImages&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;function
RandomBanners(){ return DataObject::get('Image', 'ClassName &amp;lt;&amp;gt;
&quot;Folder&quot; AND ParentID = (SELECT ID FROM File WHERE ClassName = &quot;Folder&quot;
AND Name = &quot;BannerImages&quot;)','RAND()','','5'); }&amp;nbsp;&lt;/textarea&gt; &lt;br /&gt; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the template I then cycle through each of the images in the
folder marking up the HTML as required by the the excellent jQuery
cycle plugin (&lt;a href=&quot;http://malsup.com/jquery/cycle/&quot;&gt;http://malsup.com/jquery/cycle/&lt;/a&gt;) which is what I use for the cycling of frames.&lt;br /&gt;&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;div id=&quot;banner&quot; &amp;gt;
	&amp;lt;div style=&quot;display:none&quot; id=&quot;bannerimgs&quot;&amp;gt; 		
		&amp;lt;% control RandomBanners %&amp;gt; 
			&amp;lt;img src=&quot;$URL&quot; alt=&quot;&quot; width=&quot;930&quot; height=&quot;200&quot;/ &amp;gt; 
		&amp;lt;% end_control %&amp;gt; 
	&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/textarea&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Note that I hide the banner images until jQuery loads, to get around
having all the images display at once right at the start. I then
initialise the jQuery Cycle plugin mentioned above inside the &lt;strong&gt;innit() &lt;/strong&gt;function of the &lt;strong&gt;Page_Controller&lt;/strong&gt;:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;Requirements::customScript(&quot;
	jQuery(document).ready(function(){ 
		jQuery('#bannerimgs').cycle({ delay: 5000, speed: 2000 }); 
		jQuery('#bannerimgs').show(); 
	});&quot;
);&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;You should now have a lovely rotating banner using random images from a folder.&lt;/p&gt;
&lt;h2&gt;A single random Banner&lt;/h2&gt;
&lt;p&gt;You may also want to only have a single banner without the jQuery
rotation but still randomly picked. To achieve this forst create a new
function to just grab a single image:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;function
OneRandomBanner(){ return DataObject::get('Image', 'ClassName &amp;lt;&amp;gt;
&quot;Folder&quot; AND ParentID = (SELECT ID FROM File WHERE ClassName = &quot;Folder&quot;
AND Name = &quot;BannerImages&quot;)','RAND()','','1'); }&lt;/textarea&gt;&lt;/p&gt;
&amp;nbsp;
&lt;p&gt;Then in the template add the image as a background to the div (note. this will not validate as XHTML):&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;div
id=&quot;banner&quot; style=&quot;background-image:url(http://www.ssbits.com/&amp;lt;% control OneRandomBanner
%&amp;gt;&amp;lt;% end_control %&amp;gt;);&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;h2&gt;Variations on Image Getter functions&lt;br /&gt;&lt;/h2&gt;
&lt;p&gt;Here are a couple of slightly different way of retrieving the folder.&lt;/p&gt;
&lt;p&gt;This function grabs a single image based on it's parent folder's ID:&lt;/p&gt;
&lt;p&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function RandomImage(){ 
	return DataObject::get_one(&quot;Image&quot;,&quot;ParentID = 94&quot;,false, &quot;RAND()&quot;); 
} &lt;/textarea&gt;&lt;br /&gt;While this function uses the folders name:&lt;br /&gt;&amp;nbsp;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function getHomePageImages(){ 
	$img_dir = DataObject::get_one(&quot;Folder&quot;, &quot;Name = 'HomepageSlide'&quot;); 
	$randImg = ( $img_dir-&amp;gt;ID ) ? DataObject::get(&quot;Image&quot;, &quot;ParentID = $img_dir-&amp;gt;ID&quot;,&quot;RAND()&quot;,null,8 ) : false; 
	return $randImg; 
} &lt;/textarea&gt; &lt;br /&gt;or more usefully you can pass in the folder name:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;function getRandomImage($imgdir){ 
	$img_dir = DataObject::get_one(&quot;Folder&quot;, &quot;Name = \&quot;$imgdir\&quot;&quot;); 
	$randImg = ( $img_dir-&amp;gt;ID ) ? DataObject::get_one(&quot;Image&quot;, &quot;ParentID = $img_dir-&amp;gt;ID&quot;, true, &quot;RAND()&quot; ) : false; 
	return $randImg; 
}&amp;nbsp;&lt;/textarea&gt;&lt;/p&gt;
&lt;h2&gt;Getting the banner from the top level parent&lt;/h2&gt;
&lt;p&gt;Often
you may want to only set the banner for the top level 'section' page
and have it passed down to all it's children. The simlest way to do
this is by using the level(1) function on the current page and then
calling the appropriate function on the top level page like so:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function GetTopBannerImage(){
	return $this-&amp;gt;Level(1)-&amp;gt;BannerImage();
}&lt;/textarea&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 13 Jul 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/working-with-banners/</guid>
		</item>
		
		<item>
			<title>Removing an Item From the Main CMS Menu</title>
			<link>http://www.ssbits.com/removing-an-item-from-the-main-cms-menu/</link>
			<description>&lt;p&gt;If you want to remove an item from the CMSTopMenu without making it inaccessible you can add this line to your _config.php:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;CMSMenu::remove_menu_item('SecurityAdmin');&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;This example will remove the &lt;strong&gt;Security&lt;/strong&gt; link. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note.&lt;/strong&gt; You would still be able to access the Securtiy section by going to &lt;strong&gt;admin/security&lt;/strong&gt;, it just won't show in the menu.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Fri, 03 Jul 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/removing-an-item-from-the-main-cms-menu/</guid>
		</item>
		
		<item>
			<title>Creating Previous and Next Buttons on a page</title>
			<link>http://www.ssbits.com/creating-previous-and-next-buttons-on-a-page/</link>
			<description>&lt;p&gt;When you have a number of pages which follow on from one another you
may find that asking a user to return to an index or select the next
item from a side menu each time they want to progress is cumbersome. In
this situation having previous and next buttons at the bottom of a page
becomes very useful. In this snippet we'll add these buttons and also a
counter to show the current page we are on and the total number of
pages.&lt;/p&gt;
&lt;p&gt;First add this function to your Page_Controller class:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;    public function PrevNextPage($Mode = 'next') {
	  
	  if($Mode == 'next'){
	  	$Where = &quot;ParentID = ($this-&amp;gt;ParentID) AND Sort &amp;gt; ($this-&amp;gt;Sort)&quot;;
		$Sort = &quot;Sort ASC&quot;;
	  }
	  elseif($Mode == 'prev'){
	  	$Where = &quot;ParentID = ($this-&amp;gt;ParentID) AND Sort &amp;lt; ($this-&amp;gt;Sort)&quot;;
		$Sort = &quot;Sort DESC&quot;;
	  }
	  else{
	  	return false;
	  }
	  
	  return DataObject::get(&quot;SiteTree&quot;, $Where, $Sort, null, 1);
	  	
    }&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Let's go through the function. First we pass in a string $Mode. This
will be used to decide whether to return the previous or next page. &lt;/p&gt;
&lt;p&gt;Then if we have passed in 'next' (the default) we setup the database
criteria for that page, which is having the same parent ID and a sort
value that is higher than the current page. We also set the database
sort to arrange the pages by their &lt;strong&gt;Sort&lt;/strong&gt; value in &lt;strong&gt;Ascending&lt;/strong&gt;
order. Otherwise if $Mode is 'prev' then we setup the criteria to fetch
the previous page. If $Mode was not equal to either 'next' or 'prev'
then we just return false.&lt;/p&gt;
&lt;p&gt;Finally we do the database call and grab a single page using the
criteria we set in the first part of the function and return the result.&lt;/p&gt;
&lt;p&gt;Now we can use this function in our template like so:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;% control PrevNextPage(prev) %&amp;gt;
	  &amp;lt;a href=&quot;$Link&quot; mce_href=&quot;$Link&quot; title=&quot;Go to $Title&quot;&amp;gt;&amp;lt;&amp;lt; previous page&amp;lt;/a&amp;gt;	
&amp;lt;% end_control %&amp;gt;
&amp;lt;% control PrevNextPage(next) %&amp;gt;				
	  &amp;lt;a href=&quot;$Link&quot; mce_href=&quot;$Link&quot; title=&quot;Go to $Title&quot;&amp;gt;next page &amp;gt;&amp;gt; &amp;lt;/a&amp;gt;
&amp;lt;% end_control %&amp;gt;&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;By wrapping the links in &lt;strong&gt;&amp;lt;% control %&amp;gt;&lt;/strong&gt; blocks instead of using &lt;strong&gt;$Variables&lt;/strong&gt;, we prevent the link from being drawn if there is no page to go to.&lt;/p&gt;
&lt;p&gt;Finally
we can also add these functions to our Page_Controller to enable us to
print the current page's number and the total number of pages:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function NumberOfSiblings(){
	return DataObject::get(&quot;SiteTree&quot;,&quot;ParentID = ($this-&amp;gt;ParentID)&quot;)-&amp;gt;Count();
}
public function CurrentPageNumber(){
	return (DataObject::get(&quot;SiteTree&quot;,&quot;ParentID = ($this-&amp;gt;ParentID) AND Sort &amp;lt;= ($this-&amp;gt;Sort)&quot;)-&amp;gt;Count());
}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;And then in our template:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;p&amp;gt;Page $CurrentPage of $NoOfSiblings&amp;lt;/p&amp;gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Thanks to &lt;strong&gt;Rick &lt;/strong&gt;for suggesting this snippet!&lt;/p&gt;</description>
			<pubDate>Sun, 28 Jun 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/creating-previous-and-next-buttons-on-a-page/</guid>
		</item>
		
		<item>
			<title>Using canCreate(), canEdit(), canDelete() and canPublish() to manage page type permissions</title>
			<link>http://www.ssbits.com/using-cancreate-canedit-candelete-and-canpublish-to-manage-page-type-permissions/</link>
			<description>&lt;p&gt;Often you will want to control which users can create, edit, delete
and publish certain page types. For example you may only want high level users to be able to create ContactPage page types, or prevent low level users from deleting HomePage page types. This can easily be achieved by adding these
functions to the page type model (usually just before &lt;strong&gt;getCMSFields()&lt;/strong&gt;). Then within the function you can define conditionals which decide whether to return true or false.&lt;/p&gt;
&lt;p&gt;So let's say you have created the permission code in &lt;a href=&quot;http://www.ssbits.com/create-a-permission-code/&quot;&gt;this snippet&lt;/a&gt;. We can now use that permission code and the &lt;strong&gt;canCreate()&lt;/strong&gt; function to decide whether a particular user can create this page type:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;	function canCreate(){
		if(permission::check('SUPERUSER')){
			return true;
		}else{
			return false;
		}
	}&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;This
function uses the permission::check() function to check whether the
current user is in a group which has a particular permission code assigned to it.&lt;/p&gt;
&lt;p&gt;Alternatively you could check the ID of the group the user is in by using &lt;strong&gt;Member::currentUser()-&amp;gt;inGroup($GroupID) &lt;/strong&gt;in the &lt;strong&gt;if() &lt;/strong&gt;statement.&lt;/p&gt;
&lt;p&gt;This code goes for each of these functions: &lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;canEdit()&lt;/strong&gt; - If false returned removes editing ability from a particular page type&lt;strong&gt;&lt;br /&gt;canDelete() &lt;/strong&gt;-&lt;strong&gt; &lt;/strong&gt;If false returned removes the delete buttons from the page.&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt; &lt;strong&gt;canCreate()&lt;/strong&gt; - If false returned removes from the page type dropdown.&lt;br /&gt;&lt;strong&gt;canPublish()&lt;/strong&gt; - If false returned removes the publish button from the page. &lt;/p&gt;
&lt;p&gt;Combining these functions gives you a powerful way to control your site permissions and when used alongside the CMS access permissions you have complete control over your sites security structure.&lt;/p&gt;</description>
			<pubDate>Tue, 23 Jun 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/using-cancreate-canedit-candelete-and-canpublish-to-manage-page-type-permissions/</guid>
		</item>
		
		<item>
			<title>Change the CMS "Help" Link</title>
			<link>http://www.ssbits.com/change-the-cms-help-link/</link>
			<description>&lt;p&gt;Usually you can change the CMS menu settings from your site
configuration, but the &quot;Help&quot; link is hard-coded to allow for
translations. This snippet, placed in your site configuration file will
override the &quot;Help&quot; link with a link back to your site:&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;CMSMenu::add_link('Help', 'Home', Director::baseUrl());&lt;/textarea&gt;&lt;/p&gt;</description>
			<pubDate>Wed, 10 Jun 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/change-the-cms-help-link/</guid>
		</item>
		
		<item>
			<title>Displaying Fields From a Set of Pages on Another Page</title>
			<link>http://www.ssbits.com/displaying-fields-from-a-set-of-pages-on-another-page/</link>
			<description>&lt;p&gt;Although ultimately requiring very little code, displaying data from
a set of pages on another page
can seem confusing for those new to SilverStripe. This example will
display all of the Images from all the staff pages on our current page.
This works by first returning all the staff pages to our template and
cycling through each of them, drawing the Image for each one.&lt;/p&gt;
&lt;p&gt;Add the following function to your current pages Controller:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;public function GetStaffPages(){
	return DataObject::get(&quot;StaffPage&quot;);
}&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Then inside your template you can simply cycle through the results using &amp;lt;% control GetStaffPages %&amp;gt; like so:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;% control GetStaffPages %&amp;gt;
	&amp;lt;img src=&quot;$Image.URL&quot; mce_src=&quot;$Image.URL&quot; alt=&quot;A pic of $Name&quot; /&amp;gt;
&amp;lt;% end_control %&amp;gt;&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Of course this can be taken a lot further, creating filters or sorts in the DataObject::get() call or adding conditions in the template.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;strong&gt;Moreno&lt;/strong&gt; for suggesting this snippet.&lt;/em&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 25 May 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/displaying-fields-from-a-set-of-pages-on-another-page/</guid>
		</item>
		
		<item>
			<title>Adding a Thumbnail to a DataObjectManager or Complex Table Field</title>
			<link>http://www.ssbits.com/adding-a-thumbnail-to-a-dataobjectmanager-or-complex-table-field/</link>
			<description>&lt;p&gt;This snippet lets you add a thumbnail to items in UncleCheese's Data Object Manager module or a regular Complex Table field. All you need to do is create a function that returns a thumbnail and refer to this function in your DOM or CTF definition.&lt;/p&gt;
&lt;p&gt;So add a function like this to your DataObject class:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;	function Thumbnail() {
		$Image = $this-&amp;gt;Image();
		if ( $Image ) {
			return $Image-&amp;gt;CMSThumbnail();
		} else {
			return null;
		}
	}&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Notice the use of &lt;strong&gt;CMSThumbnail() &lt;/strong&gt;SilverStripe has already done the hard work of creating the thumbnail so all you need to do is call this function on your image!&lt;/p&gt;
&lt;p&gt;Then when you define your DOM or CTF just use the function name as your key for the field you would like to display the thumbnail in&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;		$manager = new DataObjectManager(
			$this, 
			'DataObjects',
			'DataObject',
			array(
				'Thumbnail' =&amp;gt; 'Image',
				'Name' =&amp;gt; 'Name'
			),
			'getCMSFields_forPopup'
		);&lt;/textarea&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 21 May 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/adding-a-thumbnail-to-a-dataobjectmanager-or-complex-table-field/</guid>
		</item>
		
		<item>
			<title>Using @import in your _config.php for Live site Database Details</title>
			<link>http://www.ssbits.com/using-import-in-your-config-php-for-live-site-database-details/</link>
			<description>&lt;p&gt;Have you ever mistakenly overwritten your live site &lt;strong&gt;_config.php&lt;/strong&gt; with your local one? Even if you haven't it can be a pain to keep copying new lines from your local config file to the live one. This little trick means you won't ever have to worry about it again! &lt;/p&gt;
&lt;p&gt;First create a file on your live server with the relevant Database info:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mysite/_liveConfig.php&lt;br /&gt;&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;global $databaseConfig;
$databaseConfig = array(
	&quot;type&quot; =&amp;gt; &quot;MySQLDatabase&quot;,
	&quot;server&quot; =&amp;gt; &quot;localhost&quot;, 
	&quot;username&quot; =&amp;gt; &quot;LiveUsername&quot;, 
	&quot;password&quot; =&amp;gt; &quot;LivePassword&quot;, 
	&quot;database&quot; =&amp;gt; &quot;SS_site&quot;,
);
Debug::send_errors_to(&quot;you@yoursite.com&quot;);&lt;/textarea&gt; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;then simply add this line to the bottom of your regular _config.php file:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mysite/_config.php&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;@include '_liveConfig.php';&lt;/textarea&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The @ infront of the include allows it to fail silently when the file does not exist (i.e. on your local server). You can now upload your _config.php file as much as you like without interfering with the live database settings!&lt;/p&gt;</description>
			<pubDate>Thu, 14 May 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/using-import-in-your-config-php-for-live-site-database-details/</guid>
		</item>
		
		<item>
			<title>Creating a Page Export Function</title>
			<link>http://www.ssbits.com/creating-a-page-export-function/</link>
			<description>&lt;p&gt;Need to create an 'export' function for a page? Do it quickly and cleanly with &lt;strong&gt;HTTP::sendFileToBrowser&lt;/strong&gt;. In your page controller, add a new action 'export':&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;function export() {
	$filename = &quot;Page Export.html&quot;;
	$data = $this-&amp;gt;renderWith(array('Page_Export'));
	HTTP::sendFileToBrowser($data, $filename);
}&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Now you just need to create &lt;strong&gt;Page_Export.ss&lt;/strong&gt;, and direct the user to the URL &quot;/export/&quot;. Your page will be returned to the browser as an attachment to download.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Wed, 06 May 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/creating-a-page-export-function/</guid>
		</item>
		
		<item>
			<title> Dynamically Generating a Dropdown List</title>
			<link>http://www.ssbits.com/dynamically-generating-a-dropdown-list/</link>
			<description>&lt;p&gt;If you want to create a drop down list (or option set) dynamically, for example from a set of pages or DataObjects, you can use the &lt;strong&gt;DataObject::get() &lt;/strong&gt;call along with the function &lt;strong&gt;toDropdownMap()&lt;/strong&gt; to generate it like so:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;new DropdownField(
	'DataObjectID',
	'Please choose an object',
	Dataobject::get(&quot;DataObject&quot;)-&amp;gt;toDropdownMap(&quot;ID&quot;, &quot;Title&quot;)
);&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Alternatively you can generate the list from a set of Enum values defined in your &lt;strong&gt;$db&lt;/strong&gt; array like so:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&quot;Options&quot; =&amp;gt; &quot;Enum('Default, Option1, Option2, Option3', 'Default')&quot;
&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;Then use this syntax when adding your form field to the &lt;strong&gt;getCMSFields() &lt;/strong&gt;function:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;$fields-&amp;gt;addFieldToTab(
	&quot;Root.Content.Main&quot;,
	new DropdownField(
		'Options',
		'Choose an option', 
		singleton('ThisPageType')-&amp;gt;dbObject('Options')-&amp;gt;enumValues())
);&lt;/textarea&gt;&lt;/p&gt;</description>
			<pubDate>Thu, 30 Apr 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/dynamically-generating-a-dropdown-list/</guid>
		</item>
		
		<item>
			<title>Create a Field in 'Page' but not it's Decendents</title>
			<link>http://www.ssbits.com/create-a-field-in-page-but-not-it-s-decendents/</link>
			<description>&lt;p&gt;This snippet allow you to add a field only to a page of type 'Page' and not those pages which extend Page.&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;	public function getCMSFields()
	{
	$fields = parent::getCMSFields();	
	if($this-&amp;gt;ClassName == &quot;Page&quot;){
		$fields-&amp;gt;addFieldToTab(&quot;Root.Content.Main&quot;, new TextField(&quot;PageField&quot;));
		}
		return $fields;
	}	&lt;/textarea&gt; &lt;/p&gt;</description>
			<pubDate>Sun, 26 Apr 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/create-a-field-in-page-but-not-it-s-decendents/</guid>
		</item>
		
		<item>
			<title>Create a Permission Code</title>
			<link>http://www.ssbits.com/create-a-permission-code/</link>
			<description>&lt;p&gt;Ever wanted to add an extra permission code so that when you add permissions to a group you can create a custom option? Here's how it's done; Simply add this code to your Page_Controller class as well as adding &quot;implements PermissionProvider&quot; on the end of the class definition like so:&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class Page_Controller extends ContentController implements PermissionProvider {
	
	function providePermissions(){
		return array(
			&quot;USER&quot; =&amp;gt; &quot;Just a regular user&quot;,
			&quot;SUPER_USER&quot; =&amp;gt; &quot;A super-duper mega user&quot;
		);
	}&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;That will create two new permission codes: 'USER' and 'SUPERUSER', so you can then call permission::check('USER') anywhere in your code to see if the current user is in a group with USER permissions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
			<pubDate>Sat, 18 Apr 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/create-a-permission-code/</guid>
		</item>
		
		<item>
			<title>getting objects from multiple child pages</title>
			<link>http://www.ssbits.com/getting-objects-from-multiple-child-pages/</link>
			<description>&lt;p&gt;When you want to create a DataObjectSet encompasing objects from all the current pages children you can do something like this:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;$pageIDs = $this-&amp;gt;getDescendantIDList();
$ObjectSet = DataObject::get(
                 &quot;Object&quot;, 
                 &quot;`ObjectPageID` IN (&quot; . implode(&quot;,&quot;, $pageIDs) . &quot;)&quot;
                  );&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;The first line creates an array of the ID's from all, with the current page and any descendant page ID's. &lt;/p&gt;
&lt;p&gt;The second line onwards then gets all Objects that have an ObjectPageID that
is either the current page's ID, or any child page of the current page.&lt;/p&gt;
&lt;p&gt;You can then add the usual &lt;strong&gt;filter&lt;/strong&gt;, &lt;strong&gt;join&lt;/strong&gt; or &lt;strong&gt;limit &lt;/strong&gt;clauses to the &lt;strong&gt;DataObject::get&lt;/strong&gt; call.&lt;/p&gt;</description>
			<pubDate>Tue, 14 Apr 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/getting-objects-from-multiple-child-pages/</guid>
		</item>
		
		<item>
			<title>Check to see if a widget area has any widgets</title>
			<link>http://www.ssbits.com/check-to-see-if-a-widget-area-has-any-widgets/</link>
			<description>&lt;p&gt;If you want to check that a WidgetArea actually has widgets, and only
display it if it has, you can add this function to your &lt;strong&gt;Page_Controller&lt;/strong&gt; (where &lt;strong&gt;widgetBarID&lt;/strong&gt; is&lt;strong&gt; &lt;/strong&gt;the name of your&lt;strong&gt; widgetArea&lt;em&gt; &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;+&lt;/em&gt;&lt;strong&gt;&lt;em&gt; &lt;/em&gt;ID&lt;/strong&gt;):&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;function HasWidgets() {
    return DataObject::get(&quot;Widget&quot;, &quot;ParentID = $this-&amp;gt;WidgetbarID&quot;);
} &lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Then in your template file, &lt;strong&gt;MyPage.ss&lt;/strong&gt; you can use HasWidgets to check whether the WidgetArea should be rendered:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;%if HasWidgets %&amp;gt;
    &amp;lt;div id=&quot;Widgetbar&quot;&amp;gt;
        $Widgetbar
    &amp;lt;/div&amp;gt;
&amp;lt;% end_if %&amp;gt;&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;You need to have added a WidgetArea to your page (called &lt;strong&gt;'Widgetbar'&lt;/strong&gt; in this example), otherwise the above will fail and you'll get a white page of
death. This code will add a widgetArea to &lt;strong&gt;MyPage&lt;/strong&gt;:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;class MyPage extends Page {
   
    static $db = array(
    );
    static $has_one = array(
        &quot;Widgetbar&quot; =&amp;gt; &quot;WidgetArea&quot;
    );
    function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields-&amp;gt;addFieldToTab('Root.Content.Widgets', new WidgetAreaEditor('Widgetbar'));
        return $fields;
    }
}&lt;/textarea&gt; 
&lt;/p&gt;</description>
			<pubDate>Sun, 05 Apr 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/check-to-see-if-a-widget-area-has-any-widgets/</guid>
		</item>
		
		<item>
			<title>Create an 'Edit this Page' link</title>
			<link>http://www.ssbits.com/create-an-edit-this-page-link/</link>
			<description>&lt;p&gt;For some sites you may want your client to be able to click a link on a particlar page and be taken strait to that page in the admin area. Here's what a link that does just that would look like:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;toolbar:false;'&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;a href=&quot;admin/show/{$ID}&quot; title=&quot;edit this page&quot;&amp;gt;Edit this page&amp;lt;/a&amp;gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;If you wanted this to only show up when a user is logged in you could use the &lt;strong&gt;CurrentMember &lt;/strong&gt;call to check. So it would look like this:&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;% if CurrentMember %&amp;gt;
      &amp;lt;a href=&quot;admin/show/{$ID}&quot; title=&quot;edit this page&quot;&amp;gt;Edit this Page&amp;lt;/a&amp;gt;
&amp;lt;% end_if %&amp;gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;You could also take this a step further and write a function in your page controller to check whether the current user has permission to access the CMS using &lt;strong&gt;Permission::check('&lt;acronym title=&quot;Content Management System&quot;&gt;CMS&lt;/acronym&gt;_ACCESS_CMSMain&lt;/strong&gt;&lt;strong&gt;') &lt;/strong&gt;call.&lt;/p&gt;</description>
			<pubDate>Sun, 29 Mar 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/create-an-edit-this-page-link/</guid>
		</item>
		
		<item>
			<title>Get Errors E-mailed to you</title>
			<link>http://www.ssbits.com/get-errors-e-mailed-to-you/</link>
			<description>&lt;p&gt;If your site is live it means you are probebly not getting errors reported in the view, so it's handy to have them emailed to you so you can still debug.&lt;/p&gt;
&lt;p&gt;Add this line to your &lt;strong&gt;mysite/_config.php&lt;/strong&gt; file and expect some mail!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mysite/_config.php&lt;/strong&gt;&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;if(Director::isLive()) Debug::send_errors_to(&quot;your@email.com&quot;);&lt;/textarea&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 24 Mar 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/get-errors-e-mailed-to-you/</guid>
		</item>
		
		<item>
			<title>Dynamic Year Function</title>
			<link>http://www.ssbits.com/dynamic-year-function/</link>
			<description>&lt;p&gt;Using this function you can create a dynamic year in the footer of your site. Simply add the function to your Page_Controller class and use $Year in your footer template.&lt;br /&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:php;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;	function Year(){
		$StartDate = &quot;2009&quot;;
		if($StartDate == Date(&quot;Y&quot;)){
			return $StartDate;
		}
		else{
			return 	$StartDate . &quot; - &quot; . Date(&quot;Y&quot;);
		}
	}&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;This will output &quot;2009&quot; for this year and then &quot;2009-2010&quot; next year etc.&lt;/p&gt;</description>
			<pubDate>Mon, 23 Mar 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/dynamic-year-function/</guid>
		</item>
		
		<item>
			<title>Resizing an image in a custom &lt;img&gt; tag</title>
			<link>http://www.ssbits.com/resizing-an-image-in-a-custom-img-tag/</link>
			<description>&lt;p&gt;You can resize images from within the template very easily. But sometimes you need to resize it and just use the URL value, something you can't do by calling the resize on the variable directly (e.g. $Image1.CroppedImage(200,200). This is how we would create a cropped resize of it and still be able to use just the URL, allowing a custom &amp;lt;img&amp;gt; tag.&lt;/p&gt;
&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;brush:xml; gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;% control Image1 %&amp;gt;
	&amp;lt;% control CroppedImage(200,200) %&amp;gt;
		&amp;lt;img src=&quot;$URL&quot; alt=&quot;A cropped image&quot; /&amp;gt;
	&amp;lt;% end_control %&amp;gt;
&amp;lt;% end_control %&amp;gt;&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;You can also use these other GD functions in a control block:&lt;br /&gt;
&lt;textarea name=&quot;code&quot; class=&quot;brush:xhtml;gutter:false;&quot; cols=&quot;80&quot; rows=&quot;10&quot;&gt;&amp;lt;% control PaddedImage(200,200) %&amp;gt; 
&amp;lt;% control ResizedImage(200,200) %&amp;gt; 
&amp;lt;% control SetWidth(200) %&amp;gt; 
&amp;lt;% control SetHeight(200) %&amp;gt; &lt;/textarea&gt; &lt;/p&gt;</description>
			<pubDate>Sun, 22 Mar 2009 00:00:00 -0500</pubDate>
			
			
			<guid>http://www.ssbits.com/resizing-an-image-in-a-custom-img-tag/</guid>
		</item>
		

	</channel>
</rss>
