From a3007b618f4d3d88b84c8edd005d45c8c3e7205f Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Fri, 21 Sep 2012 19:59:31 +1200 Subject: [PATCH 1/2] API moved StaticCache / StaticPublisher to module. Removed all related functionality for exporting a static version of the website to the silverstripe-static module. --- code/controllers/StaticExporter.php | 114 ------ code/staticpublisher/CachedPHPPage.tmpl | 28 -- .../staticpublisher/CachedPHPRedirection.tmpl | 20 -- code/staticpublisher/FilesystemPublisher.php | 327 ------------------ .../RsyncMultiHostPublisher.php | 63 ---- code/staticpublisher/StaticPublisher.php | 157 --------- .../htaccess_example_rsyncmultiservers | 39 --- .../htaccess_example_rsyncsingleserver | 48 --- .../htaccess_example_rsyncwithphp | 39 --- tasks/RebuildStaticCacheTask.php | 126 ------- .../FilesystemPublisherTest.php | 160 --------- 11 files changed, 1121 deletions(-) delete mode 100644 code/controllers/StaticExporter.php delete mode 100644 code/staticpublisher/CachedPHPPage.tmpl delete mode 100644 code/staticpublisher/CachedPHPRedirection.tmpl delete mode 100644 code/staticpublisher/FilesystemPublisher.php delete mode 100644 code/staticpublisher/RsyncMultiHostPublisher.php delete mode 100644 code/staticpublisher/StaticPublisher.php delete mode 100644 code/staticpublisher/htaccess_example_rsyncmultiservers delete mode 100644 code/staticpublisher/htaccess_example_rsyncsingleserver delete mode 100644 code/staticpublisher/htaccess_example_rsyncwithphp delete mode 100644 tasks/RebuildStaticCacheTask.php delete mode 100644 tests/staticpublisher/FilesystemPublisherTest.php diff --git a/code/controllers/StaticExporter.php b/code/controllers/StaticExporter.php deleted file mode 100644 index 1dbb8dd6..00000000 --- a/code/controllers/StaticExporter.php +++ /dev/null @@ -1,114 +0,0 @@ -Usage - * - * 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. - * - *
http://localhost/StaticExporter/export
- * - * Specify a custom baseurl in case you want to deploy the static HTML pages on a different host: - *
http://localhost/StaticExporter/export?baseurl=http://example.com
- * - * @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 "

"._t('StaticExporter.NAME','Static exporter')."

"; - 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(); - } - -} - diff --git a/code/staticpublisher/CachedPHPPage.tmpl b/code/staticpublisher/CachedPHPPage.tmpl deleted file mode 100644 index 2fe875b6..00000000 --- a/code/staticpublisher/CachedPHPPage.tmpl +++ /dev/null @@ -1,28 +0,0 @@ - 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** diff --git a/code/staticpublisher/CachedPHPRedirection.tmpl b/code/staticpublisher/CachedPHPRedirection.tmpl deleted file mode 100644 index 755fcddd..00000000 --- a/code/staticpublisher/CachedPHPRedirection.tmpl +++ /dev/null @@ -1,20 +0,0 @@ - 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); - -?> diff --git a/code/staticpublisher/FilesystemPublisher.php b/code/staticpublisher/FilesystemPublisher.php deleted file mode 100644 index 92a5082d..00000000 --- a/code/staticpublisher/FilesystemPublisher.php +++ /dev/null @@ -1,327 +0,0 @@ -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 = ""; - } 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; - } - -} - diff --git a/code/staticpublisher/RsyncMultiHostPublisher.php b/code/staticpublisher/RsyncMultiHostPublisher.php deleted file mode 100644 index 18383162..00000000 --- a/code/staticpublisher/RsyncMultiHostPublisher.php +++ /dev/null @@ -1,63 +0,0 @@ -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; - } - -} - diff --git a/code/staticpublisher/htaccess_example_rsyncmultiservers b/code/staticpublisher/htaccess_example_rsyncmultiservers deleted file mode 100644 index b7aefcfe..00000000 --- a/code/staticpublisher/htaccess_example_rsyncmultiservers +++ /dev/null @@ -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] \ No newline at end of file diff --git a/code/staticpublisher/htaccess_example_rsyncsingleserver b/code/staticpublisher/htaccess_example_rsyncsingleserver deleted file mode 100644 index 8a22bd22..00000000 --- a/code/staticpublisher/htaccess_example_rsyncsingleserver +++ /dev/null @@ -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 ### diff --git a/code/staticpublisher/htaccess_example_rsyncwithphp b/code/staticpublisher/htaccess_example_rsyncwithphp deleted file mode 100644 index 2cc4943e..00000000 --- a/code/staticpublisher/htaccess_example_rsyncwithphp +++ /dev/null @@ -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] \ No newline at end of file diff --git a/tasks/RebuildStaticCacheTask.php b/tasks/RebuildStaticCacheTask.php deleted file mode 100644 index c3064340..00000000 --- a/tasks/RebuildStaticCacheTask.php +++ /dev/null @@ -1,126 +0,0 @@ -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 "
\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 "
\n";
-		print_r($urls);
-		echo "\n
"; - } -} diff --git a/tests/staticpublisher/FilesystemPublisherTest.php b/tests/staticpublisher/FilesystemPublisherTest.php deleted file mode 100644 index 5cb25c19..00000000 --- a/tests/staticpublisher/FilesystemPublisherTest.php +++ /dev/null @@ -1,160 +0,0 @@ -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'); - - - } - -} From cbd31e3ab2470987adfa3574ca391322f7be50f3 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 21 Sep 2012 11:31:00 +0200 Subject: [PATCH 2/2] API Removed SiteTree.MetaTitle and MetaKeywords They are irrelevant in terms of SEO, general page informancy, clutter up the CMS UI, and encourage CMS authors to waste their time filling them out. [1] http://www.seomoz.org/learn-seo/title-tag [2] http://www.mattcutts.com/blog/keywords-meta-tag-in-web-search/ --- code/model/RedirectorPage.php | 2 - code/model/SiteTree.php | 43 +++++++++------------- tests/controller/CMSSiteTreeFilterTest.php | 4 +- tests/model/SiteTreeTest.php | 8 ++-- 4 files changed, 23 insertions(+), 34 deletions(-) diff --git a/code/model/RedirectorPage.php b/code/model/RedirectorPage.php index 6378bee0..2c55fbc2 100644 --- a/code/model/RedirectorPage.php +++ b/code/model/RedirectorPage.php @@ -121,8 +121,6 @@ class RedirectorPage extends Page { // Remove all metadata fields, does not apply for redirector pages $fields->removeByName('MetaTagsHeader'); - $fields->removeByName('MetaTitle'); - $fields->removeByName('MetaKeywords'); $fields->removeByName('MetaDescription'); $fields->removeByName('ExtraMeta'); diff --git a/code/model/SiteTree.php b/code/model/SiteTree.php index 38608d7c..261fdcfc 100644 --- a/code/model/SiteTree.php +++ b/code/model/SiteTree.php @@ -76,9 +76,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid "Title" => "Varchar(255)", "MenuTitle" => "Varchar(100)", "Content" => "HTMLText", - "MetaTitle" => "Varchar(255)", "MetaDescription" => "Text", - "MetaKeywords" => "Varchar(255)", "ExtraMeta" => "HTMLText", "ShowInMenus" => "Boolean", "ShowInSearch" => "Boolean", @@ -1268,18 +1266,13 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid public function MetaTags($includeTitle = true) { $tags = ""; if($includeTitle === true || $includeTitle == 'true') { - $tags .= "" . Convert::raw2xml(($this->MetaTitle) - ? $this->MetaTitle - : $this->Title) . "\n"; + $tags .= "" . $this->Title . "\n"; } $tags .= "\n"; $charset = ContentNegotiator::get_encoding(); $tags .= "\n"; - if($this->MetaKeywords) { - $tags .= "MetaKeywords) . "\" />\n"; - } if($this->MetaDescription) { $tags .= "MetaDescription) . "\" />\n"; } @@ -1852,11 +1845,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid $htmlField = new HtmlEditorField("Content", _t('SiteTree.HTMLEDITORTITLE', "Content", 'HTML editor title')), ToggleCompositeField::create('Metadata', _t('SiteTree.MetadataToggle', 'Metadata'), array( - $metaIntroField = new CompositeField( - $metaIntro = new LabelField("MetaIntro", $Title = "Metadata helps describe and categorise your site. By filling out the fields below it will help improve your site's ranking on search engines.") - ), - $metaFieldTitle = new TextField("MetaTitle", $this->fieldLabel('MetaTitle')), - $metaFieldKeyword = new TextareaField("MetaKeywords", $this->fieldLabel('MetaKeywords'), 1), $metaFieldDesc = new TextareaField("MetaDescription", $this->fieldLabel('MetaDescription')), $metaFieldExtra = new TextareaField("ExtraMeta",$this->fieldLabel('ExtraMeta')) ) @@ -1870,17 +1858,23 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid ); $htmlField->addExtraClass('stacked'); - $metaIntroField->addExtraClass('field'); - $metaIntro->addExtraClass('help'); // Help text for MetaData on page content editor - $metaFieldTitle->setRightTitle(_t('SiteTree.METATITLEHELP', "Add the title of your page here")) - ->addExtraClass('help'); - $metaFieldKeyword->setRightTitle(_t('SiteTree.METAKEYWORDHELP', "Add any keywords that are relevant to the page here. Separate keywords and phrases with a comma: keyword, keywords, keyword phrase")) - ->addExtraClass('help'); - $metaFieldDesc->setRightTitle(_t('SiteTree.METADESCHELP', "Add a description of your page here. Make sure you think about your keywords when writing your description")) - ->addExtraClass('help'); - $metaFieldExtra->setRightTitle(_t('SiteTree.METAEXTRAHELP', "When adding custom meta tags they must be wrapped in an html tag. For example <meta name=\"customName\" content=\"your custom content here\" />")) - ->addExtraClass('help'); + $metaFieldDesc + ->setRightTitle( + _t( + 'SiteTree.METADESCHELP', + "Search engines use this content for displaying search results (although it will not influence their ranking)." + ) + ) + ->addExtraClass('help'); + $metaFieldExtra + ->setRightTitle( + _t( + 'SiteTree.METAEXTRAHELP', + "HTML tags for additional meta information. For example <meta name=\"customName\" content=\"your custom content here\" />" + ) + ) + ->addExtraClass('help'); // Conditional dependent pages tab if($dependentPagesCount) $tabDependent->setTitle(_t('SiteTree.TABDEPENDENT', "Dependent pages") . " ($dependentPagesCount)"); @@ -2036,10 +2030,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid $labels = parent::fieldLabels($includerelations); $labels['Title'] = _t('SiteTree.PAGETITLE', "Page name"); $labels['MenuTitle'] = _t('SiteTree.MENUTITLE', "Navigation label"); - $labels['MetaIntro'] = _t('SiteTree.METAINTRO', "Metadata helps describe and categorise your site. By filling out the fields below it will help improve your site's ranking on search engines."); - $labels['MetaTitle'] = _t('SiteTree.METATITLE', "Meta Title"); $labels['MetaDescription'] = _t('SiteTree.METADESC', "Meta Description"); - $labels['MetaKeywords'] = _t('SiteTree.METAKEYWORDS', "Meta Keywords"); $labels['ExtraMeta'] = _t('SiteTree.METAEXTRA', "Custom Meta Tags"); $labels['ClassName'] = _t('SiteTree.PAGETYPE', "Page type", 'Classname of a page object'); $labels['ParentType'] = _t('SiteTree.PARENTTYPE', "Page location"); diff --git a/tests/controller/CMSSiteTreeFilterTest.php b/tests/controller/CMSSiteTreeFilterTest.php index 110349e0..2e3c79bc 100644 --- a/tests/controller/CMSSiteTreeFilterTest.php +++ b/tests/controller/CMSSiteTreeFilterTest.php @@ -51,9 +51,9 @@ class CMSSiteTreeFilterTest extends SapphireTest { $unchangedPage->doPublish(); $changedPage = $this->objFromFixture('Page', 'page2'); - $changedPage->MetaTitle = 'Original'; + $changedPage->Title = 'Original'; $changedPage->publish('Stage', 'Live'); - $changedPage->MetaTitle = 'Changed'; + $changedPage->Title = 'Changed'; $changedPage->write(); $f = new CMSSiteTreeFilter_ChangedPages(); diff --git a/tests/model/SiteTreeTest.php b/tests/model/SiteTreeTest.php index 5f007040..70855809 100644 --- a/tests/model/SiteTreeTest.php +++ b/tests/model/SiteTreeTest.php @@ -136,17 +136,17 @@ class SiteTreeTest extends SapphireTest { $this->logInWithPermission('ADMIN'); $obj = $this->objFromFixture('Page', 'about'); - $obj->MetaTitle = "asdfasdf"; + $obj->Title = "asdfasdf"; $obj->write(); $this->assertTrue($obj->doPublish()); - $this->assertEquals('asdfasdf', DB::query("SELECT \"MetaTitle\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value()); + $this->assertEquals('asdfasdf', DB::query("SELECT \"Title\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value()); - $obj->MetaTitle = null; + $obj->Title = null; $obj->write(); $this->assertTrue($obj->doPublish()); - $this->assertNull(DB::query("SELECT \"MetaTitle\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value()); + $this->assertNull(DB::query("SELECT \"Title\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value()); }