From 9c4c3eef2ee74c8b6944f1b01dd320ff5848e08f Mon Sep 17 00:00:00 2001 From: Saophalkun Ponlu Date: Thu, 29 Apr 2010 05:48:48 +0000 Subject: [PATCH] BUGFIX: static publisher for a site that resides in a subfolder of webroot git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/branches/2.4@103745 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- code/staticpublisher/FilesystemPublisher.php | 76 +++++++++++++++--- tests/FilesystemPublisherTest.php | 81 ++++++++++++++++++++ 2 files changed, 147 insertions(+), 10 deletions(-) diff --git a/code/staticpublisher/FilesystemPublisher.php b/code/staticpublisher/FilesystemPublisher.php index 8548be40..27ed61da 100644 --- a/code/staticpublisher/FilesystemPublisher.php +++ b/code/staticpublisher/FilesystemPublisher.php @@ -1,7 +1,11 @@ pagesAffectedByUnpublishing() to return other URLS * that should be de-cached if $page is unpublished. @@ -12,14 +16,27 @@ * @subpackage publishers */ class FilesystemPublisher extends StaticPublisher { - protected $destFolder; + + /** + * @var String + */ + protected $destFolder = 'cache'; + + /** + * @var String + */ protected $fileExtension = 'html'; + /** + * @var String + */ protected static $static_base_url = null; /** - * Use domain based cacheing (put cache files into a domain subfolder) - * This must be true if you are using this with subsites. + * @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; @@ -32,25 +49,57 @@ class FilesystemPublisher extends StaticPublisher { } /** - * @param $destFolder The folder to save the cached site into - * @param $fileExtension The file extension to use, for example, '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 + * @param $destFolder The folder to save the cached site into. + * This needs to be set in sapphire/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, $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 + * sapphire/static-main.php. Does not include the {@link $destFolder} prefix. + * Replaces various special characters in the resulting filename similar to {@link SiteTree::generateURLSegment()}. + * + * 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) { $urlParts = @parse_url($url); - $urlParts['path'] = isset($urlParts['path']) ? $urlParts['path'] : ''; + + // 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(substr(strtolower($path), 0, strlen(BASE_URL)) == strtolower(BASE_URL)) { + $urlSegment = substr($path, strlen(BASE_URL)); + } else { + $urlSegment = $path; + } + // perform similar transformations to SiteTree::generateURLSegment() - $urlSegment = $urlParts['path']; $urlSegment = str_replace('&','-and-',$urlSegment); $urlSegment = str_replace('&','-and-',$urlSegment); $urlSegment = ereg_replace('[^A-Za-z0-9\/-]+','-',$urlSegment); @@ -114,7 +163,9 @@ class FilesystemPublisher extends StaticPublisher { $files = array(); $i = 0; $totalURLs = sizeof($urls); + foreach($urls as $url => $path) { + if(self::$static_base_url) Director::setBaseURL(self::$static_base_url); $i++; @@ -129,9 +180,14 @@ class FilesystemPublisher extends StaticPublisher { } Requirements::clear(); + + if(Director::is_relative_url($url)) $url = Director::absoluteURL($url); $response = Director::test(str_replace('+', ' ', $url)); + Requirements::clear(); + + singleton('DataObject')->flushCache(); // Generate file content diff --git a/tests/FilesystemPublisherTest.php b/tests/FilesystemPublisherTest.php index 49e9cf05..9504e031 100644 --- a/tests/FilesystemPublisherTest.php +++ b/tests/FilesystemPublisherTest.php @@ -9,20 +9,101 @@ class FilesystemPublisherTest extends SapphireTest { protected $usesDatabase = true; + protected $orig = array(); + function setUp() { parent::setUp(); Object::add_extension("SiteTree", "FilesystemPublisher('../FilesystemPublisherTest-static-folder/')"); SiteTree::$write_homepage_map = false; + + $this->orig['domain_based_caching'] = FilesystemPublisher::$domain_based_caching; + FilesystemPublisher::$domain_based_caching = false; } function tearDown() { Object::remove_extension("SiteTree", "FilesystemPublisher('../FilesystemPublisherTest-static-folder/')"); SiteTree::$write_homepage_map = true; + FilesystemPublisher::$domain_based_caching = $this->orig['domain_based_caching']; + parent::tearDown(); } + 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() { + 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' + ); + } + /** * Simple test to ensure that FileSystemPublisher::__construct() * has called parent::__construct() by checking the class property.