artabro/wire/modules/Markup/MarkupCache.module

221 lines
5.7 KiB
Text
Raw Normal View History

2024-08-27 11:35:37 +02:00
<?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");
}
}