You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							210 lines
						
					
					
						
							5.0 KiB
						
					
					
				
			
		
		
	
	
							210 lines
						
					
					
						
							5.0 KiB
						
					
					
				<?php | 
						|
 | 
						|
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 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 (!$this->validatePostRequest()) { | 
						|
			return; | 
						|
		} | 
						|
 | 
						|
		$token = Config::c('CLOUDFLARE_TOKEN'); | 
						|
		$zone = Config::c('CLOUDFLARE_ZONE'); | 
						|
 | 
						|
		$url = "https://api.cloudflare.com/client/v4/zones/$zone/settings/development_mode"; | 
						|
 | 
						|
		$config = $this->getConfigValues(); | 
						|
		$currentState = $config['CLOUDFLARE_DEVELOPMENT_MODE_ENABLED']; | 
						|
 | 
						|
		$response = (new Http)->withToken($token) | 
						|
							  ->asJson() | 
						|
							  ->acceptJson() | 
						|
							  ->patch($url, [ | 
						|
								  'value' => $currentState == '1' ? 'off' : 'on', | 
						|
							  ]); | 
						|
 | 
						|
		$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 | 
						|
	{ | 
						|
		$result = []; | 
						|
 | 
						|
		$config = [ | 
						|
			'CLOUDFLARE_DEVELOPMENT_MODE_ENABLED' => '0', | 
						|
			'CLOUDFLARE_DEVELOPMENT_MODE_UPDATED_AT' => '', | 
						|
			'CLOUDFLARE_DEVELOPMENT_MODE_EXPIRES_IN' => '', | 
						|
		]; | 
						|
 | 
						|
		foreach ($config as $key => $value) { | 
						|
			$result[$key] = ConfigModel::firstOrCreate( | 
						|
				['key' => $key], | 
						|
				['value' => $value] | 
						|
			)->value; | 
						|
		} | 
						|
 | 
						|
		if ($result['CLOUDFLARE_DEVELOPMENT_MODE_ENABLED']) { | 
						|
			$expiresIn = $result['CLOUDFLARE_DEVELOPMENT_MODE_EXPIRES_IN']; | 
						|
			$updatedAt = $result['CLOUDFLARE_DEVELOPMENT_MODE_UPDATED_AT']; | 
						|
 | 
						|
			$expiresAtObject = new \DateTime($updatedAt); | 
						|
			$expiresAt = $expiresAtObject | 
						|
					   ->modify("+ $expiresIn seconds") | 
						|
					   ->format('Y-m-d H:i:s'); | 
						|
			$nowObject = new \DateTime('now'); | 
						|
			$now = $nowObject->format('Y-m-d H:i:s'); | 
						|
 | 
						|
			if ($now >= $expiresAt) { | 
						|
				ConfigModel::updateOrCreate( | 
						|
					['key' => 'CLOUDFLARE_DEVELOPMENT_MODE_ENABLED'], | 
						|
					['value' => 0]); | 
						|
				$result['CLOUDFLARE_DEVELOPMENT_MODE_ENABLED'] = 0; | 
						|
			} | 
						|
			else { | 
						|
				$result['enabled-remaining'] = $expiresAtObject->modify( | 
						|
					'- ' . $nowObject->getTimestamp() . ' seconds' | 
						|
				)->format('H:i:s'); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		return $result; | 
						|
	} | 
						|
 | 
						|
	private static function saveConfigValues(string $response): void | 
						|
	{ | 
						|
		$decodedResponse = json_decode($response, true); | 
						|
		if ($decodedResponse['success'] == true) { | 
						|
			$state = $decodedResponse['result']['value']; | 
						|
			$expiresIn = $decodedResponse['result']['time_remaining']; | 
						|
			$updatedAt = $decodedResponse['result']['modified_on']; | 
						|
 | 
						|
			$updatedAtFormatted = (new \DateTime($updatedAt))->format('Y-m-d H:i:s'); | 
						|
 | 
						|
			ConfigModel::updateOrCreate( | 
						|
				['key' => 'CLOUDFLARE_DEVELOPMENT_MODE_ENABLED'], | 
						|
				['value' => $state == 'on' ? 1 : 0]); | 
						|
 | 
						|
			ConfigModel::updateOrCreate( | 
						|
				['key' => 'CLOUDFLARE_DEVELOPMENT_MODE_EXPIRES_IN'], | 
						|
				['value' => $expiresIn]); | 
						|
 | 
						|
			ConfigModel::updateOrCreate( | 
						|
				['key' => 'CLOUDFLARE_DEVELOPMENT_MODE_UPDATED_AT'], | 
						|
				['value' => $updatedAtFormatted]); | 
						|
		} | 
						|
	} | 
						|
 | 
						|
}
 | 
						|
 |