221 lines
5.7 KiB
Text
221 lines
5.7 KiB
Text
|
<?php namespace ProcessWire;
|
||
|
|
||
|
/**
|
||
|
* ProcessWire Markup Cache module
|
||
|
*
|
||
|
* A simple way to cache segments of markup in your templates.
|
||
|
* A simpler front end to ProcessWire's CacheFile class.
|
||
|
*
|
||
|
* Example usage:
|
||
|
*
|
||
|
* $mycache = $modules->get("MarkupCache");
|
||
|
* if(!$data = $mycache->get("cityOptions")) {
|
||
|
* foreach($pages->find("template=city, sort=name") as $city) {
|
||
|
* $data .= "<option value='{$city->id}'>{$city->title}</option>";
|
||
|
* }
|
||
|
* $mycache->save($data);
|
||
|
* }
|
||
|
* echo $data;
|
||
|
*
|
||
|
*
|
||
|
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||
|
* https://processwire.com
|
||
|
*
|
||
|
*
|
||
|
* @todo add serialize/unserialize to support non-string data in MarkupCache
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
class MarkupCache extends Wire implements Module, ConfigurableModule {
|
||
|
|
||
|
/**
|
||
|
* getModuleInfo is a module required by all modules to tell ProcessWire about them
|
||
|
*
|
||
|
* @return array
|
||
|
*
|
||
|
*/
|
||
|
public static function getModuleInfo() {
|
||
|
|
||
|
return array(
|
||
|
'title' => 'Markup Cache',
|
||
|
'version' => 101,
|
||
|
'summary' => 'A simple way to cache segments of markup in your templates. ',
|
||
|
'href' => 'https://processwire.com/api/modules/markupcache/',
|
||
|
'singular' => true,
|
||
|
'autoload' => true,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Instance of CacheFile
|
||
|
*
|
||
|
* @var CacheFile
|
||
|
*
|
||
|
*/
|
||
|
protected $cache = null;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Boolean indicating whether we've already cleared the cache.
|
||
|
*
|
||
|
*/
|
||
|
protected $cleared = false;
|
||
|
|
||
|
/**
|
||
|
* Path to cache files, as set by the init() method.
|
||
|
*
|
||
|
*/
|
||
|
protected $path = '';
|
||
|
|
||
|
/**
|
||
|
* Non zero when caches shouldn't expire on page save
|
||
|
*
|
||
|
*/
|
||
|
protected $noExpire = 0;
|
||
|
|
||
|
/**
|
||
|
* Generate the module's path, static so it can be used by the static getModuleConfigInputfields function
|
||
|
*
|
||
|
*/
|
||
|
public function path() {
|
||
|
return $this->wire('config')->paths->cache . 'MarkupCache' . '/';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialize the module and add a hook after Pages::save
|
||
|
*
|
||
|
*/
|
||
|
public function init() {
|
||
|
$this->path = $this->path();
|
||
|
if(!$this->noExpire) $this->pages->addHookAfter('save', $this, 'expire');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get cached data identified by 'uniqueName' or false if cache not available
|
||
|
*
|
||
|
* @param string $uniqueName A unique string or number to identify this cache, i.e. 'citiesList'
|
||
|
* @param int $seconds The number of seconds the cache should live.
|
||
|
* @return string|bool Returns the cache data, or FALSE if it has expired and needs to be re-created.
|
||
|
* @throws WireException
|
||
|
*
|
||
|
*/
|
||
|
public function get($uniqueName, $seconds = 3600) {
|
||
|
$cache = $this->wire(new CacheFile($this->path, $uniqueName, $seconds));
|
||
|
if(!$cache) throw new WireException("Unable to create cache '{$this->path}/$uniqueName'");
|
||
|
$this->cache = $cache;
|
||
|
return $this->cache->get();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save the data to the cache
|
||
|
*
|
||
|
* Must be preceded by a call to get() so that you have set the cache unique name
|
||
|
*
|
||
|
* @param string $data Data to cache
|
||
|
* @return int Number of bytes written to cache, or FALSE on failure.
|
||
|
* @throws WireException
|
||
|
*
|
||
|
*/
|
||
|
public function save($data) {
|
||
|
if(!$this->cache) throw new WireException("You must attempt to retrieve a cache first, before you can save it.");
|
||
|
$result = $this->cache->save($data);
|
||
|
$this->cache = null;
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Expire the cache, automatically hooked to every $pages->save() call
|
||
|
*
|
||
|
*/
|
||
|
public function expire($event = null) {
|
||
|
/*
|
||
|
* If already cleared during this session, don't do it again
|
||
|
* that way if we're saving 100+ pages, we aren't clearing the cache 100+ times
|
||
|
*
|
||
|
*/
|
||
|
if($this->cleared) return;
|
||
|
|
||
|
if($this->cache) $cache = $this->cache;
|
||
|
else $cache = $this->wire(new CacheFile($this->path, '', 0));
|
||
|
$cache->expireAll();
|
||
|
$this->cleared = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clears all MarkupCache files
|
||
|
*
|
||
|
* @return number of files/dirs deleted
|
||
|
*
|
||
|
*/
|
||
|
public function removeAll() {
|
||
|
$path = $this->path();
|
||
|
try {
|
||
|
$num = CacheFile::removeAll($path, true);
|
||
|
} catch(\Exception $e) {
|
||
|
$num = 0;
|
||
|
}
|
||
|
return $num;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* For ConfigurableModule interface, even though we aren't currently using it
|
||
|
*
|
||
|
*/
|
||
|
public function __set($key, $value) {
|
||
|
if($key == 'noExpire') $this->noExpire = (int) $value;
|
||
|
// intentionally left blank
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Provide cache clearing capability in the module's configuration
|
||
|
*
|
||
|
* @param array $data
|
||
|
* @return InputfieldWrapper
|
||
|
*
|
||
|
*/
|
||
|
public function getModuleConfigInputfields(array $data) {
|
||
|
|
||
|
$inputfields = $this->wire(new InputfieldWrapper());
|
||
|
$clearNow = $this->wire('input')->post->_clearCache ? true : false;
|
||
|
$message = '';
|
||
|
|
||
|
if($clearNow) {
|
||
|
$numFiles = $this->removeAll();
|
||
|
$message = "Cleared $numFiles MarkupCache files and dirs";
|
||
|
$inputfields->message($message);
|
||
|
}
|
||
|
|
||
|
$name = "_clearCache"; // prefix with '_' tells ProcessModule not to save it in module's config data
|
||
|
$f = $this->wire('modules')->get('InputfieldCheckbox');
|
||
|
$f->attr('name', $name);
|
||
|
$f->attr('value', 1);
|
||
|
$f->attr('checked', '');
|
||
|
$f->label = "Clear the MarkupCache?";
|
||
|
$f->notes = $message;
|
||
|
$f->description = "This will remove all files and directories used by the MarkupCache";
|
||
|
$inputfields->append($f);
|
||
|
|
||
|
$f = $this->wire('modules')->get('InputfieldRadios');
|
||
|
$f->attr('name', 'noExpire');
|
||
|
$f->attr('value', empty($data['noExpire']) ? 0 : 1);
|
||
|
$f->label = "Expire markup caches when pages are saved?";
|
||
|
$f->description = "If you want to ensure stale data is never shown, you should choose: Yes. If you want to maximize performance, you should choose: No.";
|
||
|
$f->addOption(0, "Yes - Expire markup caches");
|
||
|
$f->addOption(1, "No - Don't expire markup caches");
|
||
|
$inputfields->append($f);
|
||
|
|
||
|
return $inputfields;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Uninstall this module and remove it's files
|
||
|
*
|
||
|
*/
|
||
|
public function ___uninstall() {
|
||
|
$numFiles = $this->removeAll();
|
||
|
$this->message("Removed $numFiles MarkupCache files");
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|