API moved StaticCache / StaticPublisher to module.

Removed all related functionality for exporting a static version of the website to the silverstripe-static module.
This commit is contained in:
Will Rossiter 2012-09-21 19:59:31 +12:00
parent bb4af2efbf
commit a3007b618f
11 changed files with 0 additions and 1121 deletions

View File

@ -1,114 +0,0 @@
<?php
/**
* This class lets you export a static copy of your site.
* It creates a huge number of folders each containing an index.html file.
* This preserves the URL naming format.
*
* Requirements: Unix Filesystem supporting symlinking. Doesn't work on Windows.
*
* <b>Usage</b>
*
* The exporter can only be invoked through a URL. Usage on commandline (through [sake](sake)) is not possible at the moment, as we're sending a file to the browser for download.
*
* <pre>http://localhost/StaticExporter/export</pre>
*
* Specify a custom baseurl in case you want to deploy the static HTML pages on a different host:
* <pre>http://localhost/StaticExporter/export?baseurl=http://example.com</pre>
*
* @see StaticPublisher
*
* @package cms
* @subpackage export
*/
class StaticExporter extends Controller {
static $allowed_actions = array(
'index',
'export',
);
function init() {
parent::init();
$canAccess = (Director::isDev() || Director::is_cli() || Permission::check("ADMIN"));
if(!$canAccess) return Security::permissionFailure($this);
}
function Link($action = null) {
return "StaticExporter/$action";
}
function index() {
echo "<h1>"._t('StaticExporter.NAME','Static exporter')."</h1>";
echo $this->StaticExportForm()->forTemplate();
}
function StaticExportForm() {
return new Form($this, 'StaticExportForm', new FieldList(
// new TextField('folder', _t('StaticExporter.FOLDEREXPORT','Folder to export to')),
new TextField('baseurl', _t('StaticExporter.BASEURL','Base URL'))
), new FieldList(
new FormAction('export', _t('StaticExporter.EXPORTTO','Export to that folder'))
));
}
function export() {
// specify custom baseurl for publishing to other webroot
if(isset($_REQUEST['baseurl'])) {
$base = $_REQUEST['baseurl'];
if(substr($base,-1) != '/') $base .= '/';
Director::setBaseURL($base);
}
// setup temporary folders
$tmpBaseFolder = TEMP_FOLDER . '/static-export';
$tmpFolder = (project()) ? "$tmpBaseFolder/" . project() : "$tmpBaseFolder/site";
if(!file_exists($tmpFolder)) Filesystem::makeFolder($tmpFolder);
$baseFolderName = basename($tmpFolder);
// symlink /assets
$f1 = ASSETS_PATH;
$f2 = Director::baseFolder() . '/' . project();
`cd $tmpFolder; ln -s $f1; ln -s $f2`;
// iterate through all instances of SiteTree
$pages = DataObject::get("SiteTree");
foreach($pages as $page) {
$subfolder = "$tmpFolder/" . trim($page->RelativeLink(null, true), '/');
$contentfile = "$tmpFolder/" . trim($page->RelativeLink(null, true), '/') . '/index.html';
// Make the folder
if(!file_exists($subfolder)) {
Filesystem::makeFolder($subfolder);
}
// Run the page
Requirements::clear();
$link = Director::makeRelative($page->Link());
$response = Director::test($link);
// Write to file
if($fh = fopen($contentfile, 'w')) {
fwrite($fh, $response->getBody());
fclose($fh);
}
}
// copy homepage (URLSegment: "home") to webroot
copy("$tmpFolder/home/index.html", "$tmpFolder/index.html");
// archive all generated files
`cd $tmpBaseFolder; tar -czhf $baseFolderName.tar.gz $baseFolderName`;
$archiveContent = file_get_contents("$tmpBaseFolder/$baseFolderName.tar.gz");
// remove temporary files and folder
Filesystem::removeFolder($tmpBaseFolder);
// return as download to the client
$response = SS_HTTPRequest::send_file($archiveContent, "$baseFolderName.tar.gz", 'application/x-tar-gz');
echo $response->output();
}
}

View File

@ -1,28 +0,0 @@
<?php
/**
* This is a system-generated PHP script that performs header management for the statically cached content given below.
*/
define('MAX_AGE', '**MAX_AGE**');
define('LAST_MODIFIED', '**LAST_MODIFIED**');
if(MAX_AGE > 0) {
header("Cache-Control: max-age=" . MAX_AGE);
header("Pragma:");
} else {
header("Cache-Control: no-cache, max-age=0, must-revalidate");
}
header("Expires: " . gmdate('D, d M Y H:i:s', time() + MAX_AGE) . ' GMT');
header("Last-modified: " . gmdate('D, d M Y H:i:s', strtotime(LAST_MODIFIED)) . ' GMT');
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
if(strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= strtotime(LAST_MODIFIED)) {
header("Last-modified: " . gmdate('D, d M Y H:i:s', strtotime(LAST_MODIFIED)) . ' GMT', true, 304);
exit;
}
}
?>
**CONTENT**

View File

@ -1,20 +0,0 @@
<?php
/**
* This is a system-generated PHP script that performs header management for a 301 redirection.
*/
define('DESTINATION', '**DESTINATION**');
define('MAX_AGE', 3600);
if(MAX_AGE > 0) {
header("Cache-Control: max-age=" . MAX_AGE);
header("Pragma:");
} else {
header("Cache-Control: no-cache, max-age=0, must-revalidate");
}
header("Expires: " . gmdate('D, d M Y H:i:s', time() + MAX_AGE) . ' GMT');
header("Location: " . DESTINATION, true, 301);
?>

View File

@ -1,327 +0,0 @@
<?php
/**
* Usage: Object::add_extension("SiteTree", "FilesystemPublisher('static-folder', 'html')");
*
* Usage: To work with Subsite module you need to:
* - Add FilesystemPublisher::$domain_based_caching = true; in mysite/_config.php
* - Added main site host mapping in subsites/host-map.php after everytime a new subsite is created or modified
*
* You may also have a method $page->pagesAffectedByUnpublishing() to return other URLS
* that should be de-cached if $page is unpublished.
*
* @see http://doc.silverstripe.com/doku.php?id=staticpublisher
*
* @package cms
* @subpackage publishers
*/
class FilesystemPublisher extends StaticPublisher {
/**
* @var String
*/
protected $destFolder = 'cache';
/**
* @var String
*/
protected $fileExtension = 'html';
/**
* @var String
*/
protected static $static_base_url = null;
/**
* @var Boolean Use domain based cacheing (put cache files into a domain subfolder)
* This must be true if you are using this with the "subsites" module.
* Please note that this form of caching requires all URLs to be provided absolute
* (not relative to the webroot) via {@link SiteTree->AbsoluteLink()}.
*/
public static $domain_based_caching = false;
/**
* Set a different base URL for the static copy of the site.
* This can be useful if you are running the CMS on a different domain from the website.
*/
static function set_static_base_url($url) {
self::$static_base_url = $url;
}
/**
* @param $destFolder The folder to save the cached site into.
* This needs to be set in framework/static-main.php as well through the {@link $cacheBaseDir} variable.
* @param $fileExtension The file extension to use, e.g 'html'.
* If omitted, then each page will be placed in its own directory,
* with the filename 'index.html'. If you set the extension to PHP, then a simple PHP script will
* be generated that can do appropriate cache & redirect header negotation.
*/
function __construct($destFolder = 'cache', $fileExtension = null) {
// Remove trailing slash from folder
if(substr($destFolder, -1) == '/') $destFolder = substr($destFolder, 0, -1);
$this->destFolder = $destFolder;
$this->fileExtension = $fileExtension;
parent::__construct();
}
/**
* Transforms relative or absolute URLs to their static path equivalent.
* This needs to be the same logic that's used to look up these paths through
* framework/static-main.php. Does not include the {@link $destFolder} prefix.
*
* URL filtering will have already taken place for direct SiteTree links via SiteTree->generateURLSegment()).
* For all other links (e.g. custom controller actions), we assume that they're pre-sanitized
* to suit the filesystem needs, as its impossible to sanitize them without risking to break
* the underlying naming assumptions in URL routing (e.g. controller method names).
*
* Examples (without $domain_based_caching):
* - http://mysite.com/mywebroot/ => /index.html (assuming your webroot is in a subfolder)
* - http://mysite.com/about-us => /about-us.html
* - http://mysite.com/parent/child => /parent/child.html
*
* Examples (with $domain_based_caching):
* - http://mysite.com/mywebroot/ => /mysite.com/index.html (assuming your webroot is in a subfolder)
* - http://mysite.com/about-us => /mysite.com/about-us.html
* - http://myothersite.com/about-us => /myothersite.com/about-us.html
* - http://subdomain.mysite.com/parent/child => /subdomain.mysite.com/parent/child.html
*
* @param Array $urls Absolute or relative URLs
* @return Array Map of original URLs to filesystem paths (relative to {@link $destFolder}).
*/
function urlsToPaths($urls) {
$mappedUrls = array();
foreach($urls as $url) {
// parse_url() is not multibyte safe, see https://bugs.php.net/bug.php?id=52923.
// We assume that the URL hsa been correctly encoded either on storage (for SiteTree->URLSegment),
// or through URL collection (for controller method names etc.).
$urlParts = @parse_url($url);
// Remove base folders from the URL if webroot is hosted in a subfolder (same as static-main.php)
$path = isset($urlParts['path']) ? $urlParts['path'] : '';
if(mb_substr(mb_strtolower($path), 0, mb_strlen(BASE_URL)) == mb_strtolower(BASE_URL)) {
$urlSegment = mb_substr($path, mb_strlen(BASE_URL));
} else {
$urlSegment = $path;
}
// Normalize URLs
$urlSegment = trim($urlSegment, '/');
$filename = $urlSegment ? "$urlSegment.$this->fileExtension" : "index.$this->fileExtension";
if (self::$domain_based_caching) {
if (!$urlParts) continue; // seriously malformed url here...
$filename = $urlParts['host'] . '/' . $filename;
}
$mappedUrls[$url] = ((dirname($filename) == '/') ? '' : (dirname($filename).'/')).basename($filename);
}
return $mappedUrls;
}
function unpublishPages($urls) {
// Do we need to map these?
// Detect a numerically indexed arrays
if (is_numeric(join('', array_keys($urls)))) $urls = $this->urlsToPaths($urls);
// This can be quite memory hungry and time-consuming
// @todo - Make a more memory efficient publisher
increase_time_limit_to();
increase_memory_limit_to();
$cacheBaseDir = $this->getDestDir();
foreach($urls as $url => $path) {
if (file_exists($cacheBaseDir.'/'.$path)) {
@unlink($cacheBaseDir.'/'.$path);
}
}
}
function publishPages($urls) {
// Do we need to map these?
// Detect a numerically indexed arrays
if (is_numeric(join('', array_keys($urls)))) $urls = $this->urlsToPaths($urls);
// This can be quite memory hungry and time-consuming
// @todo - Make a more memory efficient publisher
increase_time_limit_to();
increase_memory_limit_to();
// Set the appropriate theme for this publication batch.
// This may have been set explicitly via StaticPublisher::static_publisher_theme,
// or we can use the last non-null theme.
if(!StaticPublisher::static_publisher_theme())
SSViewer::set_theme(SSViewer::current_custom_theme());
else
SSViewer::set_theme(StaticPublisher::static_publisher_theme());
$currentBaseURL = Director::baseURL();
if(self::$static_base_url) Director::setBaseURL(self::$static_base_url);
if($this->fileExtension == 'php') SSViewer::setOption('rewriteHashlinks', 'php');
if(StaticPublisher::echo_progress()) echo $this->class.": Publishing to " . self::$static_base_url . "\n";
$files = array();
$i = 0;
$totalURLs = sizeof($urls);
foreach($urls as $url => $path) {
if(self::$static_base_url) Director::setBaseURL(self::$static_base_url);
$i++;
if($url && !is_string($url)) {
user_error("Bad url:" . var_export($url,true), E_USER_WARNING);
continue;
}
if(StaticPublisher::echo_progress()) {
echo " * Publishing page $i/$totalURLs: $url\n";
flush();
}
Requirements::clear();
if($url == "") $url = "/";
if(Director::is_relative_url($url)) $url = Director::absoluteURL($url);
$response = Director::test(str_replace('+', ' ', $url));
Requirements::clear();
singleton('DataObject')->flushCache();
//skip any responses with a 404 status code. We don't want to turn those into statically cached pages
if (!$response || $response->getStatusCode() == '404') continue;
// Generate file content
// PHP file caching will generate a simple script from a template
if($this->fileExtension == 'php') {
if(is_object($response)) {
if($response->getStatusCode() == '301' || $response->getStatusCode() == '302') {
$content = $this->generatePHPCacheRedirection($response->getHeader('Location'));
} else {
$content = $this->generatePHPCacheFile($response->getBody(), HTTP::get_cache_age(), date('Y-m-d H:i:s'));
}
} else {
$content = $this->generatePHPCacheFile($response . '', HTTP::get_cache_age(), date('Y-m-d H:i:s'));
}
// HTML file caching generally just creates a simple file
} else {
if(is_object($response)) {
if($response->getStatusCode() == '301' || $response->getStatusCode() == '302') {
$absoluteURL = Director::absoluteURL($response->getHeader('Location'));
$content = "<meta http-equiv=\"refresh\" content=\"2; URL=$absoluteURL\">";
} else {
$content = $response->getBody();
}
} else {
$content = $response . '';
}
}
$files[] = array(
'Content' => $content,
'Folder' => dirname($path).'/',
'Filename' => basename($path),
);
// Add externals
/*
$externals = $this->externalReferencesFor($content);
if($externals) foreach($externals as $external) {
// Skip absolute URLs
if(preg_match('/^[a-zA-Z]+:\/\//', $external)) continue;
// Drop querystring parameters
$external = strtok($external, '?');
if(file_exists("../" . $external)) {
// Break into folder and filename
if(preg_match('/^(.*\/)([^\/]+)$/', $external, $matches)) {
$files[$external] = array(
"Copy" => "../$external",
"Folder" => $matches[1],
"Filename" => $matches[2],
);
} else {
user_error("Can't parse external: $external", E_USER_WARNING);
}
} else {
$missingFiles[$external] = true;
}
}*/
}
if(self::$static_base_url) Director::setBaseURL($currentBaseURL);
if($this->fileExtension == 'php') SSViewer::setOption('rewriteHashlinks', true);
$base = BASE_PATH . "/$this->destFolder";
foreach($files as $file) {
Filesystem::makeFolder("$base/$file[Folder]");
if(isset($file['Content'])) {
$fh = fopen("$base/$file[Folder]$file[Filename]", "w");
fwrite($fh, $file['Content']);
fclose($fh);
} else if(isset($file['Copy'])) {
copy($file['Copy'], "$base/$file[Folder]$file[Filename]");
}
}
}
/**
* Generate the templated content for a PHP script that can serve up the given piece of content with the given age and expiry
*/
protected function generatePHPCacheFile($content, $age, $lastModified) {
$template = file_get_contents(BASE_PATH . '/cms/code/staticpublisher/CachedPHPPage.tmpl');
return str_replace(
array('**MAX_AGE**', '**LAST_MODIFIED**', '**CONTENT**'),
array((int)$age, $lastModified, $content),
$template);
}
/**
* Generate the templated content for a PHP script that can serve up a 301 redirect to the given destionation
*/
protected function generatePHPCacheRedirection($destination) {
$template = file_get_contents(BASE_PATH . '/cms/code/staticpublisher/CachedPHPRedirection.tmpl');
return str_replace(
array('**DESTINATION**'),
array($destination),
$template);
}
public function getDestDir() {
return BASE_PATH . '/' . $this->destFolder;
}
/**
* Return an array of all the existing static cache files, as a map of URL => file.
* Only returns cache files that will actually map to a URL, based on urlsToPaths.
*/
public function getExistingStaticCacheFiles() {
$cacheDir = BASE_PATH . '/' . $this->destFolder;
$urlMapper = array_flip($this->urlsToPaths($this->owner->allPagesToCache()));
$output = array();
// Glob each dir, then glob each one of those
foreach(glob("$cacheDir/*", GLOB_ONLYDIR) as $cacheDir) {
foreach(glob($cacheDir.'/*') as $cacheFile) {
$mapKey = str_replace(BASE_PATH . "/cache/","",$cacheFile);
if(isset($urlMapper[$mapKey])) {
$url = $urlMapper[$mapKey];
$output[$url] = $cacheFile;
}
}
}
return $output;
}
}

View File

@ -1,63 +0,0 @@
<?php
/**
* This static publisher can be used to deploy static content to multiple hosts, by generating the cache files locally and then rsyncing then to
* each destination box. This can be used to set up a load-balanced collection of static servers.
*
* @see http://doc.silverstripe.com/doku.php?id=staticpublisher
*
* @package cms
* @subpackage publishers
*/
class RsyncMultiHostPublisher extends FilesystemPublisher {
/**
* Array of rsync targets to publish to. These can either be local file names, or scp-style targets, in the form "user@server:path"
*/
protected static $targets = array();
protected static $excluded_folders = array();
/**
* Set the targets to publish to.
* If target is an scp-style remote path, no password is accepted - we assume key-based authentication to be set up on the application server
* initiating the publication.
*
* @param $targets An array of targets to publish to. These can either be local file names, or scp-style targets, in the form "user@server:path"
*/
static function set_targets($targets) {
self::$targets = $targets;
}
/**
* Specify folders to exclude from the rsync
* For example, you could exclude assets.
*/
static function set_excluded_folders($folders) {
self::$excluded_folders = $folders;
}
function publishPages($urls) {
parent::publishPages($urls);
$base = Director::baseFolder();
$framework = FRAMEWORK_DIR;
// Get variable that can turn off the rsync component of publication
if(isset($_GET['norsync']) && $_GET['norsync']) return;
$extraArg = "";
if(self::$excluded_folders) foreach(self::$excluded_folders as $folder) {
$extraArg .= " --exclude " . escapeshellarg($folder);
}
foreach(self::$targets as $target) {
// Transfer non-PHP content from everything to the target; that will ensure that we have all the JS/CSS/etc
$rsyncOutput = `cd $base; rsync -av -e ssh --exclude /.htaccess --exclude /web.config --exclude '*.php' --exclude '*.svn' --exclude '*.git' --exclude '*~' $extraArg --delete . $target`;
// Then transfer "safe" PHP from the cache/ directory
$rsyncOutput .= `cd $base; rsync -av -e ssh --exclude '*.svn' --exclude '*~' $extraArg --delete cache $target`;
// Transfer framework/static-main.php to the target
$rsyncOutput .= `cd $base; rsync -av -e ssh --delete $framework/static-main.php $target/$framework`;
if(StaticPublisher::echo_progress()) echo $rsyncOutput;
}
}
}

View File

@ -1,157 +0,0 @@
<?php
/**
* @package cms
* @subpackage publishers
*/
abstract class StaticPublisher extends DataExtension {
/**
* Defines whether to output information about publishing or not. By
* default, this is off, and should be turned on when you want debugging
* (for example, in a cron task)
*/
static $echo_progress = false;
/**
* Realtime static publishing... the second a page
* is saved, it is written to the cache
*/
static $disable_realtime = false;
/*
* This is the current static publishing theme, which can be set at any point
* If it's not set, then the last non-null theme, set via SSViewer::set_theme() is used
* The obvious place to set this is in _config.php
*/
static $static_publisher_theme=false;
abstract function publishPages($pages);
abstract function unpublishPages($pages);
static function set_static_publisher_theme($theme){
self::$static_publisher_theme=$theme;
}
static function static_publisher_theme(){
return self::$static_publisher_theme;
}
static function echo_progress() {
return (boolean)self::$echo_progress;
}
/**
* Either turns on (boolean true) or off (boolean false) the progress indicators.
* @see StaticPublisher::$echo_progress
*/
static function set_echo_progress($progress) {
self::$echo_progress = (boolean)$progress;
}
/**
* Called after a page is published.
*/
function onAfterPublish($original) {
$this->republish($original);
}
/**
* Called after link assets have been renamed, and the live site has been updated, without
* an actual publish event.
*
* Only called if the published content exists and has been modified.
*/
function onRenameLinkedAsset($original) {
$this->republish($original);
}
function republish($original) {
if (self::$disable_realtime) return;
$urls = array();
if($this->owner->hasMethod('pagesAffectedByChanges')) {
$urls = $this->owner->pagesAffectedByChanges($original);
} else {
$pages = Versioned::get_by_stage('SiteTree', 'Live', '', '', '', 10);
if($pages) {
foreach($pages as $page) {
$urls[] = $page->AbsoluteLink();
}
}
}
// Note: Similiar to RebuildStaticCacheTask->rebuildCache()
foreach($urls as $i => $url) {
if(!is_string($url)) {
user_error("Bad URL: " . var_export($url, true), E_USER_WARNING);
continue;
}
// Remove leading slashes from all URLs (apart from the homepage)
if(substr($url,-1) == '/' && $url != '/') $url = substr($url,0,-1);
$urls[$i] = $url;
}
$urls = array_unique($urls);
$this->publishPages($urls);
}
/**
* On after unpublish, get changes and hook into underlying
* functionality
*/
function onAfterUnpublish($page) {
if (self::$disable_realtime) return;
// Get the affected URLs
if($this->owner->hasMethod('pagesAffectedByUnpublishing')) {
$urls = $this->owner->pagesAffectedByUnpublishing();
$urls = array_unique($urls);
} else {
$urls = array($this->owner->AbsoluteLink());
}
$legalPages = singleton('Page')->allPagesToCache();
$urlsToRepublish = array_intersect($urls, $legalPages);
$urlsToUnpublish = array_diff($urls, $legalPages);
$this->unpublishPages($urlsToUnpublish);
$this->publishPages($urlsToRepublish);
}
/**
* Get all external references to CSS, JS,
*/
function externalReferencesFor($content) {
$CLI_content = escapeshellarg($content);
$tidy = `echo $CLI_content | tidy -numeric -asxhtml`;
$tidy = preg_replace('/xmlns="[^"]+"/','', $tidy);
$xContent = new SimpleXMLElement($tidy);
//Debug::message($xContent->asXML());
$xlinks = array(
"//link[@rel='stylesheet']/@href" => false,
"//script/@src" => false,
"//img/@src" => false,
"//a/@href" => true,
);
$urls = array();
foreach($xlinks as $xlink => $assetsOnly) {
$matches = $xContent->xpath($xlink);
if($matches) foreach($matches as $item) {
$url = $item . '';
if($assetsOnly && substr($url,0,7) != ASSETS_DIR . '/') continue;
$urls[] = $url;
}
}
return $urls;
}
}

View File

@ -1,39 +0,0 @@
### SILVERSTRIPE START ###
RewriteEngine On
## CONFIG FOR DEV ENVIRONMENTS
# Cached content - **sitedir** subdirectory
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/**sitedir**/(.*)$
RewriteCond %{REQUEST_URI} /**sitedir**/(.*[^/])/?$
RewriteCond %{DOCUMENT_ROOT}/**sitedir**/cache/%1.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /**sitedir**/cache/%1.html [L]
# Cached content - homepage
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/**sitedir**/?$
RewriteCond /**sitedir**/cache/index.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /**sitedir**/cache/index.html [L]
## CONFIG FOR TEST/LIVE ENVIRONMENTS
# Cached content - live webserver
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} /(.*[^/])/?$
RewriteCond %{DOCUMENT_ROOT}/cache/%1.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/%1.html [L]
# Cached content - homepage
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/?$
RewriteCond %{DOCUMENT_ROOT}/cache/index.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/index.html [L]

View File

@ -1,48 +0,0 @@
### SILVERSTRIPE START ###
RewriteEngine On
## CONFIG FOR DEV ENVIRONMENTS
# Cached content - **sitedir** subdirectory
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/**sitedir**/(.*)$
RewriteCond %{REQUEST_URI} /**sitedir**/(.*[^/])/?$
RewriteCond %{DOCUMENT_ROOT}/**sitedir**/cache/%1.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /**sitedir**/cache/%1.html [L]
# Cached content - homepage
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/**sitedir**/?$
RewriteCond /**sitedir**/cache/index.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /**sitedir**/cache/index.html [L]
## CONFIG FOR TEST/LIVE ENVIRONMENTS
# Cached content - live webserver
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} /(.*[^/])/?$
RewriteCond %{DOCUMENT_ROOT}/cache/%1.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/%1.html [L]
# Cached content - homepage
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/?$
RewriteCond %{DOCUMENT_ROOT}/cache/index.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/index.html [L]
## DYNAMIC CONFIG
# Dynamic content
RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)$
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* framework/main.php?url=%1&%{QUERY_STRING} [L]
### SILVERSTRIPE END ###

View File

@ -1,39 +0,0 @@
### SILVERSTRIPE START ###
RewriteEngine On
## CONFIG FOR DEV ENVIRONMENTS
# Cached content - **sitedir** subdirectory
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/**sitedir**/(.*)$
RewriteCond %{REQUEST_URI} /**sitedir**/(.*[^/])/?$
RewriteCond %{DOCUMENT_ROOT}/**sitedir**/cache/%1.php -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /**sitedir**/cache/%1.php [L]
# Cached content - homepage
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/**sitedir**/?$
RewriteCond /**sitedir**/cache/index.php -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /**sitedir**/cache/index.php [L]
## CONFIG FOR TEST/LIVE ENVIRONMENTS
# Cached content - live webserver
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} /(.*[^/])/?$
RewriteCond %{DOCUMENT_ROOT}/cache/%1.php -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/%1.php [L]
# Cached content - homepage
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/?$
RewriteCond %{DOCUMENT_ROOT}/cache/index.php -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/index.php [L]

View File

@ -1,126 +0,0 @@
<?php
/**
* @package cms
* @subpackage tasks
*
* @todo Make this use the Task interface once it gets merged back into trunk
*/
class RebuildStaticCacheTask extends Controller {
static $allowed_actions = array(
'index',
);
function init() {
parent::init();
Versioned::reading_stage('live');
$canAccess = (Director::isDev() || Director::is_cli() || Permission::check("ADMIN"));
if(!$canAccess) return Security::permissionFailure($this);
}
function index() {
StaticPublisher::set_echo_progress(true);
$page = singleton('Page');
if(!$page->hasMethod('allPagesToCache')) {
user_error(
'RebuildStaticCacheTask::index(): Please define a method "allPagesToCache()" on your Page class to return all pages affected by a cache refresh.',
E_USER_ERROR
);
}
if(!empty($_GET['urls'])) $urls = $_GET['urls'];
else $urls = $page->allPagesToCache();
$this->rebuildCache($urls, true);
}
/**
* Rebuilds the static cache for the pages passed through via $urls
*
* @param array $urls The URLs of pages to re-fetch and cache.
* @param bool $removeAll Remove all stale cache files (default TRUE).
*/
function rebuildCache($urls, $removeAll = true) {
if(!is_array($urls)) {
// $urls must be an array
user_error("Rebuild cache must be passed an array of urls. Make sure your allPagesToCache function returns an array", E_USER_ERROR);
return;
};
if(!Director::is_cli()) echo "<pre>\n";
echo "Rebuilding cache.\nNOTE: Please ensure that this page ends with 'Done!' - if not, then something may have gone wrong.\n\n";
$page = singleton('Page');
$cacheBaseDir = $page->getDestDir();
if(!file_exists($cacheBaseDir)) {
Filesystem::makeFolder($cacheBaseDir);
}
if (file_exists($cacheBaseDir.'/lock') && !isset($_REQUEST['force'])) die("There already appears to be a publishing queue running. You can skip warning this by adding ?/&force to the URL.");
touch($cacheBaseDir.'/lock');
// Note: Similiar to StaticPublisher->republish()
foreach($urls as $i => $url) {
if($url && !is_string($url)) {
user_error("Bad URL: " . var_export($url, true), E_USER_WARNING);
continue;
}
// Remove leading slashes from all URLs (apart from the homepage)
if(substr($url,-1) == '/' && $url != '/') $url = substr($url,0,-1);
$urls[$i] = $url;
}
$urls = array_unique($urls);
sort($urls);
$mappedUrls = $page->urlsToPaths($urls);
$start = isset($_GET['start']) ? $_GET['start'] : 0;
$count = isset($_GET['count']) ? $_GET['count'] : sizeof($urls);
if(($start + $count) > sizeof($urls)) $count = sizeof($urls) - $start;
$urls = array_slice($urls, $start, $count);
if($removeAll && !isset($_GET['urls']) && $start == 0 && file_exists("../cache")) {
echo "Removing stale cache files... \n";
flush();
if (FilesystemPublisher::$domain_based_caching) {
// Glob each dir, then glob each one of those
foreach(glob(BASE_PATH . '/cache/*', GLOB_ONLYDIR) as $cacheDir) {
foreach(glob($cacheDir.'/*') as $cacheFile) {
$searchCacheFile = trim(str_replace($cacheBaseDir, '', $cacheFile), '\/');
if (!in_array($searchCacheFile, $mappedUrls)) {
echo " * Deleting $cacheFile\n";
@unlink($cacheFile);
}
}
}
} else {
}
echo "done.\n\n";
}
echo "Rebuilding cache from " . sizeof($mappedUrls) . " urls...\n\n";
$page->extend('publishPages', $mappedUrls);
if (file_exists($cacheBaseDir.'/lock')) unlink($cacheBaseDir.'/lock');
echo "\n\n== Done! ==";
}
function show() {
$urls = singleton('Page')->allPagesToCache();
echo "<pre>\n";
print_r($urls);
echo "\n</pre>";
}
}

View File

@ -1,160 +0,0 @@
<?php
/**
* Tests for the {@link FilesystemPublisher} class.
*
* @package cms
* @subpackage tests
*/
class FilesystemPublisherTest extends SapphireTest {
protected $usesDatabase = true;
protected $orig = array();
function setUp() {
parent::setUp();
Object::add_extension("SiteTree", "FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/')");
$this->orig['domain_based_caching'] = FilesystemPublisher::$domain_based_caching;
FilesystemPublisher::$domain_based_caching = false;
}
function tearDown() {
parent::tearDown();
Object::remove_extension("SiteTree", "FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/')");
FilesystemPublisher::$domain_based_caching = $this->orig['domain_based_caching'];
if(file_exists(BASE_PATH . '/assets/FilesystemPublisherTest-static-folder')) {
Filesystem::removeFolder(BASE_PATH . '/assets/FilesystemPublisherTest-static-folder');
}
}
function testUrlsToPathsWithRelativeUrls() {
$fsp = new FilesystemPublisher('.', 'html');
$this->assertEquals(
$fsp->urlsToPaths(array('/')),
array('/' => './index.html'),
'Root URL path mapping'
);
$this->assertEquals(
$fsp->urlsToPaths(array('about-us')),
array('about-us' => './about-us.html'),
'URLsegment path mapping'
);
$this->assertEquals(
$fsp->urlsToPaths(array('parent/child')),
array('parent/child' => 'parent/child.html'),
'Nested URLsegment path mapping'
);
}
function testUrlsToPathsWithAbsoluteUrls() {
$fsp = new FilesystemPublisher('.', 'html');
$url = Director::absoluteBaseUrl();
$this->assertEquals(
$fsp->urlsToPaths(array($url)),
array($url => './index.html'),
'Root URL path mapping'
);
$url = Director::absoluteBaseUrl() . 'about-us';
$this->assertEquals(
$fsp->urlsToPaths(array($url)),
array($url => './about-us.html'),
'URLsegment path mapping'
);
$url = Director::absoluteBaseUrl() . 'parent/child';
$this->assertEquals(
$fsp->urlsToPaths(array($url)),
array($url => 'parent/child.html'),
'Nested URLsegment path mapping'
);
}
function testUrlsToPathsWithDomainBasedCaching() {
$origDomainBasedCaching = FilesystemPublisher::$domain_based_caching;
FilesystemPublisher::$domain_based_caching = true;
$fsp = new FilesystemPublisher('.', 'html');
$url = 'http://domain1.com/';
$this->assertEquals(
$fsp->urlsToPaths(array($url)),
array($url => 'domain1.com/index.html'),
'Root URL path mapping'
);
$url = 'http://domain1.com/about-us';
$this->assertEquals(
$fsp->urlsToPaths(array($url)),
array($url => 'domain1.com/about-us.html'),
'URLsegment path mapping'
);
$url = 'http://domain2.com/parent/child';
$this->assertEquals(
$fsp->urlsToPaths(array($url)),
array($url => 'domain2.com/parent/child.html'),
'Nested URLsegment path mapping'
);
FilesystemPublisher::$domain_based_caching = $origDomainBasedCaching;
}
/**
* Simple test to ensure that FileSystemPublisher::__construct()
* has called parent::__construct() by checking the class property.
* The class property is set on {@link Object::__construct()} and
* this is therefore a good test to ensure it was called.
*
* If FilesystemPublisher doesn't call parent::__construct() then
* it won't be enabled propery because {@link Object::__construct()}
* is where extension instances are set up and subsequently used by
* {@link DataObject::defineMethods()}.
*/
function testHasCalledParentConstructor() {
$fsp = new FilesystemPublisher('.', '.html');
$this->assertEquals($fsp->class, 'FilesystemPublisher');
}
/*
* These are a few simple tests to check that we will be retrieving the correct theme when we need it
* StaticPublishing needs to be able to retrieve a non-null theme at the time publishPages() is called.
*/
function testStaticPublisherTheme(){
//This will be the name of the default theme of this particular project
$default_theme=SSViewer::current_theme();
$p1 = new Page();
$p1->URLSegment = strtolower(__CLASS__).'-page-1';
$p1->HomepageForDomain = '';
$p1->write();
$p1->doPublish();
$current_theme=SSViewer::current_custom_theme();
$this->assertEquals($current_theme, $default_theme, 'After a standard publication, the theme is correct');
//The CMS sometimes sets the theme to null. Check that the $current_custom_theme is still the default
SSViewer::set_theme(null);
$current_theme=SSViewer::current_custom_theme();
$this->assertEquals($current_theme, $default_theme, 'After a setting the theme to null, the default theme is correct');
//We can set the static_publishing theme to something completely different:
//Static publishing will use this one instead of the current_custom_theme if it is not false
StaticPublisher::set_static_publisher_theme('otherTheme');
$current_theme=StaticPublisher::static_publisher_theme();
$this->assertNotEquals($current_theme, $default_theme, 'The static publisher theme overrides the custom theme');
}
}