Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a99c31d47 | ||
|
|
d50443b10a | ||
|
|
b244b625ab | ||
|
|
2311c98257 |
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Http;
|
||||
|
||||
class Http {
|
||||
|
||||
private string $bodyContent;
|
||||
|
||||
private string $bodyFormat;
|
||||
|
||||
private array $options = [];
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function delete(string $url, $data = []): Response
|
||||
{
|
||||
return $this->send('DELETE', $url, [
|
||||
$this->bodyFormat => $data
|
||||
]);
|
||||
}
|
||||
|
||||
public function get(string $url, $query = null): Response
|
||||
{
|
||||
return $this->send('GET', $url, [
|
||||
'query' => $query
|
||||
]);
|
||||
}
|
||||
|
||||
public function patch(string $url, array $data = []): Response
|
||||
{
|
||||
return $this->send('PATCH', $url, [
|
||||
$this->bodyFormat => $data
|
||||
]);
|
||||
}
|
||||
|
||||
public function put(string $url, array $data = []): Response
|
||||
{
|
||||
return $this->send('PUT', $url, [
|
||||
$this->bodyFormat => $data
|
||||
]);
|
||||
}
|
||||
|
||||
public function post(string $url, array $data = []): Response
|
||||
{
|
||||
return $this->send('POST', $url, [
|
||||
$this->bodyFormat => $data
|
||||
]);
|
||||
}
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
public function accept(string $contentType): Http
|
||||
{
|
||||
return $this->withHeaders(['Accept' => $contentType]);
|
||||
}
|
||||
|
||||
public function acceptJson(): Http
|
||||
{
|
||||
return $this->accept('application/json');
|
||||
}
|
||||
|
||||
public function asForm(): Http
|
||||
{
|
||||
return $this->bodyFormat('form_params')
|
||||
->contentType('application/x-www-form-urlencoded');
|
||||
}
|
||||
|
||||
public function asJson(): Http
|
||||
{
|
||||
return $this->bodyFormat('json')
|
||||
->contentType('application/json');
|
||||
}
|
||||
|
||||
public function bodyFormat(string $format): Http
|
||||
{
|
||||
$this->bodyFormat = $format;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function contentType(string $type): Http
|
||||
{
|
||||
return $this->withHeaders(['Content-Type' => $type]);
|
||||
}
|
||||
|
||||
public function withBody(string $content, string $contentType): Http
|
||||
{
|
||||
$this->bodyFormat('body');
|
||||
|
||||
$this->bodyContent = $content;
|
||||
|
||||
$this->contentType($contentType);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withHeaders(array $headers): Http
|
||||
{
|
||||
$this->options = array_merge_recursive($this->options, [
|
||||
'headers' => $headers,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withToken(string $token): Http
|
||||
{
|
||||
$this->withHeaders(['Authorization' => 'Bearer ' . trim($token)]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
public function send(string $method, string $url, array $options = []): Response
|
||||
{
|
||||
// Format headers
|
||||
$headers = [];
|
||||
if (_exists($this->options, 'headers')) {
|
||||
foreach ($this->options['headers'] as $key => $value) {
|
||||
$headers[] = "$key: $value";
|
||||
}
|
||||
}
|
||||
|
||||
// Fill body content
|
||||
switch ($this->bodyFormat) {
|
||||
case 'body':
|
||||
break;
|
||||
case 'json':
|
||||
if (_exists($options, 'json')) {
|
||||
$this->bodyContent = json_encode($options['json']);
|
||||
}
|
||||
break;
|
||||
case 'form_params':
|
||||
if (_exists($options, 'form_params')) {
|
||||
$this->bodyContent = http_build_query($options['form_params']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Send HTTP request
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->bodyContent);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
$response = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
// On failed requests
|
||||
if (!$response) {
|
||||
$response = '';
|
||||
}
|
||||
|
||||
return new Response($response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Http;
|
||||
|
||||
class Response {
|
||||
|
||||
private string $response;
|
||||
|
||||
public function __construct(string $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
public function body(): string
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,21 +3,86 @@
|
||||
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';
|
||||
$this->router->service()->toggleUrl = $this->url . '/toggle';
|
||||
parent::view();
|
||||
}
|
||||
|
||||
public function developmentAction(): void
|
||||
public function purgeAction(): void
|
||||
{
|
||||
if (Config::c('CLOUDFLARE_ENABLED') != '1') {
|
||||
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 (!$this->validatePostRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,38 +90,55 @@ class CacheController extends PageController {
|
||||
$zone = Config::c('CLOUDFLARE_ZONE');
|
||||
|
||||
$url = "https://api.cloudflare.com/client/v4/zones/$zone/settings/development_mode";
|
||||
$headers = [
|
||||
"Authorization: Bearer $token",
|
||||
"Content-Type: application/json"
|
||||
];
|
||||
|
||||
$config = $this->getConfigValues();
|
||||
$currentState = $config['CLOUDFLARE_DEVELOPMENT_MODE_ENABLED'];
|
||||
|
||||
$newState = $currentState == '1' ? 'off' : 'on';
|
||||
$data = '{"value": "' . $newState . '"}';
|
||||
$response = (new Http)->withToken($token)
|
||||
->asJson()
|
||||
->acceptJson()
|
||||
->patch($url, [
|
||||
'value' => $currentState == '1' ? 'off' : 'on',
|
||||
]);
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// curl_setopt($curl, CURLINFO_HEADER_OUT, 1);
|
||||
$this->saveConfigValues($response->body());
|
||||
|
||||
$response = curl_exec($curl);
|
||||
// $info = curl_getinfo($curl, CURLINFO_HEADER_OUT);
|
||||
|
||||
curl_close($curl);
|
||||
|
||||
$this->saveConfigValues($response);
|
||||
|
||||
echo $response;
|
||||
// echo $info;
|
||||
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
|
||||
{
|
||||
$result = [];
|
||||
|
||||
@@ -23,7 +23,8 @@ use \App\Classes\Config;
|
||||
</div>
|
||||
<div class="col-3 col-md-2 col-lg-2 col-xl-2">
|
||||
<div class="d-flex justify-content-center">
|
||||
<button id="" class="btn btn-dark">Purge</button>
|
||||
<a class="js-purge btn btn-dark" href="<?= $this->purgeUrl; ?>"
|
||||
data-type="css-js" data-token="<?= $this->csrfToken; ?>">Purge</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -35,7 +36,8 @@ use \App\Classes\Config;
|
||||
</div>
|
||||
<div class="col-3 col-md-2 col-lg-2 col-xl-2">
|
||||
<div class="d-flex justify-content-center">
|
||||
<button id="" class="btn btn-danger">Purge</button>
|
||||
<a class="js-purge btn btn-danger" href="<?= $this->purgeUrl; ?>"
|
||||
data-type="fonts-images" data-token="<?= $this->csrfToken; ?>">Purge</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,7 +49,8 @@ use \App\Classes\Config;
|
||||
</div>
|
||||
<div class="col-3 col-md-2 col-lg-2 col-xl-2">
|
||||
<div class="d-flex justify-content-center">
|
||||
<button id="" class="btn btn-danger">Purge</button>
|
||||
<a class="js-purge btn btn-danger" href="<?= $this->purgeUrl; ?>"
|
||||
data-type="all" data-token="<?= $this->csrfToken; ?>">Purge</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,6 +75,7 @@ use \App\Classes\Config;
|
||||
<div class="col-3 col-md-2 col-lg-2 col-xl-2">
|
||||
<div class="d-flex justify-content-center">
|
||||
<input type="checkbox" id="development-mode"
|
||||
data-href="<?= $this->toggleUrl; ?>" data-token="<?= $this->csrfToken; ?>"
|
||||
<?= $this->config['CLOUDFLARE_DEVELOPMENT_MODE_ENABLED'] ? 'checked' : ''; ?>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
],
|
||||
"psr-4": {
|
||||
"App\\Classes\\": "app/classes/",
|
||||
"App\\Classes\\Http\\": "app/classes/http/",
|
||||
"App\\Controllers\\": "app/controllers/",
|
||||
"App\\Model\\": "app/model/",
|
||||
"App\\Traits\\": "app/traits/"
|
||||
|
||||
+65
-18
@@ -229,6 +229,40 @@ $(document).ready(function() {
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
$('.js-purge').on('click', function(event)
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
if (!confirm('Are you sure you want to continue?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const purgeType = $(this).attr('data-type');
|
||||
const csrfToken = $(this).attr('data-token');
|
||||
|
||||
$.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)
|
||||
{
|
||||
@@ -238,26 +272,39 @@ $(document).ready(function() {
|
||||
return;
|
||||
}
|
||||
|
||||
$.get('/admin/toggle-development-mode').done(function(data)
|
||||
{
|
||||
const response = JSON.parse(data);
|
||||
if (response.success == false) {
|
||||
console.log(data);
|
||||
alert("Development mode could not be enabled!");
|
||||
return;
|
||||
}
|
||||
const dataHref = $(this).attr('data-href');
|
||||
const csrfToken = $(this).attr('data-token');
|
||||
|
||||
if (response.result.value == 'on') {
|
||||
e.target.checked = true;
|
||||
$('#develop-enabled').css('visibility', 'visible');
|
||||
$('#develop-remaining').text('03:00:00');
|
||||
}
|
||||
else {
|
||||
e.target.checked = false;
|
||||
$('#develop-enabled').css('visibility', 'hidden');
|
||||
}
|
||||
$.ajax({
|
||||
url: dataHref,
|
||||
type: 'POST',
|
||||
data: { _token: csrfToken },
|
||||
success: function(data)
|
||||
{
|
||||
if (data == '') {
|
||||
alert("Development mode could not be enabled!");
|
||||
return;
|
||||
}
|
||||
|
||||
alert("Development mode has been set to: '" + response.result.value + "'");
|
||||
const response = JSON.parse(data);
|
||||
if (response.success == false) {
|
||||
console.log(data);
|
||||
alert("Development mode could not be enabled!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.result.value == 'on') {
|
||||
e.target.checked = true;
|
||||
$('#develop-enabled').css('visibility', 'visible');
|
||||
$('#develop-remaining').text('03:00:00');
|
||||
}
|
||||
else {
|
||||
e.target.checked = false;
|
||||
$('#develop-enabled').css('visibility', 'hidden');
|
||||
}
|
||||
|
||||
alert("Development mode has been set to: '" + response.result.value + "'");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ return [
|
||||
['/admin', 'AdminController', '', ''],
|
||||
['/admin/cache', 'CacheController', 'cache', ''],
|
||||
['/admin/toggle', 'AdminController', 'toggle', ''],
|
||||
['/admin/toggle-development-mode', 'CacheController', 'development', ''],
|
||||
['/admin/cache/purge', 'CacheController', 'purge', ''],
|
||||
['/admin/cache/toggle', 'CacheController', 'toggle', ''],
|
||||
['/admin/syntax-highlighting', 'AdminController', 'syntax', ''],
|
||||
['/test', 'TestController', '', ''],
|
||||
// ["", "", "", ""],
|
||||
|
||||
Reference in New Issue
Block a user