diff --git a/src/AutoReload.php b/src/AutoReload.php new file mode 100644 index 0000000..d091814 --- /dev/null +++ b/src/AutoReload.php @@ -0,0 +1,166 @@ + [ + * [\Simps\Utils\AutoReload::class, 'start'], + * ], + * Class AutoReload. + */ +class AutoReload +{ + /** + * @var Server + */ + protected $server; + + /** + * @var Process + */ + protected $hotReloadProcess; + + /** + * 文件类型. + * @var array + */ + protected $reloadFileTypes = ['.php' => true]; + + /** + * 监听文件. + * @var array + */ + protected $lastFileList = []; + + /** + * 是否正在重载. + * @var bool + */ + protected $reloading = false; + + /** + * AutoReload constructor. + */ + public function __construct(Server $server) + { + $this->server = $server; + } + + /** + * start. + * @return Process + */ + public static function start(Server $server) + { + $autoLoad = new self($server); + + $autoLoad->hotReloadProcess = new Process([$autoLoad, 'hotReloadProcessCallBack'], false, 2, false); + + return $autoLoad->hotReloadProcess; + } + + /** + * hotReloadProcessCallBack. + */ + public function hotReloadProcessCallBack(Process $worker) + { + $this->hotReloadProcess->signal(SIGUSR1, [$this, 'signalCallBack']); + + $this->run(BASE_PATH); + + $currentOS = PHP_OS; + + $currentPID = $this->hotReloadProcess->pid; + + echoSuccess("自动重载代码初始化({$currentOS})PID: {$currentPID} ..."); + } + + public function signalCallBack() + { + echoSuccess('重载时间: ' . date('Y-m-d H:i:s')); + + $res = $this->server->reload(); + + $res ? echoSuccess('重载成功') : echoError('重载失败'); + } + + /** + * 添加文件类型 + * addFileType. + * @param $type + * @return $this + */ + public function addFileType($type) + { + $type = trim($type, '.'); + + $this->reloadFileTypes['.' . $type] = true; + + return $this; + } + + /** + * watch. + * @param $dir + */ + public function watch($dir) + { + $files = FileHelper::scanDirectory($dir); + + $dirtyList = []; + + foreach ($files as $file) { + //检测文件类型 + $fileType = strrchr($file, '.'); + if (isset($this->reloadFileTypes[$fileType])) { + $fileInfo = new \SplFileInfo($file); + $mtime = $fileInfo->getMTime(); + $inode = $fileInfo->getInode(); + $dirtyList[$inode] = $mtime; + } + } + + // 当数组中出现脏值则发生了文件变更 + if (array_diff_assoc($dirtyList, $this->lastFileList)) { + $this->lastFileList = $dirtyList; + if ($this->reloading) { + $this->sendReloadSignal(); + } + } + + $this->reloading = true; + } + + /** + * run. + * @param mixed $dir + */ + public function run($dir) + { + $this->watch($dir); + + Timer::tick(1000, function () use ($dir) { + $this->watch($dir); + }); + } + + /** + * sendReloadSignal. + */ + protected function sendReloadSignal() + { + Process::kill($this->hotReloadProcess->pid, SIGUSR1); + } +} diff --git a/src/FileHelper.php b/src/FileHelper.php new file mode 100644 index 0000000..2097950 --- /dev/null +++ b/src/FileHelper.php @@ -0,0 +1,203 @@ + $value) { + if (substr($value, -1) == '/') { + mkdir($value); + } else { + file_put_contents($value, ''); + } + } + } + + /** + * removeDirectory. + * @param $dir + * @param array $options + */ + public static function removeDirectory($dir, $options = []) + { + if (! is_dir($dir)) { + return; + } + if (! empty($options['traverseSymlinks']) || ! is_link($dir)) { + if (! ($handle = opendir($dir))) { + return; + } + while (($file = readdir($handle)) !== false) { + if ($file === '.' || $file === '..') { + continue; + } + $path = $dir . DIRECTORY_SEPARATOR . $file; + if (is_dir($path)) { + static::removeDirectory($path, $options); + } else { + static::unlink($path); + } + } + closedir($handle); + } + if (is_link($dir)) { + static::unlink($dir); + } else { + rmdir($dir); + } + } + + /** + * unlink. + * @param $path + * @return bool + */ + public static function unlink($path) + { + $isWindows = DIRECTORY_SEPARATOR === '\\'; + + if (! $isWindows) { + return unlink($path); + } + + if (is_link($path) && is_dir($path)) { + return rmdir($path); + } + + try { + return unlink($path); + } catch (\Exception $e) { + return false; + } + } + + /** + * getMimeType. + * @param $file + * @return null|mixed + */ + public static function getMimeType($file) + { + if (extension_loaded('fileinfo')) { + $info = finfo_open(FILEINFO_MIME_TYPE); + if ($info) { + $result = finfo_file($info, $file); + finfo_close($info); + + if ($result !== false) { + return $result; + } + } + } + return null; + } +} diff --git a/src/functions.php b/src/functions.php index 84cfbfe..69b1079 100644 --- a/src/functions.php +++ b/src/functions.php @@ -44,3 +44,37 @@ function env($key, $default = null) return container()->get(\Simps\Utils\Env::class)->get($key, $default); } } + +if (! function_exists('printEol')) { + /** + * printEol. + * @param $expression + */ + function printEol($expression) + { + print_r($expression); + echo PHP_EOL; + } +} + +if (! function_exists('echoSuccess')) { + /** + * printEol. + * @param $msg + */ + function echoSuccess($msg) + { + printEol('[' . date('Y-m-d H:i:s') . '] [INFO] ' . "\033[32m{$msg}\033[0m"); + } +} + +if (! function_exists('echoError')) { + /** + * printEol. + * @param $msg + */ + function echoError($msg) + { + printEol('[' . date('Y-m-d H:i:s') . '] [ERROR] ' . "\033[31m{$msg}\033[0m"); + } +}