I used SilverStripe to develop couple of projects and I really liked it. I am still a fan of CakePHP but you should give a try if you don’t want to build a new CMS from scratch with CakePHP.
I want to show you how easy to add an image rotator to your SilverStripe site by using JW Image Rotator. You can see it in action at sumpa.com.tr.
First download the greatest flash image rotator, JW Image Rotator. Then copy/move it to your SilverStripe project folder. I prefer “images” folder.

In order to add or remove new images (or swf files) to your rotator easily, we are going to use a folder in our “Uploads” directory and list all the files in this folder. Let’s assume that our directory name is “flash”. To do that, go to your admin panel in SilverStripe, switch to “Files & Images” tab in your menu and create a new directory called “flash”.
In your Page class, define a new method called ImageRotator().
// myproject/code/Page.php
class Page extends SiteTree {
static $db = array();
static $has_one = array();
function ImageRotator() {
return DataObject::get('File', 'ClassName <> "Folder" AND ParentID = (SELECT ID FROM File WHERE ClassName = "Folder" AND Name = "flash" LIMIT 0,1)');
}
}
Create a new file “ImageRotator.ss” in “myproject/templates/”
<?xml version="1.0" encoding="utf-8"?> <playlist version="1" xmlns="http://xspf.org/ns/0/"> <trackList> <% if ImageRotator %> <% control ImageRotator %> <track> <title>$Title.XML</title> <location>$BaseHref$Filename.XML</location> </track> <% end_if %> <% end_control %> </trackList> </playlist>
Create a new file “Flash.ss” in “myproject/templates/Includes”
<!--
Don't change the "file" variable. This is the URI of our XML which contains images
You can change other settings or add/remove.
-->
<script type="text/javascript">
var introFlashvars = {
width: "950",
height: "300",
file: "$URLSegment/ImageRotatorXML",
shownavigation: false,
screencolor: "0xFFFFFF",
rotatetime: 15
};
var params = {
wmode: "transparent"
}
</script>
<!--
Following div with id "Intro" is used as a container for our image rotator.
Browsers which are not supporting Javascript, "dummyimage.jpg" image linked to the home page is displayed
Don't forget to add swfobject.js into your head tag!
You can download it from http://code.google.com/p/swfobject/
-->
<div id="Intro"><a href="/"><img src="dummyimage.jpg" /></a></div>
<script type="text/javascript">
swfobject.embedSWF("$ThemeDir/images/imagerotator.swf", "Intro", introFlashvars.width, introFlashvars.height, "8", false, introFlashvars, params);
</script>
We complete the steps to create our rotator. Now, you can call it from any page that you want with the following include directive:
<% include Flash %>
Upload your images and swf files into your “flash” directory and open the page by adding “?flush=1″ to URI. It will refresh the cache.
I know, it should be a widget so that it can easily be added to the pages without hardcoding. I am not planning to do that kind of work but if you find it useful, convert it to a widget and share with community. You are free to do that! No license, no restrictions…
Contributions are welcome…
Combine is a small PHP script and some clever URL rewriting designed to speed up the loading of pages that use many or large css and javascript files.
It is good but how can you integrate it with your CakePHP project? And solution comes with the question
.
Download a copy of combine.php and drop it into your “app/webroot” directory (or whatever your application folder name is XXX/webroot/).
Open the file in your text editor and change lines:
$cachedir = dirname(__FILE__) . '/cache'; $cssdir = dirname(__FILE__) . '/css'; $jsdir = dirname(__FILE__) . '/javascript';
with
$cachedir = dirname(__FILE__) . '/../tmp/cache'; $cssdir = dirname(__FILE__) . '/css'; $jsdir = dirname(__FILE__) . '/js';
Open your “app/webroot/.htaccess” file and add those two lines
RewriteRule ^css/(.*\.css) combine.php?type=css&files=$1 RewriteRule ^js/(.*\.js) combine.php?type=javascript&files=$1
That’s all! Check download times of your css and javascript files with a tool like Firebug. A fatty 527KB ext-all.js javascript framework file compressed to 140KB! Amazing ha?
A CakePHP component which extends built-in RequestHandler component by adding some useful geolocation information. It requires MaxMind WebService license key to work properly.
Save it with the name request_handler_ext.php into your application components directory under controllers.
You can call the following methods within your controller (e.g. $this->RequestHandlerExt->methodName()):
getClientCountryCode() : ISO 3166 Two-letter Country Code
getClientRegionCode() : Region Code
getClientCity() : City
getClientPostalCode() : Postal Code
getClientLatitude() : Latitude
getClientLongitude() : Longitude
getClientMetropolitanCode() : Metropolitan Code
getClientMetropolitanCode() : Area Code
getClientIsp() : ISP
getClientOrganization() : Organization
<?php
/**
* Extends RequestHandler component by adding some useful geolocation information.
*
* Requires MaxMind WebService license key to work properly
*
* @copyright 2009 Erhan Abay
* @package app
* @subpackage app.controllers.components
* @version $Revision$
* @lastmodified $Date$
*/
App::import('Component', 'RequestHandler');
class RequestHandlerExtComponent extends RequestHandlerComponent
{
/**
* Required to query MaxMind WebService
*
* Provide your own key by replacing XXXXX.
*/
const MM_LICENSE_KEY = 'XXXXXX';
public function startup(&amp;amp;amp;$controller)
{
parent::startup(&amp;amp;amp;$controller);
$this->controller =&amp;amp;amp; $controller;
}
/**
* Searches key value in array returned by function getGeoLocation()
*
* @param string $name Name of the method
* @param unknown_type $arguments Not used, required not to give error
* @return string if key found
* null else
*/
public function __call($name, $raw = false)
{
$var = Inflector::underscore(preg_replace('/getClient/i', '', $name));
$geo_location = (array)$this->getGeoLocation($raw);
return array_key_exists($var, $geo_location) ? $geo_location[$var] : null;
}
/**
* Queries to the MaxMind WebService and returns an array of information
*
* @param bool $raw
* @return null if IP address is local
* bool false if webservice returns error code
* string if $raw is set true
* array else
*/
public function getGeoLocation($raw = false)
{
if ($this->isLocalIP()) {
return null;
}
if ($this->controller->Session->check('User.GeoLocation')) {
return $raw ? $this->controller->Session->read('User.GeoLocation.raw') : $this->controller->Session->read('User.GeoLocation');
}
App::import('HttpSocket');
$http = new HttpSocket();
/*
* Returns in order:
*
* 0 ISO 3166 Two-letter Country Code,
* 1 Region Code,
* 2 City,
* 3 Postal Code,
* 4 Latitude,
* 5 Longitude,
* 6 Metropolitan Code,
* 7 Area Code,
* 8 ISP,
* 9 Organization,
* 10 Error code
*/
$result = $http->get('http://geoip1.maxmind.com/f', array(
'l' => self::MM_LICENSE_KEY,
'i' => $this->getClientIP()
));
$values = explode(',', $result);
if (isset($values[10])) {
return false;
}
if ($raw) {
return $result;
}
$keys = array('country_code', 'region_code', 'city', 'postal_code', 'latitude', 'longitude', 'metropolitan_code', 'area_code', 'isp', 'organization');
$data = array_combine($keys, $values);
$data['coords'] = $values[4].','.$values[5];
$data['raw'] = $result;
$this->controller->Session->write('User.GeoLocation', $data);
return $data;
}
/**
* Detects whether IP address is local or not
*
* @param string $ip IP address to check
* @return bool
*/
public function isLocalIP($ip = null) {
$ip = is_null($ip) ? $this->getClientIP() : $ip;
$regex = '/(192\.168\.[0-9]{1,3}\.[0-9]{1,3})';
$regex .= '|(10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})';
$regex .= '|(172\.0?([1][6-9])¦([2][0-9])¦([3][0-1])\.[0-9]{1,3}\.[0-9]{1,3})';
$regex .= '|(127\.0\.0\.1)/';
return (bool)preg_match($regex, $ip);
}
}
?>