| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- <?php
- // +----------------------------------------------------------------------
- // | saiadmin [ saiadmin快速开发框架 ]
- // +----------------------------------------------------------------------
- // | Author: sai <1430792918@qq.com>
- // +----------------------------------------------------------------------
- namespace plugin\saiadmin\utils\code;
- use Twig\TwigFilter;
- use Twig\Environment;
- use Twig\Loader\FilesystemLoader;
- use plugin\saiadmin\exception\ApiException;
- /**
- * 代码生成引擎
- */
- class CodeEngine
- {
- /**
- * @var array 值栈
- */
- private array $value = [];
- /**
- * 模板名称
- * @var string
- */
- private string $stub = 'saiadmin';
- /**
- * 获取配置文件
- * @return string[]
- */
- private static function _getConfig(): array
- {
- return [
- 'template_path' => base_path().DIRECTORY_SEPARATOR.'plugin'.DIRECTORY_SEPARATOR.'saiadmin'.DIRECTORY_SEPARATOR.'utils'.DIRECTORY_SEPARATOR.'code'.DIRECTORY_SEPARATOR.'stub',
- 'generate_path' => runtime_path().DIRECTORY_SEPARATOR.'code_engine'.DIRECTORY_SEPARATOR.'saiadmin',
- ];
- }
- /**
- * 初始化
- * @param array $data 数据
- */
- public function __construct(array $data)
- {
- // 读取配置文件
- $config = self::_getConfig();
- // 判断模板是否存在
- if (!is_dir($config['template_path'])) {
- throw new ApiException('模板目录不存在!');
- }
- // 判断文件生成目录是否存在
- if (!is_dir($config['generate_path'])) {
- mkdir($config['generate_path'], 0770, true);
- }
- // 赋值
- $this->value = $data;
- }
- /**
- * 设置模板名称
- * @param $stub
- * @return void
- */
- public function setStub($stub): void
- {
- $this->stub = $stub;
- }
- /**
- * 渲染文件内容
- */
- public function renderContent($path, $filename): string
- {
- $config = self::_getConfig();
- $path = $config['template_path'].DIRECTORY_SEPARATOR.$this->stub.DIRECTORY_SEPARATOR.$path;
- $loader = new FilesystemLoader($path);
- $twig = new Environment($loader);
- $camelFilter = new TwigFilter('camel', function ($value) {
- static $cache = [];
- $key = $value;
- if (isset($cache[$key])) {
- return $cache[$key];
- }
- $value = ucwords(str_replace(['-', '_'], ' ', $value));
- return $cache[$key] = str_replace(' ', '', $value);
- });
- $boolFilter = new TwigFilter('bool', function ($value) {
- if ($value == 1) {
- return 'true';
- } else {
- return 'false';
- }
- });
- $formatFilter = new TwigFilter('formatNumber', function ($value) {
- if (ctype_digit((string)$value)) {
- return $value;
- } else {
- return '1';
- }
- });
- $defaultFilter = new TwigFilter('parseNumber', function ($value) {
- if ($value) {
- return $value;
- } else {
- return 'null';
- }
- });
- $containsFilter = new TwigFilter('str_contains', function ($haystack, $needle) {
- return str_contains($haystack ?? '', $needle ?? '');
- });
- $twig->addFilter($camelFilter);
- $twig->addFilter($boolFilter);
- $twig->addFilter($containsFilter);
- $twig->addFilter($formatFilter);
- $twig->addFilter($defaultFilter);
- return $twig->render($filename, $this->value);
- }
- /**
- * 生成后端文件
- */
- public function generateBackend($action, $content): void
- {
- $outPath = '';
- if ($this->value['template'] == 'app') {
- $rootPath = base_path() . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . $this->value['namespace'];
- } else {
- $rootPath = base_path() . DIRECTORY_SEPARATOR . 'plugin' . DIRECTORY_SEPARATOR . $this->value['namespace'] . DIRECTORY_SEPARATOR . 'app';
- }
- $subPath = '';
- if (!empty($this->value['package_name'])) {
- $subPath = DIRECTORY_SEPARATOR . $this->value['package_name'];
- }
- switch ($action) {
- case 'controller':
- $outPath = $rootPath . DIRECTORY_SEPARATOR . 'controller' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . 'Controller.php';
- break;
- case 'logic':
- $outPath = $rootPath . DIRECTORY_SEPARATOR . 'logic' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . 'Logic.php';
- break;
- case 'model':
- $outPath = $rootPath . DIRECTORY_SEPARATOR . 'model' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . '.php';
- break;
- case 'validate':
- $outPath = $rootPath . DIRECTORY_SEPARATOR . 'validate' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . 'Validate.php';
- break;
- default:
- break;
- }
- if (empty($outPath)) {
- throw new ApiException('文件类型异常,无法生成指定文件!');
- }
- if (!is_dir(dirname($outPath))) {
- mkdir(dirname($outPath), 0777, true);
- }
- file_put_contents($outPath, $content);
- }
- /**
- * 生成前端文件
- */
- public function generateFrontend($action, $content): void
- {
- $rootPath = dirname(base_path()) . DIRECTORY_SEPARATOR . $this->value['generate_path'];
- if (!is_dir($rootPath)) {
- throw new ApiException('前端目录查找失败,必须与后端目录为同级目录!');
- }
- $rootPath = $rootPath . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . $this->value['namespace'];
- $subPath = '';
- if (!empty($this->value['package_name'])) {
- $subPath = DIRECTORY_SEPARATOR . $this->value['package_name'];
- }
- switch ($action) {
- case 'index':
- $outPath = $rootPath . $subPath . DIRECTORY_SEPARATOR . $this->value['business_name'] . DIRECTORY_SEPARATOR . 'index.vue';
- break;
- case 'edit':
- $outPath = $rootPath . $subPath . DIRECTORY_SEPARATOR . $this->value['business_name'] . DIRECTORY_SEPARATOR . 'edit.vue';
- break;
- case 'api':
- $outPath = $rootPath . DIRECTORY_SEPARATOR . 'api' . $subPath . DIRECTORY_SEPARATOR . $this->value['business_name'] . '.js';
- break;
- default:
- break;
- }
- if (empty($outPath)) {
- throw new ApiException('文件类型异常,无法生成指定文件!');
- }
- if (!is_dir(dirname($outPath))) {
- mkdir(dirname($outPath), 0777, true);
- }
- file_put_contents($outPath, $content);
- }
- /**
- * 生成临时文件
- */
- public function generateTemp(): void
- {
- $config = self::_getConfig();
- $rootPath = $config['generate_path'];
- $vuePath = $rootPath . DIRECTORY_SEPARATOR . 'vue' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . $this->value['namespace'];
- $phpPath = $rootPath . DIRECTORY_SEPARATOR . 'php';
- $sqlPath = $rootPath . DIRECTORY_SEPARATOR . 'sql';
- if ($this->value['template'] == 'app') {
- $phpPath = $phpPath . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . $this->value['namespace'];
- } else {
- $phpPath = $phpPath . DIRECTORY_SEPARATOR . 'plugin' . DIRECTORY_SEPARATOR . $this->value['namespace'] . DIRECTORY_SEPARATOR . 'app';
- }
- $subPath = '';
- if (!empty($this->value['package_name'])) {
- $subPath = DIRECTORY_SEPARATOR . $this->value['package_name'];
- }
- $indexOutPath = $vuePath . $subPath . DIRECTORY_SEPARATOR . $this->value['business_name']. DIRECTORY_SEPARATOR . 'index.vue';
- $this->checkPath($indexOutPath);
- $indexContent = $this->renderContent('vue', 'index.stub');
- file_put_contents($indexOutPath, $indexContent);
- $editOutPath = $vuePath . $subPath . DIRECTORY_SEPARATOR . $this->value['business_name']. DIRECTORY_SEPARATOR . 'edit.vue';
- $this->checkPath($editOutPath);
- $editContent = $this->renderContent('vue', 'edit.stub');
- file_put_contents($editOutPath, $editContent);
- $viewOutPath = $vuePath . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . $this->value['business_name'] . '.js';
- $this->checkPath($viewOutPath);
- $viewContent = $this->renderContent('js', 'api.stub');
- file_put_contents($viewOutPath, $viewContent);
- $controllerOutPath = $phpPath . DIRECTORY_SEPARATOR . 'controller' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . 'Controller.php';
- $this->checkPath($controllerOutPath);
- $controllerContent = $this->renderContent('php', 'controller.stub');
- file_put_contents($controllerOutPath, $controllerContent);
- $logicOutPath = $phpPath . DIRECTORY_SEPARATOR . 'logic' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . 'Logic.php';
- $this->checkPath($logicOutPath);
- $logicContent = $this->renderContent('php', 'logic.stub');
- file_put_contents($logicOutPath, $logicContent);
- $validateOutPath = $phpPath . DIRECTORY_SEPARATOR . 'validate' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . 'Validate.php';
- $this->checkPath($validateOutPath);
- $validateContent = $this->renderContent('php', 'validate.stub');
- file_put_contents($validateOutPath, $validateContent);
- $modelOutPath = $phpPath . DIRECTORY_SEPARATOR . 'model' . $subPath . DIRECTORY_SEPARATOR . $this->value['class_name'] . '.php';
- $this->checkPath($modelOutPath);
- $modelContent = $this->renderContent('php', 'model.stub');
- file_put_contents($modelOutPath, $modelContent);
- $sqlOutPath = $sqlPath . DIRECTORY_SEPARATOR . 'sql.sql';
- $this->checkPath($sqlOutPath);
- $sqlContent = $this->renderContent('sql', 'sql.stub');
- file_put_contents($sqlOutPath, $sqlContent);
- }
- /**
- * 检查并生成路径
- * @param $path
- * @return void
- */
- protected function checkPath($path): void
- {
- if (!is_dir(dirname($path))) {
- mkdir(dirname($path), 0777, true);
- }
- }
- }
|