add trashes

This commit is contained in:
Diskette Guy
2025-07-21 15:40:51 +07:00
parent c8f2944770
commit 07171f5b5a
848 changed files with 134166 additions and 0 deletions
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\HotReloader;
use CodeIgniter\Exceptions\FrameworkException;
use Config\Toolbar;
use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
/**
* @internal
* @see \CodeIgniter\HotReloader\DirectoryHasherTest
*/
final class DirectoryHasher
{
/**
* Generates an md5 value of all directories that are watched by the
* Hot Reloader, as defined in the Config\Toolbar.
*
* This is the current app fingerprint.
*/
public function hash(): string
{
return md5(implode('', $this->hashApp()));
}
/**
* Generates an array of md5 hashes for all directories that are
* watched by the Hot Reloader, as defined in the Config\Toolbar.
*/
public function hashApp(): array
{
$hashes = [];
$watchedDirectories = config(Toolbar::class)->watchedDirectories;
foreach ($watchedDirectories as $directory) {
if (is_dir(ROOTPATH . $directory)) {
$hashes[$directory] = $this->hashDirectory(ROOTPATH . $directory);
}
}
return array_unique(array_filter($hashes));
}
/**
* Generates an md5 hash of a given directory and all of its files
* that match the watched extensions defined in Config\Toolbar.
*/
public function hashDirectory(string $path): string
{
if (! is_dir($path)) {
throw FrameworkException::forInvalidDirectory($path);
}
$directory = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$filter = new IteratorFilter($directory);
$iterator = new RecursiveIteratorIterator($filter);
$hashes = [];
foreach ($iterator as $file) {
if ($file->isFile()) {
$hashes[] = md5_file($file->getRealPath());
}
}
return md5(implode('', $hashes));
}
}
@@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\HotReloader;
/**
* @internal
*/
final class HotReloader
{
public function run(): void
{
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
ini_set('zlib.output_compression', 'Off');
header('Cache-Control: no-store');
header('Content-Type: text/event-stream');
header('Access-Control-Allow-Methods: GET');
ob_end_clean();
set_time_limit(0);
$hasher = new DirectoryHasher();
$appHash = $hasher->hash();
while (true) {
if (connection_status() !== CONNECTION_NORMAL || connection_aborted() === 1) {
break;
}
$currentHash = $hasher->hash();
// If hash has changed, tell the browser to reload.
if ($currentHash !== $appHash) {
$appHash = $currentHash;
$this->sendEvent('reload', ['time' => date('Y-m-d H:i:s')]);
break;
}
if (mt_rand(1, 10) > 8) {
$this->sendEvent('ping', ['time' => date('Y-m-d H:i:s')]);
}
sleep(1);
}
}
/**
* Send an event to the browser.
*/
private function sendEvent(string $event, array $data): void
{
echo "event: {$event}\n";
echo 'data: ' . json_encode($data) . "\n\n";
ob_flush();
flush();
}
}
@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\HotReloader;
use Config\Toolbar;
use RecursiveFilterIterator;
use RecursiveIterator;
/**
* @internal
*
* @psalm-suppress MissingTemplateParam
*/
final class IteratorFilter extends RecursiveFilterIterator implements RecursiveIterator
{
private array $watchedExtensions = [];
public function __construct(RecursiveIterator $iterator)
{
parent::__construct($iterator);
$this->watchedExtensions = config(Toolbar::class)->watchedExtensions;
}
/**
* Apply filters to the files in the iterator.
*/
public function accept(): bool
{
if (! $this->current()->isFile()) {
return true;
}
$filename = $this->current()->getFilename();
// Skip hidden files and directories.
if ($filename[0] === '.') {
return false;
}
// Only consume files of interest.
$ext = trim(strtolower($this->current()->getExtension()), '. ');
return in_array($ext, $this->watchedExtensions, true);
}
}