From d50443b10ac5744fc6fefa6d77552f27039d93c4 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Mon, 30 Aug 2021 00:45:57 +0200 Subject: [PATCH] Controllers+Views+JS+Route: Implement cache purging --- app/controllers/CacheController.php | 92 ++++++++++++++++++++++++++++- app/views/admin/cache.php | 9 ++- public/js/app.js | 34 +++++++++++ route.php | 1 + 4 files changed, 132 insertions(+), 4 deletions(-) diff --git a/app/controllers/CacheController.php b/app/controllers/CacheController.php index afc67ab..7d5199a 100644 --- a/app/controllers/CacheController.php +++ b/app/controllers/CacheController.php @@ -4,18 +4,81 @@ namespace App\Controllers; use App\Classes\Config; use App\Classes\Http\Http; +use App\Classes\Session; use App\Model\ConfigModel; class CacheController extends PageController { + /** + * Maximum amount of files that can be purged on a single request + */ + public static int $purgeLimit = 30; + public function cacheAction(): void { $config = $this->getConfigValues(); $this->router->service()->config = $config; + $this->router->service()->csrfToken = Session::token(); + $this->router->service()->purgeUrl = $this->url . '/purge'; parent::view(); } + public function purgeAction(): void + { + if (!$this->validatePostRequest()) { + return; + } + + $token = Config::c('CLOUDFLARE_TOKEN'); + $zone = Config::c('CLOUDFLARE_ZONE'); + + $url = "https://api.cloudflare.com/client/v4/zones/$zone/purge_cache"; + + if (!_exists($_POST, 'type')) { + return; + } + + $bodies = []; + switch($_POST['type']) { + case 'css-js': + $body = self::generateUrls(['css', 'js']); + $chunks = array_chunk($body['files'], self::$purgeLimit); + foreach($chunks as $chunk) { + $bodies[]['files'] = $chunk; + } + break; + case 'fonts-images': + $body = self::generateUrls(['fonts', 'img', 'media']); + $chunks = array_chunk($body['files'], self::$purgeLimit); + foreach($chunks as $chunk) { + $bodies[]['files'] = $chunk; + } + break; + case 'all': + $bodies[] = ['purge_everything' => true]; + break; + default: + return; + } + + $response = null; + foreach($bodies as $body) { + $response = (new Http)->withToken($token) + ->asJson() + ->acceptJson() + ->post($url, $body); + if (empty($response->body()) + || !json_decode($response->body(), true)['success']) { + break; + } + } + + if ($response) { + echo $response->body(); + } + } + public function toggleAction(): void { if (Config::c('CLOUDFLARE_ENABLED') != '1') { @@ -40,13 +103,40 @@ class CacheController extends PageController { $this->saveConfigValues($response->body()); echo $response->body(); + } + //-------------------------------------// + private function validatePostRequest(): bool + { + if ($_SERVER['REQUEST_METHOD'] == 'GET') { + parent::throw404(); + } + if (Config::c('CLOUDFLARE_ENABLED') != '1') { + return false; + } + + if (!Session::validateToken($_POST)) { + return false; + } + return true; } - //-------------------------------------// + private static function generateUrls(array $directories): array + { + $result = []; + + foreach ($directories as $directory) { + $files = array_diff(scandir($directory), ['..', '.']); + foreach ($files as $file) { + $result['files'][] = Config::c('APP_URL') . "/$directory/$file"; + } + } + + return $result; + } private static function getConfigValues(): array { diff --git a/app/views/admin/cache.php b/app/views/admin/cache.php index 96c8694..45d95f4 100644 --- a/app/views/admin/cache.php +++ b/app/views/admin/cache.php @@ -23,7 +23,8 @@ use \App\Classes\Config;
- + Purge
@@ -35,7 +36,8 @@ use \App\Classes\Config;
- + Purge
@@ -47,7 +49,8 @@ use \App\Classes\Config;
- + Purge
diff --git a/public/js/app.js b/public/js/app.js index bcb869b..a63f401 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -229,6 +229,40 @@ $(document).ready(function() { //------------------------------------------ + $('.js-purge').on('click', function(event) + { + event.preventDefault(); + + const purgeType = $(this).attr('data-type'); + const csrfToken = $(this).attr('data-token'); + + if (!confirm('Are you sure you want to continue?')) { + return; + } + + $.ajax({ + url: $(this).attr('href'), + type: 'POST', + data: { type: purgeType, _token: csrfToken }, + success: function(data) + { + if (data == '') { + alert("Cache could not be purged!"); + return; + } + + const response = JSON.parse(data); + if (response.success == false) { + console.log(data); + alert("Cache could not be purged!"); + return; + } + + alert("Cache has been purged."); + } + }); + }); + // Developer mode $('#development-mode').on('click', function(e) { diff --git a/route.php b/route.php index e2f0d9a..d17e605 100644 --- a/route.php +++ b/route.php @@ -23,6 +23,7 @@ return [ ['/admin', 'AdminController', '', ''], ['/admin/cache', 'CacheController', 'cache', ''], ['/admin/toggle', 'AdminController', 'toggle', ''], + ['/admin/cache/purge', 'CacheController', 'purge', ''], ['/admin/cache/toggle', 'CacheController', 'toggle', ''], ['/admin/syntax-highlighting', 'AdminController', 'syntax', ''], ['/test', 'TestController', '', ''],