From f4c00c97cae21dd57865fe62b9e4280669428eff Mon Sep 17 00:00:00 2001 From: augushong Date: Wed, 2 Nov 2022 13:38:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=A7=8B=E4=BB=A3=E7=A0=81=E6=89=93?= =?UTF-8?q?=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- app/common/class/phpparser/NodeVisitor.php | 61 +++++ app/common/command/build/Dist.php | 239 ++++++++++++++++++++ app/common/exception/DirFindedException.php | 9 + composer.json | 3 +- composer.lock | 64 +++++- config/console.php | 4 +- 7 files changed, 379 insertions(+), 4 deletions(-) create mode 100644 app/common/class/phpparser/NodeVisitor.php create mode 100644 app/common/command/build/Dist.php create mode 100644 app/common/exception/DirFindedException.php diff --git a/.gitignore b/.gitignore index abdd957..90fa80c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ vendor runtime ul.db /app/tools/controller/Install.php -/app/common/command/curd/migrate_output.php \ No newline at end of file +/app/common/command/curd/migrate_output.php +/dist \ No newline at end of file diff --git a/app/common/class/phpparser/NodeVisitor.php b/app/common/class/phpparser/NodeVisitor.php new file mode 100644 index 0000000..1f4f17a --- /dev/null +++ b/app/common/class/phpparser/NodeVisitor.php @@ -0,0 +1,61 @@ +cmd = $cmd; + $this->name = $name; + } + + public function leaveNode(Node $node) + { + if ($node instanceof Use_) { + + // $this->cmd->addUsedClass($node); + + // return NodeTraverser::REMOVE_NODE; + + + foreach ($node->uses as &$use_item) { + + $name = 'class'; + + $name .= md5($this->name); + + $name .= md5(end($use_item->name->parts)); + + $use_item->alias = new Identifier($name); + } + }else if ($node instanceof Class_){ + + + if(!empty($node->extends)){ + + $name = 'class'; + + $name .= md5($this->name); + + $name .= md5(end($node->extends->parts)); + + $node->extends = new Name($name); + } + } + + return null; + } +} diff --git a/app/common/command/build/Dist.php b/app/common/command/build/Dist.php new file mode 100644 index 0000000..9490b7b --- /dev/null +++ b/app/common/command/build/Dist.php @@ -0,0 +1,239 @@ +setName('build:dist') + ->setDescription('the build:dist command'); + } + + protected function execute(Input $input, Output $output) + { + // 指令输出 + $output->writeln('build:dist'); + + $app_path = App::getRootPath(); + + $dist_path = $app_path . 'dist'; + + PathTools::intiDir($dist_path . '.temp'); + + + $this->distPath = $dist_path; + + $app_adapter = new Local($app_path); + + $app_filesystem = new Filesystem($app_adapter); + + $dist_adapter = new Local($dist_path); + + $dist_filesystem = new Filesystem($dist_adapter); + + $list_dist = $dist_filesystem->listContents(); + + foreach ($list_dist as $file_info) { + if ($file_info['type'] == 'file') { + $dist_filesystem->delete($file_info['path']); + } else { + $dist_filesystem->deleteDir($file_info['path']); + } + } + + $list_content = $app_filesystem->listContents('', true); + foreach ($list_content as $file_info) { + if ($file_info['type'] == 'dir') { + continue; + } + + $file_path = $file_info['path']; + + if ($this->isSkip($file_path)) { + continue; + } + + $file_content = $app_filesystem->read($file_path); + $path_info = pathinfo($file_path); + + if (!$this->isIgnored($file_path)) { + + if (isset($path_info['extension'])) { + if ($path_info['extension'] == 'php') { + $file_content = $this->buildPhpContent($file_content, $file_path); + } + } + } + if (!is_null($file_content)) { + + $dist_filesystem->write($file_path, $file_content); + } + } + + + + + $lib_php_path = $this->distPath . '/lib/index.' . uniqid() . '.php'; + PathTools::intiDir($lib_php_path); + + $prettyPrinter = new Standard(); + + $stmts = array_merge($this->usedClass, $this->packList); + $newCode = $prettyPrinter->prettyPrintFile($stmts); + + file_put_contents($lib_php_path, $newCode); + + $output->info('打包完成'); + } + + public function buildPhpContent($content, $name) + { + + + $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); + + $stmts = $parser->parse($content); + + $is_magic_const_dir = $this->scanForMagicConstDir($stmts); + + if ($is_magic_const_dir) { + return $content; + } + + + $stmts = $this->parseStmts($stmts, $name); + + + + $this->packList = array_merge($this->packList, $stmts); + + return null; + } + + public function addUsedClass(Node $node) + { + if (array_search($node, $this->usedClass)) { + dump('已存在'); + } else { + $this->usedClass[] = $node; + } + } + + public function parseStmts($stmts, $name) + { + + $traverser = new NodeTraverser(); + + $node_visitor = new NodeVisitor($this, $name); + + $traverser->addVisitor($node_visitor); + + $stmts = $traverser->traverse($stmts); + + return $stmts; + } + + public function scanForMagicConstDir($stmts) + { + $is_dir_find = false; + + $traverser = new NodeTraverser(); + $traverser->addVisitor(new class extends NodeVisitorAbstract + { + public function enterNode(Node $node) + { + if ($node instanceof Dir) { + // Clean out the function body + + throw new DirFindedException("finded", 1); + } + } + }); + + try { + + $stmts = $traverser->traverse($stmts); + } catch (DirFindedException $th) { + + $is_dir_find = true; + } + + return $is_dir_find; + } + + public function isSkip($path) + { + + $skip_path = [ + '/^\.git/', + '/^dist/', + '/^runtime/', + ]; + + foreach ($skip_path as $rule) { + if (preg_match($rule, $path)) { + return true; + } + } + + return false; + } + + public function isIgnored($path) + { + + $ignore_path = [ + '/^vendor/', + '/^config/', + '/event\.php/', + '/middleware\.php/', + '/provider\.php/', + '/service\.php/', + '/^app\/.*\/config\/.*/', + '/config.php/', + '/^public\/index\.php/', + '/^public\/router\.php/', + ]; + + foreach ($ignore_path as $rule) { + + if (preg_match($rule, $path)) { + return true; + } + } + + return false; + } +} diff --git a/app/common/exception/DirFindedException.php b/app/common/exception/DirFindedException.php new file mode 100644 index 0000000..315773f --- /dev/null +++ b/app/common/exception/DirFindedException.php @@ -0,0 +1,9 @@ +=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" + }, + "time": "2022-09-04T07:30:47+00:00" + }, { "name": "overtrue/flysystem-qiniu", "version": "1.0.6", diff --git a/config/console.php b/config/console.php index 0652cad..ace3868 100644 --- a/config/console.php +++ b/config/console.php @@ -6,6 +6,7 @@ use app\common\command\admin\Clear; use app\common\command\admin\Version; use app\common\command\admin\ResetPassword; +use app\common\command\build\Dist; use app\common\command\curd\Migrate; use app\common\command\Timer; @@ -19,6 +20,7 @@ return [ Timer::class, Version::class, Migrate::class, - Clear::class + Clear::class, + Dist::class ], ];