Blame | Last modification | View Log | Download
<?phpnamespace ProcessWire;class CacheControlTools extends Wire implements Module{/** @var string The cache namespace for storing asset versions in the database */public const ASSET_CACHE_NAMESPACE = 'cache-control-assets';/** @var string The default asset type / category if none is specified */public const ASSET_CACHE_DEFAULT_KEY = 'default';/** @var string The name of the system log for this module */public const LOG_NAME = 'cache-control';public static function getModuleInfo(){return ['title' => __('Cache Control Tools'),'summary' => __('Utility module installed alongside ProcessCacheControl to provide helper methods.'),'author' => "Moritz L'Hoest",'href' => 'https://github.com/MoritzLost/ProcessCacheControl','version' => '1.1.1','icon' => 'floppy-o','requires' => ['ProcessCacheControl','ProcessWire>=3.0.130','PHP>=7.1',],];}/** @var bool If this is true, all helper methods will not write any log messages */protected $silent = false;/*** Turn off all logging done by the helper methods of this module. You can* still call logMessage to log messages manually.** @return self*/public function silent(): self{$this->silent = true;return $this;}/*** Turn the logging done by helper methods back on.** @return self*/public function verbose(): self{$this->silent = false;return $this;}/*** Get the stored asset version string to append to asset source URLs. Generates* a new version string if none exists.** @param string $type Optional asset class / category.* @return string*/public function getAssetVersion(string $type = self::ASSET_CACHE_DEFAULT_KEY): string{$assetVersion = $this->wire('cache')->getFor(self::ASSET_CACHE_NAMESPACE,$type);return $assetVersion ?: $this->refreshAssetVersion($type);}/*** Refresh the stored asset version string and return it.** @param string $type Optional asset class / category to refresh the version for.* @param string|null $version The new version to store. Defaults to the curernt timestamp.* @return string*/public function refreshAssetVersion(string $type = self::ASSET_CACHE_DEFAULT_KEY, ?string $version = null): string{$version = $version ?? time();$this->wire('cache')->saveFor(self::ASSET_CACHE_NAMESPACE,$type,$version,WireCache::expireNever);$this->logMessageIfNotSilent(sprintf($this->_('Updated the asset version for type %1$s to: %2$s'),$type,$version));return $version;}/*** Clear out all stored asset versions. New version strings will be* automatically generated the next time they are requested.** @return self*/public function clearAllAssetVersions(): self{$this->wire('cache')->deleteFor(self::ASSET_CACHE_NAMESPACE);$this->logMessageIfNotSilent($this->_('Cleared all stored asset versions.'));return $this;}/*** Clear all files and directories in the specified folder inside the site's* cache directory. Includes a safety check to never delete anything outside* the cache directory.** @param string $directory The name of the folder to clear, without a leading slash.* @return self*/public function clearCacheDirectoryContent(string $directory): self{$dirPath = $this->wire('config')->paths->cache . $directory;$dirPathFromRoot = $this->wire('config')->urls->cache . $directory;// check if the directory exists, and exit early if it doesn'tif (!is_dir($dirPath)) {$this->logMessageIfNotSilent(sprintf($this->_('Skipped request to delete missing folder: %s'),$dirPathFromRoot));return $this;}// iterate over all contents of the directory and remove them recursively$dirIterator = new \DirectoryIterator($dirPath);$cacheLimitPath = $this->wire('config')->paths->cache;foreach ($dirIterator as $fileinfo) {if ($fileinfo->isDot()) continue;if ($fileinfo->isDir()) {$this->wire('files')->rmdir($fileinfo->getPathname(),true,['limitPath' => $cacheLimitPath]);}if ($fileinfo->isFile() || $fileinfo->isLink()) {$this->wire('files')->unlink($fileinfo->getPathname(),$cacheLimitPath);}}// log the resultif ($directory === PageRender::cacheDirName) {// special case: the "Page" directory contains the template render cache$this->logMessageIfNotSilent($this->_('Cleared the template render cache.'));} else {$this->logMessageIfNotSilent(sprintf($this->_('Removed all files from the following cache directory: %s'),$dirPathFromRoot));}return $this;}/*** Clears out all cache entries for the specified namespaces using* ProcessWire's cache API ($cache / WireCache).** @param array $namespaces An array of cache namespaces to clear.* @return self*/public function clearWireCacheByNamespaces(array $namespaces): self{foreach ($namespaces as $namespace) {$this->wire('cache')->deleteFor($namespace);}$this->logMessageIfNotSilent(sprintf($this->_('Deleted WireCache entries for the following namespaces: %s'),implode(', ', $namespaces)));return $this;}/*** Log a message in the dedicated log file for this module. Newly added* cache actions should use this method to log messages about what they are* doing. The module page will automatically display all messages during* this page view.** @param string $message The message to log.* @return self*/public function logMessage(string $message): self{$this->wire('log')->save(self::LOG_NAME,$message);return $this;}/*** Log a message only if this instance is not currently set to silent.** @see self::logMessage*/public function logMessageIfNotSilent(string $message): self{if (!$this->isSilent) {$this->logMessage($message);}return $this;}}