瀏覽代碼

feat: 添加.gitignore Extension.php 模版

runphp 6 月之前
父節點
當前提交
01cd40c4c0

+ 83 - 0
src/Generator/GitignoreGenerator.php

@@ -0,0 +1,83 @@
+<?php
+declare(strict_types=1);
+
+namespace SixShop\MakerBundle\Generator;
+
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class GitignoreGenerator
+{
+    private string $templatePath;
+
+    public function __construct()
+    {
+        $this->templatePath = __DIR__ . '/../../templates/.gitignore.tpl.php';
+    }
+
+    /**
+     * 生成.gitignore内容
+     */
+    public function generateContent(): string
+    {
+        if (!file_exists($this->templatePath)) {
+            throw new \RuntimeException('模板文件不存在: ' . $this->templatePath);
+        }
+
+        // 生成.gitignore内容
+        ob_start();
+        include $this->templatePath;
+        return ob_get_clean();
+    }
+
+    /**
+     * 保存.gitignore文件到指定目录
+     */
+    public function saveGitignoreFile(string $packageName, string $content, SymfonyStyle $io): bool
+    {
+        // 获取vendor上级目录并构建路径: runtime/extension/{package-name}/
+        $vendorDir = dirname(__DIR__, 5); // 从当前文件位置向上5级到vendor上级目录
+        $extensionDir = $vendorDir . '/runtime/extension/' . $packageName;
+
+        // 确保目录存在
+        if (!is_dir($extensionDir)) {
+            if (!mkdir($extensionDir, 0755, true)) {
+                $io->error('无法创建目录: ' . $extensionDir);
+                return false;
+            }
+        }
+
+        $outputPath = $extensionDir . '/.gitignore';
+        if (file_put_contents($outputPath, $content) !== false) {
+            $io->success('.gitignore 文件已成功生成: ' . $outputPath);
+            return true;
+        } else {
+            $io->error('无法写入文件: ' . $outputPath);
+            return false;
+        }
+    }
+
+    /**
+     * 完整的生成和保存流程
+     */
+    public function createGitignore(string $packageName, SymfonyStyle $io): bool
+    {
+        try {
+            // 生成内容
+            $content = $this->generateContent();
+
+            // 输出生成的内容
+            $io->section('生成的 .gitignore 内容:');
+            $io->text($content);
+
+            // 询问是否保存文件
+            if ($io->confirm('是否将内容保存到 .gitignore 文件?', true)) {
+                return $this->saveGitignoreFile($packageName, $content, $io);
+            }
+
+            return true;
+        } catch (\Exception $e) {
+            $io->error('生成 .gitignore 时发生错误: ' . $e->getMessage());
+            return false;
+        }
+    }
+}

+ 158 - 0
src/Generator/PhpCodeGenerator.php

@@ -0,0 +1,158 @@
+<?php
+declare(strict_types=1);
+
+namespace SixShop\MakerBundle\Generator;
+
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class PhpCodeGenerator
+{
+    private string $templatesPath;
+
+    public function __construct()
+    {
+        $this->templatesPath = __DIR__ . '/../../templates';
+    }
+
+    /**
+     * 生成PHP代码文件
+     */
+    public function generatePhpFiles(string $packageName, string $namespace, string $id, string $description, SymfonyStyle $io): bool
+    {
+        try {
+            $basePath = $this->getBasePath($packageName);
+            
+            // 准备模板变量
+            $variables = [
+                'namespace' => $namespace,
+                'name' => $packageName,
+                'id' => $id,
+                'description' => $description
+            ];
+
+            // 获取所有需要生成的PHP文件模板
+            $templateFiles = $this->getTemplateFiles();
+            
+            $io->section('生成PHP代码文件:');
+            
+            foreach ($templateFiles as $templateFile) {
+                if (!$this->generateFileFromTemplate($templateFile, $basePath, $variables, $io)) {
+                    return false;
+                }
+            }
+            
+            $io->success('PHP代码文件生成完成!');
+            return true;
+            
+        } catch (\Exception $e) {
+            $io->error('生成PHP代码文件时发生错误: ' . $e->getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 获取扩展基础路径
+     */
+    private function getBasePath(string $packageName): string
+    {
+        $vendorDir = dirname(__DIR__, 5);
+        return $vendorDir . '/runtime/extension/' . $packageName;
+    }
+
+    /**
+     * 获取所有模板文件
+     */
+    private function getTemplateFiles(): array
+    {
+        $templates = [];
+        $this->scanTemplateDirectory($this->templatesPath, '', $templates);
+        return $templates;
+    }
+
+    /**
+     * 递归扫描模板目录
+     */
+    private function scanTemplateDirectory(string $directory, string $relativePath, array &$templates): void
+    {
+        if (!is_dir($directory)) {
+            return;
+        }
+
+        $items = scandir($directory);
+        foreach ($items as $item) {
+            if ($item === '.' || $item === '..') {
+                continue;
+            }
+
+            $fullPath = $directory . '/' . $item;
+            $currentRelativePath = $relativePath ? $relativePath . '/' . $item : $item;
+
+            if (is_dir($fullPath)) {
+                // 递归扫描子目录
+                $this->scanTemplateDirectory($fullPath, $currentRelativePath, $templates);
+            } elseif (is_file($fullPath) && str_ends_with($item, '.php.tpl.php')) {
+                // 添加模板文件
+                $templates[] = [
+                    'template' => $currentRelativePath,
+                    'target' => str_replace('.tpl.php', '', $currentRelativePath),
+                    'fullPath' => $fullPath
+                ];
+            }
+        }
+    }
+
+    /**
+     * 从模板生成文件
+     */
+    private function generateFileFromTemplate(array $templateInfo, string $basePath, array $variables, SymfonyStyle $io): bool
+    {
+        $templatePath = $templateInfo['fullPath'];
+        $targetPath = $basePath . '/' . $templateInfo['target'];
+        
+        // 确保目标目录存在
+        $targetDir = dirname($targetPath);
+        if (!is_dir($targetDir)) {
+            if (!mkdir($targetDir, 0755, true)) {
+                $io->error("无法创建目录: $targetDir");
+                return false;
+            }
+        }
+
+        // 如果文件已存在,询问是否覆盖
+        if (file_exists($targetPath)) {
+            if (!$io->confirm("文件已存在: {$templateInfo['target']},是否覆盖?", false)) {
+                $io->text("跳过文件: {$templateInfo['target']}");
+                return true;
+            }
+        }
+
+        // 提取变量到当前作用域
+        // 命名空间双斜杆需要改为单斜杠
+        $namespace = str_replace('\\\\', '\\', $variables['namespace']);
+        $name = $variables['name'];
+        $id = $variables['id'];
+        $description = $variables['description'];
+
+        // 生成文件内容
+        ob_start();
+        include $templatePath;
+        $content = ob_get_clean();
+
+        // 写入文件
+        if (file_put_contents($targetPath, $content) !== false) {
+            $io->text("✓ 生成文件: {$templateInfo['target']}");
+            return true;
+        } else {
+            $io->error("✗ 无法写入文件: {$templateInfo['target']}");
+            return false;
+        }
+    }
+
+    /**
+     * 获取模板文件列表(用于预览)
+     */
+    public function getTemplateList(): array
+    {
+        return $this->getTemplateFiles();
+    }
+}

+ 24 - 0
src/Maker.php

@@ -10,6 +10,8 @@ use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Style\SymfonyStyle;
 use SixShop\MakerBundle\Generator\ComposerGenerator;
 use SixShop\MakerBundle\Generator\DirectoryGenerator;
+use SixShop\MakerBundle\Generator\GitignoreGenerator;
+use SixShop\MakerBundle\Generator\PhpCodeGenerator;
 
 class Maker extends Command
 {
@@ -18,12 +20,16 @@ class Maker extends Command
     
     private ComposerGenerator $composerGenerator;
     private DirectoryGenerator $directoryGenerator;
+    private GitignoreGenerator $gitignoreGenerator;
+    private PhpCodeGenerator $phpCodeGenerator;
     
     public function __construct()
     {
         parent::__construct();
         $this->composerGenerator = new ComposerGenerator();
         $this->directoryGenerator = new DirectoryGenerator();
+        $this->gitignoreGenerator = new GitignoreGenerator();
+        $this->phpCodeGenerator = new PhpCodeGenerator();
     }
 
     protected function configure(): void
@@ -59,6 +65,24 @@ class Maker extends Command
             return Command::FAILURE;
         }
         
+        // 生成 .gitignore 文件
+        $io->section('生成 .gitignore 文件');
+        if (!$this->gitignoreGenerator->createGitignore($packageInfo['packageName'], $io)) {
+            return Command::FAILURE;
+        }
+        
+        // 生成 PHP 代码文件
+        $io->section('生成 PHP 代码文件');
+        if (!$this->phpCodeGenerator->generatePhpFiles(
+            $packageInfo['packageName'],
+            $packageInfo['namespace'],
+            $packageInfo['id'],
+            $packageInfo['description'],
+            $io
+        )) {
+            return Command::FAILURE;
+        }
+        
         $io->success('扩展创建完成!');
         return Command::SUCCESS;
     }

+ 50 - 0
templates/.gitignore.tpl.php

@@ -0,0 +1,50 @@
+# Dependencies
+/vendor/
+/node_modules/
+
+# Environment files
+.env
+.env.local
+.env.*.local
+
+# IDE files
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# OS files
+.DS_Store
+Thumbs.db
+
+# Log files
+*.log
+/logs/
+
+# Cache and temporary files
+/cache/
+/tmp/
+*.tmp
+
+# Build artifacts
+/dist/
+/build/
+
+# PHP specific
+composer.phar
+/runtime/
+*.cache
+
+# Test coverage
+/coverage/
+/.phpunit.result.cache
+
+# Database
+*.sqlite
+*.db
+
+# Generated files
+/public/mix-manifest.json
+/public/hot
+/public/storage
+/storage/*.key

+ 1 - 1
templates/composer.json.tpl.php

@@ -19,7 +19,7 @@
   "license": "MIT",
   "autoload": {
     "psr-4": {
-      "<?= $namespace ?>": "src"
+      "<?= $namespace ?>\\": "src"
     }
   },
   "extra": {

+ 16 - 0
templates/src/Extension.php.tpl.php

@@ -0,0 +1,16 @@
+<?= "<?php\n" ?>
+declare(strict_types=1);
+
+namespace <?= $namespace ?>;
+
+use SixShop\Core\ExtensionAbstract;
+
+class Extension extends ExtensionAbstract
+{
+    public const string EXTENSION_ID = '<?= $id ?>';
+
+    protected function getBaseDir(): string
+    {
+        return dirname(__DIR__);
+    }
+}