mirror of
https://github.com/silverstripe/silverstripe-staticpublisher
synced 2024-10-22 14:05:54 +02:00
Merge pull request #51 from helpfulrobot/convert-to-psr-2
Converted to PSR-2
This commit is contained in:
commit
1a37a8033a
@ -14,250 +14,260 @@
|
|||||||
*
|
*
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class StaticExporter extends Controller {
|
class StaticExporter extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var array $export_objects
|
* @var array $export_objects
|
||||||
*/
|
*/
|
||||||
private static $export_objects = array();
|
private static $export_objects = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
private static $disable_sitetree_export = false;
|
private static $disable_sitetree_export = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $allowed_actions = array(
|
private static $allowed_actions = array(
|
||||||
'index',
|
'index',
|
||||||
'export',
|
'export',
|
||||||
'StaticExportForm'
|
'StaticExportForm'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function __construct() {
|
public function __construct()
|
||||||
parent::__construct();
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
if(class_exists('SiteTree')) {
|
if (class_exists('SiteTree')) {
|
||||||
if(!$this->config()->get('disable_sitetree_export')) {
|
if (!$this->config()->get('disable_sitetree_export')) {
|
||||||
$objs = $this->config()->export_objects;
|
$objs = $this->config()->export_objects;
|
||||||
if (!is_array($objs)) {
|
if (!is_array($objs)) {
|
||||||
$objs = array($objs);
|
$objs = array($objs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!in_array('SiteTree', $objs)) {
|
if (!in_array('SiteTree', $objs)) {
|
||||||
$objs[] = "SiteTree";
|
$objs[] = "SiteTree";
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->config()->export_objects = $objs;
|
$this->config()->export_objects = $objs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function init() {
|
public function init()
|
||||||
parent::init();
|
{
|
||||||
|
parent::init();
|
||||||
$canAccess = (Director::isDev() || Director::is_cli());
|
|
||||||
|
$canAccess = (Director::isDev() || Director::is_cli());
|
||||||
|
|
||||||
if(!Permission::check("ADMIN") && !$canAccess) {
|
if (!Permission::check("ADMIN") && !$canAccess) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $action
|
* @param string $action
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function Link($action = null) {
|
public function Link($action = null)
|
||||||
return "dev/staticexporter/$action";
|
{
|
||||||
}
|
return "dev/staticexporter/$action";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $action
|
* @param string $action
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function AbsoluteLink($action = null) {
|
public function AbsoluteLink($action = null)
|
||||||
return Director::absoluteURL($this->Link($action));
|
{
|
||||||
}
|
return Director::absoluteURL($this->Link($action));
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @return array
|
/**
|
||||||
*/
|
* @return array
|
||||||
public function index() {
|
*/
|
||||||
return array(
|
public function index()
|
||||||
'Title' => _t('StaticExporter.NAME','Static exporter'),
|
{
|
||||||
'Form' => $this->StaticExportForm()->forTemplate()
|
return array(
|
||||||
);
|
'Title' => _t('StaticExporter.NAME', 'Static exporter'),
|
||||||
}
|
'Form' => $this->StaticExportForm()->forTemplate()
|
||||||
|
);
|
||||||
/**
|
}
|
||||||
* @return Form
|
|
||||||
*/
|
/**
|
||||||
public function StaticExportForm() {
|
* @return Form
|
||||||
$form = new Form($this, 'StaticExportForm', new FieldList(
|
*/
|
||||||
new TextField('baseurl', _t('StaticExporter.BASEURL','Base URL'))
|
public function StaticExportForm()
|
||||||
), new FieldList(
|
{
|
||||||
new FormAction('export', _t('StaticExporter.EXPORT','Export'))
|
$form = new Form($this, 'StaticExportForm', new FieldList(
|
||||||
));
|
new TextField('baseurl', _t('StaticExporter.BASEURL', 'Base URL'))
|
||||||
|
), new FieldList(
|
||||||
|
new FormAction('export', _t('StaticExporter.EXPORT', 'Export'))
|
||||||
|
));
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function export() {
|
public function export()
|
||||||
if(isset($_REQUEST['baseurl'])) {
|
{
|
||||||
$base = $_REQUEST['baseurl'];
|
if (isset($_REQUEST['baseurl'])) {
|
||||||
|
$base = $_REQUEST['baseurl'];
|
||||||
|
|
||||||
if(substr($base,-1) != '/') $base .= '/';
|
if (substr($base, -1) != '/') {
|
||||||
|
$base .= '/';
|
||||||
|
}
|
||||||
|
|
||||||
Config::inst()->update('Director', 'alternate_base_url', $base);
|
Config::inst()->update('Director', 'alternate_base_url', $base);
|
||||||
}
|
} else {
|
||||||
else {
|
$base = Director::baseURL();
|
||||||
$base = Director::baseURL();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$folder = TEMP_FOLDER . '/static-export';
|
$folder = TEMP_FOLDER . '/static-export';
|
||||||
$project = project();
|
$project = project();
|
||||||
|
|
||||||
$exported = $this->doExport($base, $folder .'/'. $project, false);
|
$exported = $this->doExport($base, $folder .'/'. $project, false);
|
||||||
|
|
||||||
`cd $folder; tar -czhf $project-export.tar.gz $project`;
|
`cd $folder; tar -czhf $project-export.tar.gz $project`;
|
||||||
|
|
||||||
$archiveContent = file_get_contents("$folder/$project-export.tar.gz");
|
$archiveContent = file_get_contents("$folder/$project-export.tar.gz");
|
||||||
|
|
||||||
|
|
||||||
// return as download to the client
|
// return as download to the client
|
||||||
$response = SS_HTTPRequest::send_file(
|
$response = SS_HTTPRequest::send_file(
|
||||||
$archiveContent,
|
$archiveContent,
|
||||||
"$project-export.tar.gz",
|
"$project-export.tar.gz",
|
||||||
'application/x-tar-gz'
|
'application/x-tar-gz'
|
||||||
);
|
);
|
||||||
|
|
||||||
echo $response->output();
|
echo $response->output();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports the website with the given base url. Returns the path where the
|
* Exports the website with the given base url. Returns the path where the
|
||||||
* exported version of the website is located.
|
* exported version of the website is located.
|
||||||
*
|
*
|
||||||
* @param string website base url
|
* @param string website base url
|
||||||
* @param string folder to export the site into
|
* @param string folder to export the site into
|
||||||
* @param bool symlink assets
|
* @param bool symlink assets
|
||||||
* @param bool suppress output progress
|
* @param bool suppress output progress
|
||||||
*
|
*
|
||||||
* @return string path to export
|
* @return string path to export
|
||||||
*/
|
*/
|
||||||
public function doExport($base, $folder, $symlink = true, $quiet = true) {
|
public function doExport($base, $folder, $symlink = true, $quiet = true)
|
||||||
ini_set('max_execution_time', 0);
|
{
|
||||||
|
ini_set('max_execution_time', 0);
|
||||||
|
|
||||||
Config::inst()->update('Director', 'alternate_base_url', $base);
|
Config::inst()->update('Director', 'alternate_base_url', $base);
|
||||||
|
|
||||||
if(is_dir($folder)) {
|
if (is_dir($folder)) {
|
||||||
Filesystem::removeFolder($folder);
|
Filesystem::removeFolder($folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Filesystem::makeFolder($folder);
|
Filesystem::makeFolder($folder);
|
||||||
|
|
||||||
// symlink or copy /assets
|
// symlink or copy /assets
|
||||||
$f1 = ASSETS_PATH;
|
$f1 = ASSETS_PATH;
|
||||||
$f2 = Director::baseFolder() . '/' . project();
|
$f2 = Director::baseFolder() . '/' . project();
|
||||||
|
|
||||||
if($symlink) {
|
if ($symlink) {
|
||||||
`cd $folder; ln -s $f1; ln -s $f2`;
|
`cd $folder; ln -s $f1; ln -s $f2`;
|
||||||
}
|
} else {
|
||||||
else {
|
`cp -R $f1 $folder; cp -R $f2 $folder`;
|
||||||
`cp -R $f1 $folder; cp -R $f2 $folder`;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// iterate through items we need to export
|
// iterate through items we need to export
|
||||||
$urls = $this->getExportUrls();
|
$urls = $this->getExportUrls();
|
||||||
|
|
||||||
if($urls) {
|
if ($urls) {
|
||||||
$total = count($urls);
|
$total = count($urls);
|
||||||
$i = 1;
|
$i = 1;
|
||||||
|
|
||||||
foreach($urls as $url) {
|
foreach ($urls as $url) {
|
||||||
$subfolder = "$folder/" . trim($url, '/');
|
$subfolder = "$folder/" . trim($url, '/');
|
||||||
$contentfile = "$folder/" . trim($url, '/') . '/index.html';
|
$contentfile = "$folder/" . trim($url, '/') . '/index.html';
|
||||||
|
|
||||||
// Make the folder
|
// Make the folder
|
||||||
if(!file_exists($subfolder)) {
|
if (!file_exists($subfolder)) {
|
||||||
Filesystem::makeFolder($subfolder);
|
Filesystem::makeFolder($subfolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the page
|
// Run the page
|
||||||
Requirements::clear();
|
Requirements::clear();
|
||||||
DataObject::flush_and_destroy_cache();
|
DataObject::flush_and_destroy_cache();
|
||||||
|
|
||||||
$response = Director::test($url);
|
$response = Director::test($url);
|
||||||
|
|
||||||
// Write to file
|
// Write to file
|
||||||
if($fh = fopen($contentfile, 'w')) {
|
if ($fh = fopen($contentfile, 'w')) {
|
||||||
if(!$quiet) {
|
if (!$quiet) {
|
||||||
printf("-- (%s/%s) Outputting page (%s)%s",
|
printf("-- (%s/%s) Outputting page (%s)%s",
|
||||||
$i,
|
$i,
|
||||||
$total,
|
$total,
|
||||||
$url,
|
$url,
|
||||||
PHP_EOL
|
PHP_EOL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite($fh, $response->getBody());
|
fwrite($fh, $response->getBody());
|
||||||
fclose($fh);
|
fclose($fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $folder;
|
return $folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of urls to publish
|
* Return an array of urls to publish
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getExportUrls() {
|
public function getExportUrls()
|
||||||
$classes = $this->config()->get('export_objects');
|
{
|
||||||
$urls = array();
|
$classes = $this->config()->get('export_objects');
|
||||||
|
$urls = array();
|
||||||
|
|
||||||
foreach($classes as $obj) {
|
foreach ($classes as $obj) {
|
||||||
if (!class_exists($obj)) {
|
if (!class_exists($obj)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
foreach ($obj::get() as $objInstance) {
|
foreach ($obj::get() as $objInstance) {
|
||||||
$link = $objInstance->Link();
|
$link = $objInstance->Link();
|
||||||
$urls[$link] = $link;
|
$urls[$link] = $link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extend('alterExportUrls', $urls);
|
$this->extend('alterExportUrls', $urls);
|
||||||
|
|
||||||
// older api, keep around to ensure backwards compatibility
|
// older api, keep around to ensure backwards compatibility
|
||||||
$objs = new ArrayList();
|
$objs = new ArrayList();
|
||||||
$this->extend('alterObjectsToExport', $objs);
|
$this->extend('alterObjectsToExport', $objs);
|
||||||
|
|
||||||
if($objs) {
|
if ($objs) {
|
||||||
foreach($objs as $obj) {
|
foreach ($objs as $obj) {
|
||||||
$link = $obj->Link;
|
$link = $obj->Link;
|
||||||
|
|
||||||
$urls[$link] = $link;
|
$urls[$link] = $link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $urls;
|
return $urls;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,409 +3,432 @@
|
|||||||
/**
|
/**
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class FilesystemPublisher extends StaticPublisher {
|
class FilesystemPublisher extends StaticPublisher
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $destFolder = 'cache';
|
protected $destFolder = 'cache';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $fileExtension = 'html';
|
protected $fileExtension = 'html';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @config
|
* @config
|
||||||
*/
|
*/
|
||||||
private static $static_base_url = null;
|
private static $static_base_url = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var Boolean Use domain based cacheing (put cache files into a domain subfolder)
|
* @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.
|
* 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
|
* Please note that this form of caching requires all URLs to be provided absolute
|
||||||
* (not relative to the webroot) via {@link SiteTree->AbsoluteLink()}.
|
* (not relative to the webroot) via {@link SiteTree->AbsoluteLink()}.
|
||||||
*/
|
*/
|
||||||
private static $domain_based_caching = false;
|
private static $domain_based_caching = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a different base URL for the static copy of the site.
|
* 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.
|
* This can be useful if you are running the CMS on a different domain from the website.
|
||||||
*
|
*
|
||||||
* @deprecated 3.2 Use the "FilesystemPublisher.static_base_url" config setting instead
|
* @deprecated 3.2 Use the "FilesystemPublisher.static_base_url" config setting instead
|
||||||
*/
|
*/
|
||||||
static public function set_static_base_url($url) {
|
public static function set_static_base_url($url)
|
||||||
Deprecation::notice('3.2', 'Use the "FilesystemPublisher.static_base_url" config setting instead');
|
{
|
||||||
|
Deprecation::notice('3.2', 'Use the "FilesystemPublisher.static_base_url" config setting instead');
|
||||||
|
|
||||||
Config::inst()->update('FilesystemPublisher', 'static_base_url', $url);
|
Config::inst()->update('FilesystemPublisher', 'static_base_url', $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $destFolder The folder to save the cached site into.
|
* @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.
|
* 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'.
|
* @param $fileExtension The file extension to use, e.g 'html'.
|
||||||
* If omitted, then each page will be placed in its own directory,
|
* 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
|
* 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.
|
* be generated that can do appropriate cache & redirect header negotation.
|
||||||
*/
|
*/
|
||||||
public function __construct($destFolder = 'cache', $fileExtension = null) {
|
public function __construct($destFolder = 'cache', $fileExtension = null)
|
||||||
// Remove trailing slash from folder
|
{
|
||||||
if(substr($destFolder, -1) == '/') {
|
// Remove trailing slash from folder
|
||||||
$destFolder = substr($destFolder, 0, -1);
|
if (substr($destFolder, -1) == '/') {
|
||||||
}
|
$destFolder = substr($destFolder, 0, -1);
|
||||||
|
}
|
||||||
$this->destFolder = $destFolder;
|
|
||||||
|
|
||||||
if($fileExtension) {
|
|
||||||
$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}).
|
|
||||||
*/
|
|
||||||
public 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 (Config::inst()->get('FilesystemPublisher', 'domain_based_caching')) {
|
|
||||||
if (!$urlParts) continue; // seriously malformed url here...
|
|
||||||
$filename = $urlParts['host'] . '/' . $filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mappedUrls[$url] = ((dirname($filename) == '/') ? '' : (dirname($filename).'/')).basename($filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $mappedUrls;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $urls
|
|
||||||
*/
|
|
||||||
public 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses {@link Director::test()} to perform in-memory HTTP requests
|
|
||||||
* on the passed-in URLs.
|
|
||||||
*
|
|
||||||
* @param array $urls Relative URLs
|
|
||||||
* @return array Result, keyed by URL. Keys:
|
|
||||||
* - "statuscode": The HTTP status code
|
|
||||||
* - "redirect": A redirect location (if applicable)
|
|
||||||
* - "path": The filesystem path where the cache has been written
|
|
||||||
*/
|
|
||||||
public function publishPages($urls) {
|
|
||||||
// Save current stage and temporarily force it to Live
|
|
||||||
$oldStage = Versioned::current_stage();
|
|
||||||
Versioned::reading_stage("Live");
|
|
||||||
|
|
||||||
$result = array();
|
$this->destFolder = $destFolder;
|
||||||
|
|
||||||
//nest the config so we can make changes to the config and revert easily
|
if ($fileExtension) {
|
||||||
Config::nest();
|
$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}).
|
||||||
|
*/
|
||||||
|
public function urlsToPaths($urls)
|
||||||
|
{
|
||||||
|
$mappedUrls = array();
|
||||||
|
|
||||||
|
foreach ($urls as $url) {
|
||||||
|
|
||||||
// Do we need to map these?
|
// parse_url() is not multibyte safe, see https://bugs.php.net/bug.php?id=52923.
|
||||||
// Detect a numerically indexed arrays
|
// We assume that the URL hsa been correctly encoded either on storage (for SiteTree->URLSegment),
|
||||||
if (is_numeric(join('', array_keys($urls)))) $urls = $this->urlsToPaths($urls);
|
// or through URL collection (for controller method names etc.).
|
||||||
|
$urlParts = @parse_url($url);
|
||||||
// This can be quite memory hungry and time-consuming
|
|
||||||
// @todo - Make a more memory efficient publisher
|
// Remove base folders from the URL if webroot is hosted in a subfolder (same as static-main.php)
|
||||||
increase_time_limit_to();
|
$path = isset($urlParts['path']) ? $urlParts['path'] : '';
|
||||||
increase_memory_limit_to();
|
if (mb_substr(mb_strtolower($path), 0, mb_strlen(BASE_URL)) == mb_strtolower(BASE_URL)) {
|
||||||
|
$urlSegment = mb_substr($path, mb_strlen(BASE_URL));
|
||||||
// Set the appropriate theme for this publication batch.
|
} else {
|
||||||
// This may have been set explicitly via StaticPublisher::static_publisher_theme,
|
$urlSegment = $path;
|
||||||
// or we can use the last non-null theme.
|
}
|
||||||
$customTheme = Config::inst()->get('StaticPublisher', 'static_publisher_theme');
|
|
||||||
|
|
||||||
if($customTheme) {
|
// Normalize URLs
|
||||||
Config::inst()->update('SSViewer', 'theme', $customTheme);
|
$urlSegment = trim($urlSegment, '/');
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that the theme that is set gets used.
|
$filename = $urlSegment ? "$urlSegment.$this->fileExtension" : "index.$this->fileExtension";
|
||||||
Config::inst()->update('SSViewer', 'theme_enabled', true);
|
|
||||||
|
|
||||||
$staticBaseUrl = Config::inst()->get('FilesystemPublisher', 'static_base_url');
|
|
||||||
|
|
||||||
if($staticBaseUrl) {
|
|
||||||
Config::inst()->update('Director', 'alternate_base_url', $staticBaseUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->fileExtension == 'php') {
|
|
||||||
Config::inst()->update('SSViewer', 'rewrite_hash_links', 'php');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Config::inst()->get('StaticPublisher', 'echo_progress')) {
|
|
||||||
echo $this->class.": Publishing to " . $staticBaseUrl . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = array();
|
|
||||||
$i = 0;
|
|
||||||
$totalURLs = sizeof($urls);
|
|
||||||
|
|
||||||
foreach($urls as $url => $path) {
|
if (Config::inst()->get('FilesystemPublisher', 'domain_based_caching')) {
|
||||||
$origUrl = $url;
|
if (!$urlParts) {
|
||||||
$result[$origUrl] = array(
|
continue;
|
||||||
'statuscode' => null,
|
} // seriously malformed url here...
|
||||||
'redirect' => null,
|
$filename = $urlParts['host'] . '/' . $filename;
|
||||||
'path' => null
|
}
|
||||||
);
|
|
||||||
|
$mappedUrls[$url] = ((dirname($filename) == '/') ? '' : (dirname($filename).'/')).basename($filename);
|
||||||
|
}
|
||||||
|
|
||||||
$i++;
|
return $mappedUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $urls
|
||||||
|
*/
|
||||||
|
public 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses {@link Director::test()} to perform in-memory HTTP requests
|
||||||
|
* on the passed-in URLs.
|
||||||
|
*
|
||||||
|
* @param array $urls Relative URLs
|
||||||
|
* @return array Result, keyed by URL. Keys:
|
||||||
|
* - "statuscode": The HTTP status code
|
||||||
|
* - "redirect": A redirect location (if applicable)
|
||||||
|
* - "path": The filesystem path where the cache has been written
|
||||||
|
*/
|
||||||
|
public function publishPages($urls)
|
||||||
|
{
|
||||||
|
// Save current stage and temporarily force it to Live
|
||||||
|
$oldStage = Versioned::current_stage();
|
||||||
|
Versioned::reading_stage("Live");
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
|
||||||
if($url && !is_string($url)) {
|
//nest the config so we can make changes to the config and revert easily
|
||||||
user_error("Bad url:" . var_export($url,true), E_USER_WARNING);
|
Config::nest();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Config::inst()->get('StaticPublisher', 'echo_progress')) {
|
|
||||||
echo " * Publishing page $i/$totalURLs: $url\n";
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
Requirements::clear();
|
// Do we need to map these?
|
||||||
|
// Detect a numerically indexed arrays
|
||||||
if($url == "") $url = "/";
|
if (is_numeric(join('', array_keys($urls)))) {
|
||||||
if(Director::is_relative_url($url)) $url = Director::absoluteURL($url);
|
$urls = $this->urlsToPaths($urls);
|
||||||
$response = Director::test(str_replace('+', ' ', $url));
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
$customTheme = Config::inst()->get('StaticPublisher', 'static_publisher_theme');
|
||||||
|
|
||||||
if (!$response) continue;
|
if ($customTheme) {
|
||||||
|
Config::inst()->update('SSViewer', 'theme', $customTheme);
|
||||||
|
}
|
||||||
|
|
||||||
if($response) {
|
// Ensure that the theme that is set gets used.
|
||||||
$result[$origUrl]['statuscode'] = $response->getStatusCode();
|
Config::inst()->update('SSViewer', 'theme_enabled', true);
|
||||||
}
|
|
||||||
Requirements::clear();
|
$staticBaseUrl = Config::inst()->get('FilesystemPublisher', 'static_base_url');
|
||||||
|
|
||||||
singleton('DataObject')->flushCache();
|
if ($staticBaseUrl) {
|
||||||
|
Config::inst()->update('Director', 'alternate_base_url', $staticBaseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->fileExtension == 'php') {
|
||||||
|
Config::inst()->update('SSViewer', 'rewrite_hash_links', 'php');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config::inst()->get('StaticPublisher', 'echo_progress')) {
|
||||||
|
echo $this->class.": Publishing to " . $staticBaseUrl . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = array();
|
||||||
|
$i = 0;
|
||||||
|
$totalURLs = sizeof($urls);
|
||||||
|
|
||||||
// Check for ErrorPages generating output - we want to handle this in a special way below.
|
foreach ($urls as $url => $path) {
|
||||||
$isErrorPage = false;
|
$origUrl = $url;
|
||||||
$pageObject = null;
|
$result[$origUrl] = array(
|
||||||
if ($response && is_object($response) && ((int)$response->getStatusCode())>=400) {
|
'statuscode' => null,
|
||||||
$pageObject = SiteTree::get_by_link($url);
|
'redirect' => null,
|
||||||
if ($pageObject && $pageObject instanceof ErrorPage) $isErrorPage = true;
|
'path' => null
|
||||||
}
|
);
|
||||||
|
|
||||||
// Skip any responses with a 404 status code unless it's the ErrorPage itself.
|
$i++;
|
||||||
if (!$isErrorPage && is_object($response) && $response->getStatusCode()=='404') continue;
|
|
||||||
|
|
||||||
// Generate file content
|
if ($url && !is_string($url)) {
|
||||||
// PHP file caching will generate a simple script from a template
|
user_error("Bad url:" . var_export($url, true), E_USER_WARNING);
|
||||||
if($this->fileExtension == 'php') {
|
continue;
|
||||||
if(is_object($response)) {
|
}
|
||||||
if($response->getStatusCode() == '301' || $response->getStatusCode() == '302') {
|
|
||||||
$content = $this->generatePHPCacheRedirection($response->getHeader('Location'));
|
if (Config::inst()->get('StaticPublisher', 'echo_progress')) {
|
||||||
} else {
|
echo " * Publishing page $i/$totalURLs: $url\n";
|
||||||
$content = $this->generatePHPCacheFile($response->getBody(), HTTP::get_cache_age(), date('Y-m-d H:i:s'), $response->getHeader('Content-Type'));
|
flush();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$content = $this->generatePHPCacheFile($response . '', HTTP::get_cache_age(), date('Y-m-d H:i:s'), $response->getHeader('Content-Type'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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'));
|
|
||||||
$result[$origUrl]['redirect'] = $response->getHeader('Location');
|
|
||||||
$content = "<meta http-equiv=\"refresh\" content=\"2; URL=$absoluteURL\">";
|
|
||||||
} else {
|
|
||||||
$content = $response->getBody();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$content = $response . '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Config::inst()->get('StaticPublisher', 'include_caching_metadata')) {
|
|
||||||
$content = str_replace(
|
|
||||||
'</html>',
|
|
||||||
sprintf("</html>\n\n<!-- %s -->", implode(" ", $this->getMetadata($url))),
|
|
||||||
$content
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$isErrorPage) {
|
Requirements::clear();
|
||||||
|
|
||||||
|
if ($url == "") {
|
||||||
|
$url = "/";
|
||||||
|
}
|
||||||
|
if (Director::is_relative_url($url)) {
|
||||||
|
$url = Director::absoluteURL($url);
|
||||||
|
}
|
||||||
|
$response = Director::test(str_replace('+', ' ', $url));
|
||||||
|
|
||||||
$files[$origUrl] = array(
|
if (!$response) {
|
||||||
'Content' => $content,
|
continue;
|
||||||
'Folder' => dirname($path).'/',
|
}
|
||||||
'Filename' => basename($path),
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
if ($response) {
|
||||||
|
$result[$origUrl]['statuscode'] = $response->getStatusCode();
|
||||||
|
}
|
||||||
|
Requirements::clear();
|
||||||
|
|
||||||
|
singleton('DataObject')->flushCache();
|
||||||
|
|
||||||
// Generate a static version of the error page with a standardised name, so they can be plugged
|
// Check for ErrorPages generating output - we want to handle this in a special way below.
|
||||||
// into catch-all webserver statements such as Apache's ErrorDocument.
|
$isErrorPage = false;
|
||||||
$code = (int)$response->getStatusCode();
|
$pageObject = null;
|
||||||
$files[$origUrl] = array(
|
if ($response && is_object($response) && ((int)$response->getStatusCode())>=400) {
|
||||||
'Content' => $content,
|
$pageObject = SiteTree::get_by_link($url);
|
||||||
'Folder' => dirname($path).'/',
|
if ($pageObject && $pageObject instanceof ErrorPage) {
|
||||||
'Filename' => "error-$code.html",
|
$isErrorPage = true;
|
||||||
);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
// Skip any responses with a 404 status code unless it's the ErrorPage itself.
|
||||||
}
|
if (!$isErrorPage && is_object($response) && $response->getStatusCode()=='404') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//return config to its previous state
|
// Generate file content
|
||||||
Config::unnest();
|
// 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'), $response->getHeader('Content-Type'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$content = $this->generatePHPCacheFile($response . '', HTTP::get_cache_age(), date('Y-m-d H:i:s'), $response->getHeader('Content-Type'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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'));
|
||||||
|
$result[$origUrl]['redirect'] = $response->getHeader('Location');
|
||||||
|
$content = "<meta http-equiv=\"refresh\" content=\"2; URL=$absoluteURL\">";
|
||||||
|
} else {
|
||||||
|
$content = $response->getBody();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$content = $response . '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config::inst()->get('StaticPublisher', 'include_caching_metadata')) {
|
||||||
|
$content = str_replace(
|
||||||
|
'</html>',
|
||||||
|
sprintf("</html>\n\n<!-- %s -->", implode(" ", $this->getMetadata($url))),
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$base = BASE_PATH . "/$this->destFolder";
|
if (!$isErrorPage) {
|
||||||
|
$files[$origUrl] = array(
|
||||||
foreach($files as $origUrl => $file) {
|
'Content' => $content,
|
||||||
Filesystem::makeFolder("$base/$file[Folder]");
|
'Folder' => dirname($path).'/',
|
||||||
|
'Filename' => basename($path),
|
||||||
$path = "$base/$file[Folder]$file[Filename]";
|
);
|
||||||
$result[$origUrl]['path'] = $path;
|
} else {
|
||||||
|
|
||||||
if(isset($file['Content'])) {
|
|
||||||
$fh = fopen($path, "w");
|
|
||||||
fwrite($fh, $file['Content']);
|
|
||||||
fclose($fh);
|
|
||||||
} else if(isset($file['Copy'])) {
|
|
||||||
copy($file['Copy'], $path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Revert the stage back to what it was
|
// Generate a static version of the error page with a standardised name, so they can be plugged
|
||||||
Versioned::reading_stage($oldStage);
|
// into catch-all webserver statements such as Apache's ErrorDocument.
|
||||||
|
$code = (int)$response->getStatusCode();
|
||||||
|
$files[$origUrl] = array(
|
||||||
|
'Content' => $content,
|
||||||
|
'Folder' => dirname($path).'/',
|
||||||
|
'Filename' => "error-$code.html",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $result;
|
//return config to its previous state
|
||||||
}
|
Config::unnest();
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the templated content for a PHP script that can serve up the
|
|
||||||
* given piece of content with the given age and expiry.
|
|
||||||
*
|
|
||||||
* @param string $content
|
|
||||||
* @param string $age
|
|
||||||
* @param string $lastModified
|
|
||||||
* @param string $contentType
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function generatePHPCacheFile($content, $age, $lastModified, $contentType) {
|
|
||||||
$template = file_get_contents(STATIC_MODULE_DIR . '/code/CachedPHPPage.tmpl');
|
|
||||||
return str_replace(
|
|
||||||
array('**MAX_AGE**', '**LAST_MODIFIED**', '**CONTENT**', '**CONTENT_TYPE**'),
|
|
||||||
array((int)$age, $lastModified, $content, $contentType),
|
|
||||||
$template
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$base = BASE_PATH . "/$this->destFolder";
|
||||||
* Generate the templated content for a PHP script that can serve up a 301
|
|
||||||
* redirect to the given destination.
|
foreach ($files as $origUrl => $file) {
|
||||||
*
|
Filesystem::makeFolder("$base/$file[Folder]");
|
||||||
* @param string $destination
|
|
||||||
*
|
$path = "$base/$file[Folder]$file[Filename]";
|
||||||
* @return string
|
$result[$origUrl]['path'] = $path;
|
||||||
*/
|
|
||||||
protected function generatePHPCacheRedirection($destination) {
|
if (isset($file['Content'])) {
|
||||||
$template = file_get_contents(STATIC_MODULE_DIR . '/code/CachedPHPRedirection.tmpl');
|
$fh = fopen($path, "w");
|
||||||
|
fwrite($fh, $file['Content']);
|
||||||
|
fclose($fh);
|
||||||
|
} elseif (isset($file['Copy'])) {
|
||||||
|
copy($file['Copy'], $path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return str_replace(
|
// Revert the stage back to what it was
|
||||||
array('**DESTINATION**'),
|
Versioned::reading_stage($oldStage);
|
||||||
array($destination),
|
|
||||||
$template
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getExistingStaticCacheFiles() {
|
|
||||||
$cacheDir = BASE_PATH . '/' . $this->destFolder;
|
|
||||||
|
|
||||||
$urlMapper = array_flip($this->urlsToPaths($this->owner->allPagesToCache()));
|
return $result;
|
||||||
|
}
|
||||||
$output = array();
|
|
||||||
|
/**
|
||||||
// Glob each dir, then glob each one of those
|
* Generate the templated content for a PHP script that can serve up the
|
||||||
foreach(glob("$cacheDir/*", GLOB_ONLYDIR) as $cacheDir) {
|
* given piece of content with the given age and expiry.
|
||||||
foreach(glob($cacheDir.'/*') as $cacheFile) {
|
*
|
||||||
$mapKey = str_replace(BASE_PATH . "/cache/","",$cacheFile);
|
* @param string $content
|
||||||
if(isset($urlMapper[$mapKey])) {
|
* @param string $age
|
||||||
$url = $urlMapper[$mapKey];
|
* @param string $lastModified
|
||||||
$output[$url] = $cacheFile;
|
* @param string $contentType
|
||||||
}
|
*
|
||||||
}
|
* @return string
|
||||||
}
|
*/
|
||||||
|
protected function generatePHPCacheFile($content, $age, $lastModified, $contentType)
|
||||||
return $output;
|
{
|
||||||
}
|
$template = file_get_contents(STATIC_MODULE_DIR . '/code/CachedPHPPage.tmpl');
|
||||||
|
return str_replace(
|
||||||
|
array('**MAX_AGE**', '**LAST_MODIFIED**', '**CONTENT**', '**CONTENT_TYPE**'),
|
||||||
|
array((int)$age, $lastModified, $content, $contentType),
|
||||||
|
$template
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the templated content for a PHP script that can serve up a 301
|
||||||
|
* redirect to the given destination.
|
||||||
|
*
|
||||||
|
* @param string $destination
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function generatePHPCacheRedirection($destination)
|
||||||
|
{
|
||||||
|
$template = file_get_contents(STATIC_MODULE_DIR . '/code/CachedPHPRedirection.tmpl');
|
||||||
|
|
||||||
|
return str_replace(
|
||||||
|
array('**DESTINATION**'),
|
||||||
|
array($destination),
|
||||||
|
$template
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,80 +8,88 @@
|
|||||||
*
|
*
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class RsyncMultiHostPublisher extends FilesystemPublisher {
|
class RsyncMultiHostPublisher extends FilesystemPublisher
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* Array of rsync targets to publish to. These can either be local
|
* Array of rsync targets to publish to. These can either be local
|
||||||
* file names, or scp-style targets, in the form "user@server:path"
|
* file names, or scp-style targets, in the form "user@server:path"
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $targets = array();
|
private static $targets = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $excluded_folders = array();
|
private static $excluded_folders = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the targets to publish to.
|
* Set the targets to publish to.
|
||||||
*
|
*
|
||||||
* If target is an scp-style remote path, no password is accepted - we
|
* 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
|
* assume key-based authentication to be set up on the application server
|
||||||
* initiating the publication.
|
* initiating the publication.
|
||||||
*
|
*
|
||||||
* @deprecated 3.2 Use the "RsyncMultiHostPublisher.targets" config setting instead
|
* @deprecated 3.2 Use the "RsyncMultiHostPublisher.targets" config setting instead
|
||||||
*
|
*
|
||||||
* @param $targets An array of targets to publish to.
|
* @param $targets An array of targets to publish to.
|
||||||
*/
|
*/
|
||||||
public static function set_targets($targets) {
|
public static function set_targets($targets)
|
||||||
Deprecation::notice('3.2', 'Use the "RsyncMultiHostPublisher.targets" config setting instead');
|
{
|
||||||
|
Deprecation::notice('3.2', 'Use the "RsyncMultiHostPublisher.targets" config setting instead');
|
||||||
|
|
||||||
Config::inst()->update('RsyncMultiHostPublisher', 'targets', $targets);
|
Config::inst()->update('RsyncMultiHostPublisher', 'targets', $targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify folders to exclude from the rsync
|
* Specify folders to exclude from the rsync
|
||||||
* For example, you could exclude assets.
|
* For example, you could exclude assets.
|
||||||
*
|
*
|
||||||
* @deprecated 3.2 Use the "RsyncMultiHostPublisher.excluded_folders" config setting instead
|
* @deprecated 3.2 Use the "RsyncMultiHostPublisher.excluded_folders" config setting instead
|
||||||
*/
|
*/
|
||||||
public static function set_excluded_folders($folders) {
|
public static function set_excluded_folders($folders)
|
||||||
Deprecation::notice('3.2', 'Use the "RsyncMultiHostPublisher.excluded_folders" config setting instead');
|
{
|
||||||
|
Deprecation::notice('3.2', 'Use the "RsyncMultiHostPublisher.excluded_folders" config setting instead');
|
||||||
|
|
||||||
Config::inst()->update('RsyncMultiHostPublisher', 'excluded_folders', $folders);
|
Config::inst()->update('RsyncMultiHostPublisher', 'excluded_folders', $folders);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function publishPages($urls) {
|
public function publishPages($urls)
|
||||||
parent::publishPages($urls);
|
{
|
||||||
$base = Director::baseFolder();
|
parent::publishPages($urls);
|
||||||
$framework = FRAMEWORK_DIR;
|
$base = Director::baseFolder();
|
||||||
|
$framework = FRAMEWORK_DIR;
|
||||||
|
|
||||||
// Get variable that can turn off the rsync component of publication
|
// Get variable that can turn off the rsync component of publication
|
||||||
if(isset($_GET['norsync']) && $_GET['norsync']) return;
|
if (isset($_GET['norsync']) && $_GET['norsync']) {
|
||||||
|
return;
|
||||||
$extraArg = "";
|
}
|
||||||
$excludedFolders = Config::inst()->get('RsyncMultiHostPublisher', 'excluded_folders');
|
|
||||||
if($excludedFolders) foreach($excludedFolders as $folder) {
|
$extraArg = "";
|
||||||
$extraArg .= " --exclude " . escapeshellarg($folder);
|
$excludedFolders = Config::inst()->get('RsyncMultiHostPublisher', 'excluded_folders');
|
||||||
}
|
if ($excludedFolders) {
|
||||||
|
foreach ($excludedFolders as $folder) {
|
||||||
$targets = Config::inst()->get('RsyncMultiHostPublisher', 'targets');
|
$extraArg .= " --exclude " . escapeshellarg($folder);
|
||||||
foreach((array)$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
|
$targets = Config::inst()->get('RsyncMultiHostPublisher', 'targets');
|
||||||
$rsyncOutput .= `cd $base; rsync -av -e ssh --exclude '*.svn' --exclude '*~' $extraArg --delete cache $target`;
|
foreach ((array)$targets as $target) {
|
||||||
// Transfer framework/static-main.php to the 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 --delete $framework/static-main.php $target/$framework`;
|
$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
|
||||||
if(Config::inst()->get('StaticPublisher', 'echo_progress')) {
|
$rsyncOutput .= `cd $base; rsync -av -e ssh --exclude '*.svn' --exclude '*~' $extraArg --delete cache $target`;
|
||||||
echo $rsyncOutput;
|
// Transfer framework/static-main.php to the target
|
||||||
}
|
$rsyncOutput .= `cd $base; rsync -av -e ssh --delete $framework/static-main.php $target/$framework`;
|
||||||
}
|
|
||||||
}
|
if (Config::inst()->get('StaticPublisher', 'echo_progress')) {
|
||||||
|
echo $rsyncOutput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,193 +2,205 @@
|
|||||||
/**
|
/**
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
abstract class StaticPublisher extends DataExtension {
|
abstract class StaticPublisher extends DataExtension
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines whether to output information about publishing or not. By
|
* Defines whether to output information about publishing or not. By
|
||||||
* default, this is off, and should be turned on when you want debugging
|
* default, this is off, and should be turned on when you want debugging
|
||||||
* (for example, in a cron task).
|
* (for example, in a cron task).
|
||||||
*
|
*
|
||||||
* @var boolean
|
* @var boolean
|
||||||
*
|
*
|
||||||
* @config
|
* @config
|
||||||
*/
|
*/
|
||||||
private static $echo_progress = false;
|
private static $echo_progress = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Realtime static publishing... the second a page is saved, it is
|
* Realtime static publishing... the second a page is saved, it is
|
||||||
* written to the cache.
|
* written to the cache.
|
||||||
*
|
*
|
||||||
* @var boolean
|
* @var boolean
|
||||||
*
|
*
|
||||||
* @config
|
* @config
|
||||||
*/
|
*/
|
||||||
private static $disable_realtime = false;
|
private static $disable_realtime = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the current static publishing theme, which can be set at any
|
* 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
|
* 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
|
* SSViewer::set_theme() is used. The obvious place to set this is in
|
||||||
* _config.php
|
* _config.php
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @config
|
* @config
|
||||||
*/
|
*/
|
||||||
private static $static_publisher_theme = false;
|
private static $static_publisher_theme = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var boolean includes a timestamp at the bottom of the generated HTML
|
* @var boolean includes a timestamp at the bottom of the generated HTML
|
||||||
* of each file, which can be useful for debugging issues with stale
|
* of each file, which can be useful for debugging issues with stale
|
||||||
* caches etc.
|
* caches etc.
|
||||||
*
|
*
|
||||||
* @config
|
* @config
|
||||||
*/
|
*/
|
||||||
private static $include_caching_metadata = false;
|
private static $include_caching_metadata = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array
|
* @param array
|
||||||
*/
|
*/
|
||||||
abstract function publishPages($pages);
|
abstract public function publishPages($pages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array
|
* @param array
|
||||||
*/
|
*/
|
||||||
abstract function unpublishPages($pages);
|
abstract public function unpublishPages($pages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @param string
|
* @param string
|
||||||
*/
|
*/
|
||||||
public static function set_static_publisher_theme($theme) {
|
public static function set_static_publisher_theme($theme)
|
||||||
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
{
|
||||||
|
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
||||||
|
|
||||||
Config::inst()->update('StaticPublisher', 'static_publisher_theme', $theme);
|
Config::inst()->update('StaticPublisher', 'static_publisher_theme', $theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function static_publisher_theme() {
|
public static function static_publisher_theme()
|
||||||
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
{
|
||||||
|
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
||||||
|
|
||||||
return Config::inst()->get('StaticPublisher', 'static_publisher_theme');
|
return Config::inst()->get('StaticPublisher', 'static_publisher_theme');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function echo_progress() {
|
public static function echo_progress()
|
||||||
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
{
|
||||||
|
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
||||||
|
|
||||||
return Config::inst()->get('StaticPublisher', 'echo_progress');
|
return Config::inst()->get('StaticPublisher', 'echo_progress');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static function set_echo_progress($progress) {
|
public static function set_echo_progress($progress)
|
||||||
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
{
|
||||||
|
Deprecation::notice('1.0', 'Use the new config system. SSViewer.static_publisher_theme');
|
||||||
|
|
||||||
Config::inst()->get('StaticPublisher', 'echo_progress', $progress);
|
Config::inst()->get('StaticPublisher', 'echo_progress', $progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after a page is published.
|
* Called after a page is published.
|
||||||
*
|
*
|
||||||
* @param SiteTree
|
* @param SiteTree
|
||||||
*/
|
*/
|
||||||
public function onAfterPublish($original) {
|
public function onAfterPublish($original)
|
||||||
$this->republish($original);
|
{
|
||||||
}
|
$this->republish($original);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called after link assets have been renamed, and the live site has been
|
/**
|
||||||
* updated, without an actual publish event.
|
* 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.
|
*
|
||||||
*/
|
* Only called if the published content exists and has been modified.
|
||||||
public function onRenameLinkedAsset($original) {
|
*/
|
||||||
$this->republish($original);
|
public function onRenameLinkedAsset($original)
|
||||||
}
|
{
|
||||||
|
$this->republish($original);
|
||||||
public function republish($original) {
|
}
|
||||||
if (Config::inst()->get('StaticPublisher', 'disable_realtime')) {
|
|
||||||
return;
|
public function republish($original)
|
||||||
}
|
{
|
||||||
|
if (Config::inst()->get('StaticPublisher', 'disable_realtime')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$urls = array();
|
$urls = array();
|
||||||
|
|
||||||
if($this->owner->hasMethod('pagesAffectedByChanges')) {
|
if ($this->owner->hasMethod('pagesAffectedByChanges')) {
|
||||||
$urls = $this->owner->pagesAffectedByChanges($original);
|
$urls = $this->owner->pagesAffectedByChanges($original);
|
||||||
} else {
|
} else {
|
||||||
$pages = Versioned::get_by_stage('SiteTree', 'Live', '', '', '', 10);
|
$pages = Versioned::get_by_stage('SiteTree', 'Live', '', '', '', 10);
|
||||||
if($pages) {
|
if ($pages) {
|
||||||
foreach($pages as $page) {
|
foreach ($pages as $page) {
|
||||||
$urls[] = $page->AbsoluteLink();
|
$urls[] = $page->AbsoluteLink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: Similiar to RebuildStaticCacheTask->rebuildCache()
|
// Note: Similiar to RebuildStaticCacheTask->rebuildCache()
|
||||||
foreach($urls as $i => $url) {
|
foreach ($urls as $i => $url) {
|
||||||
if(!is_string($url)) {
|
if (!is_string($url)) {
|
||||||
user_error("Bad URL: " . var_export($url, true), E_USER_WARNING);
|
user_error("Bad URL: " . var_export($url, true), E_USER_WARNING);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove leading slashes from all URLs (apart from the homepage)
|
// Remove leading slashes from all URLs (apart from the homepage)
|
||||||
if(substr($url,-1) == '/' && $url != '/') $url = substr($url,0,-1);
|
if (substr($url, -1) == '/' && $url != '/') {
|
||||||
|
$url = substr($url, 0, -1);
|
||||||
$urls[$i] = $url;
|
}
|
||||||
}
|
|
||||||
|
$urls[$i] = $url;
|
||||||
|
}
|
||||||
|
|
||||||
$urls = array_unique($urls);
|
$urls = array_unique($urls);
|
||||||
|
|
||||||
$legalPages = singleton('Page')->allPagesToCache();
|
$legalPages = singleton('Page')->allPagesToCache();
|
||||||
$urls = array_intersect($urls, $legalPages);
|
$urls = array_intersect($urls, $legalPages);
|
||||||
|
|
||||||
$this->publishPages($urls);
|
$this->publishPages($urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get changes and hook into underlying functionality.
|
* Get changes and hook into underlying functionality.
|
||||||
*/
|
*/
|
||||||
public function onAfterUnpublish($page) {
|
public function onAfterUnpublish($page)
|
||||||
if (Config::inst()->get('StaticPublisher', 'disable_realtime')) {
|
{
|
||||||
return;
|
if (Config::inst()->get('StaticPublisher', 'disable_realtime')) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
// Get the affected URLs
|
|
||||||
if($this->owner->hasMethod('pagesAffectedByUnpublishing')) {
|
// Get the affected URLs
|
||||||
$urls = $this->owner->pagesAffectedByUnpublishing();
|
if ($this->owner->hasMethod('pagesAffectedByUnpublishing')) {
|
||||||
$urls = array_unique($urls);
|
$urls = $this->owner->pagesAffectedByUnpublishing();
|
||||||
} else {
|
$urls = array_unique($urls);
|
||||||
$urls = array($this->owner->AbsoluteLink());
|
} else {
|
||||||
}
|
$urls = array($this->owner->AbsoluteLink());
|
||||||
|
}
|
||||||
$legalPages = singleton('Page')->allPagesToCache();
|
|
||||||
|
$legalPages = singleton('Page')->allPagesToCache();
|
||||||
$urlsToRepublish = array_intersect($urls, $legalPages);
|
|
||||||
$urlsToUnpublish = array_diff($urls, $legalPages);
|
$urlsToRepublish = array_intersect($urls, $legalPages);
|
||||||
|
$urlsToUnpublish = array_diff($urls, $legalPages);
|
||||||
|
|
||||||
$this->unpublishPages($urlsToUnpublish);
|
$this->unpublishPages($urlsToUnpublish);
|
||||||
$this->publishPages($urlsToRepublish);
|
$this->publishPages($urlsToRepublish);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getMetadata($url) {
|
public function getMetadata($url)
|
||||||
return array(
|
{
|
||||||
'Cache generated on ' . date('Y-m-d H:i:s T (O)')
|
return array(
|
||||||
);
|
'Cache generated on ' . date('Y-m-d H:i:s T (O)')
|
||||||
}
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,139 +1,142 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class RebuildStaticCacheTask extends BuildTask {
|
class RebuildStaticCacheTask extends BuildTask
|
||||||
|
{
|
||||||
|
|
||||||
private static $quiet = false;
|
private static $quiet = false;
|
||||||
|
|
||||||
public function run($request) {
|
public function run($request)
|
||||||
if(Config::inst()->get('RebuildStaticCacheTask', 'quiet')) {
|
{
|
||||||
Config::inst()->update('StaticPublisher', 'echo_progress', false);
|
if (Config::inst()->get('RebuildStaticCacheTask', 'quiet')) {
|
||||||
} else {
|
Config::inst()->update('StaticPublisher', 'echo_progress', false);
|
||||||
Config::inst()->update('StaticPublisher', 'echo_progress', true);
|
} else {
|
||||||
}
|
Config::inst()->update('StaticPublisher', 'echo_progress', true);
|
||||||
|
}
|
||||||
$page = singleton('Page');
|
|
||||||
|
$page = singleton('Page');
|
||||||
|
|
||||||
if(!$page->hasMethod('allPagesToCache')) {
|
if (!$page->hasMethod('allPagesToCache')) {
|
||||||
user_error(
|
user_error(
|
||||||
'RebuildStaticCacheTask::index(): Please define a method "allPagesToCache()" on your Page class to return all pages affected by a cache refresh.',
|
'RebuildStaticCacheTask::index(): Please define a method "allPagesToCache()" on your Page class to return all pages affected by a cache refresh.',
|
||||||
E_USER_ERROR
|
E_USER_ERROR
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(!empty($_GET['urls'])) {
|
if (!empty($_GET['urls'])) {
|
||||||
$urls = $_GET['urls'];
|
$urls = $_GET['urls'];
|
||||||
} else {
|
} else {
|
||||||
$urls = $page->allPagesToCache();
|
$urls = $page->allPagesToCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->rebuildCache($urls, true);
|
$this->rebuildCache($urls, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function log($message = null) {
|
public function log($message = null)
|
||||||
$quiet = Config::inst()->get('RebuildStaticCacheTask', 'quiet');
|
{
|
||||||
|
$quiet = Config::inst()->get('RebuildStaticCacheTask', 'quiet');
|
||||||
|
|
||||||
if($quiet) {
|
if ($quiet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo $message;
|
echo $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rebuilds the static cache for the pages passed through via $urls
|
* Rebuilds the static cache for the pages passed through via $urls
|
||||||
*
|
*
|
||||||
* @param array $urls The URLs of pages to re-fetch and cache.
|
* @param array $urls The URLs of pages to re-fetch and cache.
|
||||||
* @param bool $removeAll Remove all stale cache files (default TRUE).
|
* @param bool $removeAll Remove all stale cache files (default TRUE).
|
||||||
*/
|
*/
|
||||||
public function rebuildCache($urls, $removeAll = true) {
|
public 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()) {
|
||||||
|
$this->log("<pre>\n");
|
||||||
|
$this->log("Rebuilding cache.\nNOTE: Please ensure that this page ends with 'Done!' - if not, then something may have gone wrong.\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
if(!is_array($urls)) {
|
$page = singleton('Page');
|
||||||
// $urls must be an array
|
$cacheBaseDir = $page->getDestDir();
|
||||||
user_error("Rebuild cache must be passed an array of urls. Make sure your allPagesToCache function returns an array", E_USER_ERROR);
|
|
||||||
return;
|
if (!file_exists($cacheBaseDir)) {
|
||||||
};
|
Filesystem::makeFolder($cacheBaseDir);
|
||||||
|
}
|
||||||
if(!Director::is_cli()) {
|
|
||||||
$this->log("<pre>\n");
|
$quiet = Config::inst()->get('RebuildStaticCacheTask', 'quiet');
|
||||||
$this->log("Rebuilding cache.\nNOTE: Please ensure that this page ends with 'Done!' - if not, then something may have gone wrong.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$page = singleton('Page');
|
if (!$quiet) {
|
||||||
$cacheBaseDir = $page->getDestDir();
|
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.");
|
||||||
if(!file_exists($cacheBaseDir)) {
|
}
|
||||||
Filesystem::makeFolder($cacheBaseDir);
|
}
|
||||||
}
|
|
||||||
|
touch($cacheBaseDir.'/lock');
|
||||||
$quiet = Config::inst()->get('RebuildStaticCacheTask', 'quiet');
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
$urls[$i] = $url;
|
||||||
|
}
|
||||||
|
|
||||||
if(!$quiet) {
|
$urls = array_unique($urls);
|
||||||
if (file_exists($cacheBaseDir.'/lock') && !isset($_REQUEST['force'])) {
|
sort($urls);
|
||||||
die("There already appears to be a publishing queue running. You can skip warning this by adding ?/&force to the URL.");
|
|
||||||
}
|
$start = isset($_GET['start']) ? $_GET['start'] : 0;
|
||||||
}
|
$count = isset($_GET['count']) ? $_GET['count'] : sizeof($urls);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
$urls[$i] = $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
$urls = array_unique($urls);
|
if (($start + $count) > sizeof($urls)) {
|
||||||
sort($urls);
|
$count = sizeof($urls) - $start;
|
||||||
|
}
|
||||||
$start = isset($_GET['start']) ? $_GET['start'] : 0;
|
|
||||||
$count = isset($_GET['count']) ? $_GET['count'] : sizeof($urls);
|
|
||||||
|
|
||||||
if(($start + $count) > sizeof($urls)) {
|
$urls = array_slice($urls, $start, $count);
|
||||||
$count = sizeof($urls) - $start;
|
|
||||||
}
|
|
||||||
|
|
||||||
$urls = array_slice($urls, $start, $count);
|
$mappedUrls = $page->urlsToPaths($urls);
|
||||||
|
|
||||||
$mappedUrls = $page->urlsToPaths($urls);
|
if ($removeAll && !isset($_GET['urls']) && $start == 0 && file_exists("../cache")) {
|
||||||
|
$this->log("Removing stale cache files... \n");
|
||||||
|
|
||||||
if($removeAll && !isset($_GET['urls']) && $start == 0 && file_exists("../cache")) {
|
if (!$quiet) {
|
||||||
$this->log("Removing stale cache files... \n");
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
if(!$quiet) {
|
if (Config::inst()->get('FilesystemPublisher', 'domain_based_caching')) {
|
||||||
flush();
|
// 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)) {
|
||||||
|
$this->log(" * Deleting $cacheFile\n");
|
||||||
|
|
||||||
|
@unlink($cacheFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->log("done.\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (Config::inst()->get('FilesystemPublisher', 'domain_based_caching')) {
|
$this->log("Rebuilding cache from " . sizeof($mappedUrls) . " urls...\n\n");
|
||||||
// Glob each dir, then glob each one of those
|
$page->extend('publishPages', $mappedUrls);
|
||||||
foreach(glob(BASE_PATH . '/cache/*', GLOB_ONLYDIR) as $cacheDir) {
|
|
||||||
foreach(glob($cacheDir.'/*') as $cacheFile) {
|
if (file_exists($cacheBaseDir.'/lock')) {
|
||||||
$searchCacheFile = trim(str_replace($cacheBaseDir, '', $cacheFile), '\/');
|
unlink($cacheBaseDir.'/lock');
|
||||||
|
}
|
||||||
if (!in_array($searchCacheFile, $mappedUrls)) {
|
|
||||||
$this->log(" * Deleting $cacheFile\n");
|
$this->log("\n\n== Done! ==\n");
|
||||||
|
}
|
||||||
@unlink($cacheFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->log("done.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->log("Rebuilding cache from " . sizeof($mappedUrls) . " urls...\n\n");
|
|
||||||
$page->extend('publishPages', $mappedUrls);
|
|
||||||
|
|
||||||
if (file_exists($cacheBaseDir.'/lock')) {
|
|
||||||
unlink($cacheBaseDir.'/lock');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->log("\n\n== Done! ==\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,33 +3,39 @@
|
|||||||
/**
|
/**
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class StaticExporterTask extends BuildTask {
|
class StaticExporterTask extends BuildTask
|
||||||
|
{
|
||||||
|
|
||||||
public function run($request) {
|
public function run($request)
|
||||||
$now = microtime(true);
|
{
|
||||||
$export = new StaticExporter();
|
$now = microtime(true);
|
||||||
|
$export = new StaticExporter();
|
||||||
|
|
||||||
$url = $request->getVar('baseurl');
|
$url = $request->getVar('baseurl');
|
||||||
$sym = $request->getVar('symlink');
|
$sym = $request->getVar('symlink');
|
||||||
$quiet = $request->getVar('quiet');
|
$quiet = $request->getVar('quiet');
|
||||||
$folder = $request->getVar('path');
|
$folder = $request->getVar('path');
|
||||||
|
|
||||||
if(!$folder) $folder = TEMP_FOLDER . '/static-export';
|
if (!$folder) {
|
||||||
|
$folder = TEMP_FOLDER . '/static-export';
|
||||||
|
}
|
||||||
|
|
||||||
$url = ($url) ? $url : Director::baseURL();
|
$url = ($url) ? $url : Director::baseURL();
|
||||||
$symlink = ($sym != "false");
|
$symlink = ($sym != "false");
|
||||||
$quiet = ($quiet) ? $quiet : false;
|
$quiet = ($quiet) ? $quiet : false;
|
||||||
|
|
||||||
if(!$quiet) printf("Exporting website with %s base URL... %s", $url, PHP_EOL);
|
if (!$quiet) {
|
||||||
$path = $export->doExport($url, $folder, $symlink, $quiet);
|
printf("Exporting website with %s base URL... %s", $url, PHP_EOL);
|
||||||
|
}
|
||||||
|
$path = $export->doExport($url, $folder, $symlink, $quiet);
|
||||||
|
|
||||||
if(!$quiet) {
|
if (!$quiet) {
|
||||||
printf("\nWebsite exported to %s\nTotal time %s\nMemory used %s. %s",
|
printf("\nWebsite exported to %s\nTotal time %s\nMemory used %s. %s",
|
||||||
$path,
|
$path,
|
||||||
number_format(microtime(true) - $now, 2) . 's',
|
number_format(microtime(true) - $now, 2) . 's',
|
||||||
number_format(memory_get_peak_usage() / 1024 / 1024, 2) .'mb',
|
number_format(memory_get_peak_usage() / 1024 / 1024, 2) .'mb',
|
||||||
PHP_EOL
|
PHP_EOL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,243 +5,257 @@
|
|||||||
*
|
*
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class FilesystemPublisherTest extends SapphireTest {
|
class FilesystemPublisherTest extends SapphireTest
|
||||||
|
{
|
||||||
protected $usesDatabase = true;
|
|
||||||
|
protected $usesDatabase = true;
|
||||||
protected $orig = array();
|
|
||||||
|
protected $orig = array();
|
||||||
public function setUp() {
|
|
||||||
parent::setUp();
|
public function setUp()
|
||||||
|
{
|
||||||
SiteTree::add_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/')");
|
parent::setUp();
|
||||||
|
|
||||||
$this->orig['domain_based_caching'] = Config::inst()->get('FilesystemPublisher', 'domain_based_caching');
|
SiteTree::add_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/')");
|
||||||
|
|
||||||
|
$this->orig['domain_based_caching'] = Config::inst()->get('FilesystemPublisher', 'domain_based_caching');
|
||||||
|
|
||||||
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', false);
|
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown()
|
||||||
parent::tearDown();
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
SiteTree::remove_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/')");
|
SiteTree::remove_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/')");
|
||||||
|
|
||||||
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', $this->orig['domain_based_caching']);
|
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', $this->orig['domain_based_caching']);
|
||||||
|
|
||||||
if(file_exists(BASE_PATH . '/assets/FilesystemPublisherTest-static-folder')) {
|
if (file_exists(BASE_PATH . '/assets/FilesystemPublisherTest-static-folder')) {
|
||||||
Filesystem::removeFolder(BASE_PATH . '/assets/FilesystemPublisherTest-static-folder');
|
Filesystem::removeFolder(BASE_PATH . '/assets/FilesystemPublisherTest-static-folder');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUrlsToPathsWithRelativeUrls() {
|
public function testUrlsToPathsWithRelativeUrls()
|
||||||
$fsp = new FilesystemPublisher('.', 'html');
|
{
|
||||||
|
$fsp = new FilesystemPublisher('.', 'html');
|
||||||
$this->assertEquals(
|
|
||||||
$fsp->urlsToPaths(array('/')),
|
$this->assertEquals(
|
||||||
array('/' => './index.html'),
|
$fsp->urlsToPaths(array('/')),
|
||||||
'Root URL path mapping'
|
array('/' => './index.html'),
|
||||||
);
|
'Root URL path mapping'
|
||||||
|
);
|
||||||
$this->assertEquals(
|
|
||||||
$fsp->urlsToPaths(array('about-us')),
|
$this->assertEquals(
|
||||||
array('about-us' => './about-us.html'),
|
$fsp->urlsToPaths(array('about-us')),
|
||||||
'URLsegment path mapping'
|
array('about-us' => './about-us.html'),
|
||||||
);
|
'URLsegment path mapping'
|
||||||
|
);
|
||||||
$this->assertEquals(
|
|
||||||
$fsp->urlsToPaths(array('parent/child')),
|
$this->assertEquals(
|
||||||
array('parent/child' => 'parent/child.html'),
|
$fsp->urlsToPaths(array('parent/child')),
|
||||||
'Nested URLsegment path mapping'
|
array('parent/child' => 'parent/child.html'),
|
||||||
);
|
'Nested URLsegment path mapping'
|
||||||
}
|
);
|
||||||
|
}
|
||||||
public function testUrlsToPathsWithAbsoluteUrls() {
|
|
||||||
$fsp = new FilesystemPublisher('.', 'html');
|
public function testUrlsToPathsWithAbsoluteUrls()
|
||||||
|
{
|
||||||
$url = Director::absoluteBaseUrl();
|
$fsp = new FilesystemPublisher('.', 'html');
|
||||||
$this->assertEquals(
|
|
||||||
$fsp->urlsToPaths(array($url)),
|
$url = Director::absoluteBaseUrl();
|
||||||
array($url => './index.html'),
|
$this->assertEquals(
|
||||||
'Root URL path mapping'
|
$fsp->urlsToPaths(array($url)),
|
||||||
);
|
array($url => './index.html'),
|
||||||
|
'Root URL path mapping'
|
||||||
$url = Director::absoluteBaseUrl() . 'about-us';
|
);
|
||||||
$this->assertEquals(
|
|
||||||
$fsp->urlsToPaths(array($url)),
|
$url = Director::absoluteBaseUrl() . 'about-us';
|
||||||
array($url => './about-us.html'),
|
$this->assertEquals(
|
||||||
'URLsegment path mapping'
|
$fsp->urlsToPaths(array($url)),
|
||||||
);
|
array($url => './about-us.html'),
|
||||||
|
'URLsegment path mapping'
|
||||||
$url = Director::absoluteBaseUrl() . 'parent/child';
|
);
|
||||||
$this->assertEquals(
|
|
||||||
$fsp->urlsToPaths(array($url)),
|
$url = Director::absoluteBaseUrl() . 'parent/child';
|
||||||
array($url => 'parent/child.html'),
|
$this->assertEquals(
|
||||||
'Nested URLsegment path mapping'
|
$fsp->urlsToPaths(array($url)),
|
||||||
);
|
array($url => 'parent/child.html'),
|
||||||
}
|
'Nested URLsegment path mapping'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testUrlsToPathsWithDomainBasedCaching() {
|
public function testUrlsToPathsWithDomainBasedCaching()
|
||||||
$origDomainBasedCaching = Config::inst()->get('FilesystemPublisher', 'domain_based_caching');
|
{
|
||||||
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', true);
|
$origDomainBasedCaching = Config::inst()->get('FilesystemPublisher', 'domain_based_caching');
|
||||||
|
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', true);
|
||||||
$fsp = new FilesystemPublisher('.', 'html');
|
|
||||||
|
$fsp = new FilesystemPublisher('.', 'html');
|
||||||
$url = 'http://domain1.com/';
|
|
||||||
$this->assertEquals(
|
$url = 'http://domain1.com/';
|
||||||
$fsp->urlsToPaths(array($url)),
|
$this->assertEquals(
|
||||||
array($url => 'domain1.com/index.html'),
|
$fsp->urlsToPaths(array($url)),
|
||||||
'Root URL path mapping'
|
array($url => 'domain1.com/index.html'),
|
||||||
);
|
'Root URL path mapping'
|
||||||
|
);
|
||||||
$url = 'http://domain1.com/about-us';
|
|
||||||
$this->assertEquals(
|
$url = 'http://domain1.com/about-us';
|
||||||
$fsp->urlsToPaths(array($url)),
|
$this->assertEquals(
|
||||||
array($url => 'domain1.com/about-us.html'),
|
$fsp->urlsToPaths(array($url)),
|
||||||
'URLsegment path mapping'
|
array($url => 'domain1.com/about-us.html'),
|
||||||
);
|
'URLsegment path mapping'
|
||||||
|
);
|
||||||
$url = 'http://domain2.com/parent/child';
|
|
||||||
$this->assertEquals(
|
$url = 'http://domain2.com/parent/child';
|
||||||
$fsp->urlsToPaths(array($url)),
|
$this->assertEquals(
|
||||||
array($url => 'domain2.com/parent/child.html'),
|
$fsp->urlsToPaths(array($url)),
|
||||||
'Nested URLsegment path mapping'
|
array($url => 'domain2.com/parent/child.html'),
|
||||||
);
|
'Nested URLsegment path mapping'
|
||||||
|
);
|
||||||
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', $origDomainBasedCaching);
|
|
||||||
}
|
Config::inst()->update('FilesystemPublisher', 'domain_based_caching', $origDomainBasedCaching);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Simple test to ensure that FileSystemPublisher::__construct()
|
/**
|
||||||
* has called parent::__construct() by checking the class property.
|
* Simple test to ensure that FileSystemPublisher::__construct()
|
||||||
* The class property is set on {@link Object::__construct()} and
|
* has called parent::__construct() by checking the class property.
|
||||||
* this is therefore a good test to ensure it was called.
|
* 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()}
|
* If FilesystemPublisher doesn't call parent::__construct() then
|
||||||
* is where extension instances are set up and subsequently used by
|
* it won't be enabled propery because {@link Object::__construct()}
|
||||||
* {@link DataObject::defineMethods()}.
|
* is where extension instances are set up and subsequently used by
|
||||||
*/
|
* {@link DataObject::defineMethods()}.
|
||||||
public function testHasCalledParentConstructor() {
|
*/
|
||||||
$fsp = new FilesystemPublisher('.', '.html');
|
public function testHasCalledParentConstructor()
|
||||||
|
{
|
||||||
|
$fsp = new FilesystemPublisher('.', '.html');
|
||||||
|
|
||||||
$this->assertEquals($fsp->class, 'FilesystemPublisher');
|
$this->assertEquals($fsp->class, 'FilesystemPublisher');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are a few simple tests to check that we will be retrieving the
|
* 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
|
* correct theme when we need it. StaticPublishing needs to be able to
|
||||||
* retrieve a non-null theme at the time publishPages() is called.
|
* retrieve a non-null theme at the time publishPages() is called.
|
||||||
*/
|
*/
|
||||||
public function testStaticPublisherTheme(){
|
public function testStaticPublisherTheme()
|
||||||
|
{
|
||||||
// This will be the name of the default theme of this particular project
|
|
||||||
$default_theme = Config::inst()->get('SSViewer', 'theme');
|
// This will be the name of the default theme of this particular project
|
||||||
|
$default_theme = Config::inst()->get('SSViewer', 'theme');
|
||||||
$p1 = new Page();
|
|
||||||
$p1->URLSegment = strtolower(__CLASS__).'-page-1';
|
$p1 = new Page();
|
||||||
$p1->HomepageForDomain = '';
|
$p1->URLSegment = strtolower(__CLASS__).'-page-1';
|
||||||
$p1->write();
|
$p1->HomepageForDomain = '';
|
||||||
$p1->doPublish();
|
$p1->write();
|
||||||
|
$p1->doPublish();
|
||||||
$current_theme = Config::inst()->get('SSViewer', 'theme_enabled') ? Config::inst()->get('SSViewer', 'theme') : null;
|
|
||||||
$this->assertEquals($current_theme, $default_theme, 'After a standard publication, the theme is correct');
|
$current_theme = Config::inst()->get('SSViewer', 'theme_enabled') ? Config::inst()->get('SSViewer', 'theme') : null;
|
||||||
|
$this->assertEquals($current_theme, $default_theme, 'After a standard publication, the 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
|
//We can set the static_publishing theme to something completely different:
|
||||||
Config::inst()->update('StaticPublisher', 'static_publisher_theme', 'otherTheme');
|
//Static publishing will use this one instead of the current_custom_theme if it is not false
|
||||||
$current_theme = Config::inst()->get('StaticPublisher', 'static_publisher_theme');
|
Config::inst()->update('StaticPublisher', 'static_publisher_theme', 'otherTheme');
|
||||||
|
$current_theme = Config::inst()->get('StaticPublisher', 'static_publisher_theme');
|
||||||
|
|
||||||
$this->assertNotEquals($current_theme, $default_theme, 'The static publisher theme overrides the custom theme');
|
$this->assertNotEquals($current_theme, $default_theme, 'The static publisher theme overrides the custom theme');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMenu2LinkingMode() {
|
public function testMenu2LinkingMode()
|
||||||
$this->logInWithPermission('ADMIN');
|
{
|
||||||
|
$this->logInWithPermission('ADMIN');
|
||||||
Config::inst()->update('SSViewer', 'theme', null);
|
|
||||||
|
Config::inst()->update('SSViewer', 'theme', null);
|
||||||
$l1 = new StaticPublisherTestPage();
|
|
||||||
$l1->URLSegment = strtolower(__CLASS__).'-level-1';
|
$l1 = new StaticPublisherTestPage();
|
||||||
$l1->write();
|
$l1->URLSegment = strtolower(__CLASS__).'-level-1';
|
||||||
$l1->doPublish();
|
$l1->write();
|
||||||
|
$l1->doPublish();
|
||||||
$l2_1 = new StaticPublisherTestPage();
|
|
||||||
$l2_1->URLSegment = strtolower(__CLASS__).'-level-2-1';
|
$l2_1 = new StaticPublisherTestPage();
|
||||||
$l2_1->ParentID = $l1->ID;
|
$l2_1->URLSegment = strtolower(__CLASS__).'-level-2-1';
|
||||||
$l2_1->write();
|
$l2_1->ParentID = $l1->ID;
|
||||||
|
$l2_1->write();
|
||||||
$l2_1->doPublish();
|
|
||||||
$response = Director::test($l2_1->AbsoluteLink());
|
$l2_1->doPublish();
|
||||||
|
$response = Director::test($l2_1->AbsoluteLink());
|
||||||
|
|
||||||
$this->assertEquals(trim($response->getBody()), "current", "current page is level 2-1");
|
$this->assertEquals(trim($response->getBody()), "current", "current page is level 2-1");
|
||||||
|
|
||||||
$l2_2 = new StaticPublisherTestPage();
|
$l2_2 = new StaticPublisherTestPage();
|
||||||
$l2_2->URLSegment = strtolower(__CLASS__).'-level-2-2';
|
$l2_2->URLSegment = strtolower(__CLASS__).'-level-2-2';
|
||||||
$l2_2->ParentID = $l1->ID;
|
$l2_2->ParentID = $l1->ID;
|
||||||
$l2_2->write();
|
$l2_2->write();
|
||||||
$l2_2->doPublish();
|
$l2_2->doPublish();
|
||||||
|
|
||||||
$response = Director::test($l2_2->AbsoluteLink());
|
$response = Director::test($l2_2->AbsoluteLink());
|
||||||
$this->assertEquals(trim($response->getBody()), "linkcurrent", "current page is level 2-2");
|
$this->assertEquals(trim($response->getBody()), "linkcurrent", "current page is level 2-2");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testContentTypeHTML() {
|
public function testContentTypeHTML()
|
||||||
SiteTree::remove_extension('FilesystemPublisher');
|
{
|
||||||
SiteTree::add_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/', 'php')");
|
SiteTree::remove_extension('FilesystemPublisher');
|
||||||
$l1 = new StaticPublisherTestPage();
|
SiteTree::add_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/', 'php')");
|
||||||
$l1->URLSegment = 'mimetype';
|
$l1 = new StaticPublisherTestPage();
|
||||||
$l1->write();
|
$l1->URLSegment = 'mimetype';
|
||||||
$l1->doPublish();
|
$l1->write();
|
||||||
$response = Director::test('mimetype');
|
$l1->doPublish();
|
||||||
$this->assertEquals($response->getHeader('Content-Type'), 'text/html; charset=utf-8', 'Content-Type should be text/html; charset=utf-8');
|
$response = Director::test('mimetype');
|
||||||
}
|
$this->assertEquals($response->getHeader('Content-Type'), 'text/html; charset=utf-8', 'Content-Type should be text/html; charset=utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
public function testContentTypeJSON() {
|
public function testContentTypeJSON()
|
||||||
SiteTree::remove_extension('FilesystemPublisher');
|
{
|
||||||
SiteTree::add_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/', 'php')");
|
SiteTree::remove_extension('FilesystemPublisher');
|
||||||
$l1 = new StaticPublisherTestPage();
|
SiteTree::add_extension("FilesystemPublisher('assets/FilesystemPublisherTest-static-folder/', 'php')");
|
||||||
$l1->URLSegment = 'mimetype';
|
$l1 = new StaticPublisherTestPage();
|
||||||
$l1->write();
|
$l1->URLSegment = 'mimetype';
|
||||||
$l1->doPublish();
|
$l1->write();
|
||||||
$response = Director::test('mimetype/json');
|
$l1->doPublish();
|
||||||
$this->assertEquals($response->getHeader('Content-Type'), 'application/json', 'Content-Type should be application/json');
|
$response = Director::test('mimetype/json');
|
||||||
}
|
$this->assertEquals($response->getHeader('Content-Type'), 'application/json', 'Content-Type should be application/json');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class StaticPublisherTestPage extends Page implements TestOnly {
|
class StaticPublisherTestPage extends Page implements TestOnly
|
||||||
|
{
|
||||||
|
|
||||||
private static $allowed_children = array(
|
private static $allowed_children = array(
|
||||||
'StaticPublisherTestPage'
|
'StaticPublisherTestPage'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
public function canPublish($member = null) {
|
public function canPublish($member = null)
|
||||||
return true;
|
{
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function getTemplate() {
|
public function getTemplate()
|
||||||
return STATIC_MODULE_DIR . '/tests/templates/StaticPublisherTestPage.ss';
|
{
|
||||||
}
|
return STATIC_MODULE_DIR . '/tests/templates/StaticPublisherTestPage.ss';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @package staticpublisher
|
* @package staticpublisher
|
||||||
*/
|
*/
|
||||||
class StaticPublisherTestPage_Controller extends Page_Controller implements TestOnly {
|
class StaticPublisherTestPage_Controller extends Page_Controller implements TestOnly
|
||||||
|
{
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $allowed_actions = array('json');
|
|
||||||
|
|
||||||
public function json(SS_HTTPRequest $request) {
|
|
||||||
$response = new SS_HTTPResponse('{"firstName": "John"}');
|
|
||||||
$response->addHeader('Content-Type', 'application/json');
|
|
||||||
return $response;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $allowed_actions = array('json');
|
||||||
|
|
||||||
|
public function json(SS_HTTPRequest $request)
|
||||||
|
{
|
||||||
|
$response = new SS_HTTPResponse('{"firstName": "John"}');
|
||||||
|
$response->addHeader('Content-Type', 'application/json');
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user