Merge branch 'feature/cache-refactor' into 1.6

This commit is contained in:
Andy Miller
2018-09-20 11:25:35 -06:00
7 changed files with 118 additions and 34 deletions

View File

@@ -39,7 +39,7 @@ $app->addCommands(array(
new \Grav\Console\Cli\ComposerCommand(),
new \Grav\Console\Cli\SandboxCommand(),
new \Grav\Console\Cli\CleanCommand(),
new \Grav\Console\Cli\ClearCacheCommand(),
new \Grav\Console\Cli\CacheCommand(),
new \Grav\Console\Cli\BackupCommand(),
new \Grav\Console\Cli\NewProjectCommand(),
new \Grav\Console\Cli\SchedulerCommand(),

View File

@@ -119,7 +119,7 @@ form:
.schedule_at:
type: cron
label: Run Scheduled Job
default: '* * * * *'
default: '* 3 * * *'
validate:
required: true

View File

@@ -514,6 +514,12 @@ form:
help: PLUGIN_ADMIN.CACHE_PREFIX_HELP
placeholder: PLUGIN_ADMIN.CACHE_PREFIX_PLACEHOLDER
cache.purge_at:
type: cron
label: PLUGIN_ADMIN.CACHE_PURGE_JOB
help: PLUGIN_ADMIN.CACHE_PURGE_JOB_HELP
default: '* 3 * * *'
cache.clear_images_by_default:
type: toggle
label: PLUGIN_ADMIN.CLEAR_IMAGES_BY_DEFAULT

View File

@@ -76,6 +76,7 @@ cache:
method: file # Method to check for updates in pages: file|folder|hash|none
driver: auto # One of: auto|file|apc|xcache|memcache|wincache
prefix: 'g' # Cache prefix string (prevents cache conflicts)
purge_at: '0 4 * * *' # How often to purge old cache (using new scheduler)
clear_images_by_default: true # By default grav will include processed images in cache clear, this can be disabled
cli_compatibility: false # Ensures only non-volatile drivers are used (file, redis, memcache, etc.)
lifetime: 604800 # Lifetime of cached data in seconds (0 = infinite)

View File

@@ -117,27 +117,45 @@ class Cache extends Getters
$this->config = $grav['config'];
$this->now = time();
$this->cache_dir = $grav['locator']->findResource('cache://doctrine', true, true);
if (is_null($this->enabled)) {
$this->enabled = (bool)$this->config->get('system.cache.enabled');
}
/** @var Uri $uri */
$uri = $grav['uri'];
$prefix = $this->config->get('system.cache.prefix');
if (is_null($this->enabled)) {
$this->enabled = (bool)$this->config->get('system.cache.enabled');
}
$uniqueness = substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION), 2, 8);
// Cache key allows us to invalidate all cache on configuration changes.
$this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION),
2, 8);
$this->key = ($prefix ? $prefix : 'g') . '-' . $uniqueness;
$this->cache_dir = $grav['locator']->findResource('cache://doctrine/' . $uniqueness, true, true);
$this->driver_setting = $this->config->get('system.cache.driver');
$this->driver = $this->getCacheDriver();
// Set the cache namespace to our unique key
$this->driver->setNamespace($this->key);
/** @var EventDispatcher $dispatcher */
$dispatcher = Grav::instance()['events'];
$dispatcher->addListener('onSchedulerInitialized', [$this, 'onSchedulerInitialized']);
}
public function purgeOldCache()
{
$cache_dir = dirname($this->cache_dir);
$current = basename($this->cache_dir);
$count = 0;
foreach (new \DirectoryIterator($cache_dir) as $file) {
$dir = $file->getBasename();
if ($file->isDot() || $file->isFile() || $dir === $current) {
continue;
}
Folder::delete($file->getPathname());
$count++;
}
return $count;
}
/**
@@ -313,6 +331,19 @@ class Cache extends Getters
return false;
}
/**
* Deletes all cache
*
* @return bool
*/
public function deleteAll()
{
if ($this->enabled) {
return $this->driver->deleteAll();
}
return false;
}
/**
* Returns a boolean state of whether or not the item exists in the cache based on id key
*
@@ -382,6 +413,12 @@ class Cache extends Getters
}
// Delete entries in the doctrine cache if required
if (in_array($remove, ['all', 'standard'])) {
$cache = Grav::instance()['cache'];
$cache->driver->deleteAll();
}
// Clearing cache event to add paths to clear
Grav::instance()->fireEvent('onBeforeCacheClear', new Event(['remove' => $remove, 'paths' => &$remove_paths]));
@@ -507,4 +544,30 @@ class Cache extends Getters
return false;
}
}
public static function purgeJob()
{
$cache = Grav::instance()['cache'];
$deleted_folders = $cache->purgeOldCache();
$msg = 'Purged ' . $deleted_folders . ' old cache folders...';
return $msg;
}
public function onSchedulerInitialized(Event $event)
{
/** @var Scheduler $scheduler */
$scheduler = $event['scheduler'];
$config = Grav::instance()['config'];
$at = $config->get('system.cache.purge_at');
$name = 'cache-purge';
$logs = 'logs/' . $name . '.out';
$job = $scheduler->addFunction('Grav\Common\Cache::purgeJob', null, $name );
$job->at($at);
$job->output($logs);
}
}

View File

@@ -9,10 +9,11 @@
namespace Grav\Console\Cli;
use Grav\Common\Cache;
use Grav\Common\Grav;
use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Input\InputOption;
class ClearCacheCommand extends ConsoleCommand
class CacheCommand extends ConsoleCommand
{
/**
*
@@ -20,14 +21,17 @@ class ClearCacheCommand extends ConsoleCommand
protected function configure()
{
$this
->setName('clear-cache')
->setAliases(['clearcache'])
->setName('cache')
->setAliases(['clearcache', 'cache-clear'])
->setDescription('Clears Grav cache')
->addOption('purge', null, InputOption::VALUE_NONE, 'If set purge old caches')
->addOption('all', null, InputOption::VALUE_NONE, 'If set will remove all including compiled, twig, doctrine caches')
->addOption('assets-only', null, InputOption::VALUE_NONE, 'If set will remove only assets/*')
->addOption('images-only', null, InputOption::VALUE_NONE, 'If set will remove only images/*')
->addOption('cache-only', null, InputOption::VALUE_NONE, 'If set will remove only cache/*')
->addOption('tmp-only', null, InputOption::VALUE_NONE, 'If set will remove only tmp/*')
->addOption('tmp-only', null, InputOption::VALUE_NONE, 'If set will remove only tmp/*')
->setHelp('The <info>clear-cache</info> deletes all cache files');
}
@@ -45,25 +49,35 @@ class ClearCacheCommand extends ConsoleCommand
private function cleanPaths()
{
$this->output->writeln('');
$this->output->writeln('<magenta>Clearing cache</magenta>');
$this->output->writeln('');
if ($this->input->getOption('all')) {
$remove = 'all';
} elseif ($this->input->getOption('assets-only')) {
$remove = 'assets-only';
} elseif ($this->input->getOption('images-only')) {
$remove = 'images-only';
} elseif ($this->input->getOption('cache-only')) {
$remove = 'cache-only';
} elseif ($this->input->getOption('tmp-only')) {
$remove = 'tmp-only';
if ($this->input->getOption('purge')) {
$this->output->writeln('<magenta>Purging old cache</magenta>');
$this->output->writeln('');
$msg = Cache::purgeJob();
$this->output->writeln($msg);
} else {
$remove = 'standard';
}
$this->output->writeln('<magenta>Clearing cache</magenta>');
$this->output->writeln('');
foreach (Cache::clearCache($remove) as $result) {
$this->output->writeln($result);
if ($this->input->getOption('all')) {
$remove = 'all';
} elseif ($this->input->getOption('assets-only')) {
$remove = 'assets-only';
} elseif ($this->input->getOption('images-only')) {
$remove = 'images-only';
} elseif ($this->input->getOption('cache-only')) {
$remove = 'cache-only';
} elseif ($this->input->getOption('tmp-only')) {
$remove = 'tmp-only';
} else {
$remove = 'standard';
}
foreach (Cache::clearCache($remove) as $result) {
$this->output->writeln($result);
}
}
}
}

View File

@@ -11,7 +11,7 @@ namespace Grav\Console;
use Grav\Common\Grav;
use Grav\Common\Composer;
use Grav\Common\GravTrait;
use Grav\Console\Cli\ClearCacheCommand;
use Grav\Console\Cli\CacheCommand;
use RocketTheme\Toolbox\File\YamlFile;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\ArrayInput;
@@ -107,7 +107,7 @@ trait ConsoleTrait
$all = ['--all' => true];
}
$command = new ClearCacheCommand();
$command = new CacheCommand();
$input = new ArrayInput($all);
return $command->run($input, $this->output);
}