From 4cef8e78424d3eddd2170ec98713529ed6dea5cf Mon Sep 17 00:00:00 2001
From: zds <49744633+zds-s@users.noreply.github.com>
Date: Mon, 7 Oct 2024 22:03:32 +0800
Subject: [PATCH] Initial 3.0 Component
---
.gitattributes | 2 +
.github/workflows/close-pull-request.yml | 15 ++++
.github/workflows/release.yml | 25 ++++++
.gitignore | 5 ++
Application.php | 42 ++++++++++
Config.php | 49 ++++++++++++
Context.php | 52 +++++++++++++
Entity/ColumnEntity.php | 98 ++++++++++++++++++++++++
Entity/GeneratorEntity.php | 25 ++++++
Entity/TableEntity.php | 58 ++++++++++++++
Enums/TableColumnType.php | 29 +++++++
Event/GeneratorStaringEvent.php | 22 ++++++
Factory.php | 21 +++++
GeneratorInterface.php | 24 ++++++
LICENSE | 21 +++++
Processor/AbstractAstProcessor.php | 61 +++++++++++++++
Processor/AbstractProcessor.php | 44 +++++++++++
Processor/ControllerProcessor.php | 82 ++++++++++++++++++++
Processor/ProcessorInterface.php | 21 +++++
Processor/stubs/controller.blade.php | 26 +++++++
README.md | 3 +
composer.json | 26 +++++++
22 files changed, 751 insertions(+)
create mode 100644 .gitattributes
create mode 100644 .github/workflows/close-pull-request.yml
create mode 100644 .github/workflows/release.yml
create mode 100644 .gitignore
create mode 100644 Application.php
create mode 100644 Config.php
create mode 100644 Context.php
create mode 100644 Entity/ColumnEntity.php
create mode 100644 Entity/GeneratorEntity.php
create mode 100644 Entity/TableEntity.php
create mode 100644 Enums/TableColumnType.php
create mode 100644 Event/GeneratorStaringEvent.php
create mode 100644 Factory.php
create mode 100644 GeneratorInterface.php
create mode 100644 LICENSE
create mode 100644 Processor/AbstractAstProcessor.php
create mode 100644 Processor/AbstractProcessor.php
create mode 100644 Processor/ControllerProcessor.php
create mode 100644 Processor/ProcessorInterface.php
create mode 100644 Processor/stubs/controller.blade.php
create mode 100644 README.md
create mode 100644 composer.json
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..ce244ab
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+/tests export-ignore
+/.github export-ignore
\ No newline at end of file
diff --git a/.github/workflows/close-pull-request.yml b/.github/workflows/close-pull-request.yml
new file mode 100644
index 0000000..7239c0b
--- /dev/null
+++ b/.github/workflows/close-pull-request.yml
@@ -0,0 +1,15 @@
+name: Close Pull Request
+
+permissions: write-all
+
+on:
+ pull_request_target:
+ types: [ opened ]
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: superbrothers/close-pull-request@v3
+ with:
+ comment: "Hi, this is a READ-ONLY repository, please submit your PR on the https://github.com/mineadmin/components repository.
This Pull Request will close automatically.
Thanks! "
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..ae1823d
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,25 @@
+on:
+ push:
+ tags:
+ - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
+
+name: Release
+permissions: write-all
+
+jobs:
+ release:
+ name: Release
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Create Release
+ id: create_release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ release_name: Release ${{ github.ref }}
+ draft: false
+ prerelease: false
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7cb10a6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+composer.lock
+.idea
+vendor
+*.cache
+runtime
\ No newline at end of file
diff --git a/Application.php b/Application.php
new file mode 100644
index 0000000..ffe7777
--- /dev/null
+++ b/Application.php
@@ -0,0 +1,42 @@
+dispatch(new GeneratorStaringEvent($context));
+ foreach ($this->config->getProcessors() as $processor) {
+ $context->getProcessors()->push($processor);
+ $context->getEntities()->push($processor->process($context));
+ }
+ return $context->getEntities()->all();
+ }
+
+ private function dispatch(object $event): void
+ {
+ $this->dispatcher->dispatch($event);
+ }
+}
diff --git a/Config.php b/Config.php
new file mode 100644
index 0000000..efba844
--- /dev/null
+++ b/Config.php
@@ -0,0 +1,49 @@
+config;
+ }
+
+ public function isEnable(): bool
+ {
+ return (bool) $this->config->get('generator.enable', false);
+ }
+
+ /**
+ * @return iterable
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function getProcessors(): iterable
+ {
+ foreach ($this->config->get('generator.processors', []) as $processor) {
+ yield $this->container->get($processor);
+ }
+ }
+}
diff --git a/Context.php b/Context.php
new file mode 100644
index 0000000..6878e26
--- /dev/null
+++ b/Context.php
@@ -0,0 +1,52 @@
+config;
+ }
+
+ public function getTable(): TableEntity
+ {
+ return $this->table;
+ }
+
+ public function getExtra(): Collection
+ {
+ return $this->extra;
+ }
+
+ public function getProcessors(): Collection
+ {
+ return $this->processors;
+ }
+
+ public function getEntities(): Collection
+ {
+ return $this->entities;
+ }
+}
diff --git a/Entity/ColumnEntity.php b/Entity/ColumnEntity.php
new file mode 100644
index 0000000..fde97d2
--- /dev/null
+++ b/Entity/ColumnEntity.php
@@ -0,0 +1,98 @@
+columnName;
+ }
+
+ public function setColumnName(string $columnName): void
+ {
+ $this->columnName = $columnName;
+ }
+
+ public function getColumnType(): TableColumnType
+ {
+ return $this->columnType;
+ }
+
+ public function setColumnType(TableColumnType $columnType): void
+ {
+ $this->columnType = $columnType;
+ }
+
+ public function getColumnComment(): string
+ {
+ return $this->columnComment;
+ }
+
+ public function setColumnComment(string $columnComment): void
+ {
+ $this->columnComment = $columnComment;
+ }
+
+ public function isNullable(): bool
+ {
+ return $this->isNullable;
+ }
+
+ public function setIsNullable(bool $isNullable): void
+ {
+ $this->isNullable = $isNullable;
+ }
+
+ public function isPrimary(): bool
+ {
+ return $this->isPrimary;
+ }
+
+ public function setIsPrimary(bool $isPrimary): void
+ {
+ $this->isPrimary = $isPrimary;
+ }
+
+ public function isUnique(): bool
+ {
+ return $this->isUnique;
+ }
+
+ public function setIsUnique(bool $isUnique): void
+ {
+ $this->isUnique = $isUnique;
+ }
+
+ public function isAutoIncrement(): bool
+ {
+ return $this->isAutoIncrement;
+ }
+
+ public function setIsAutoIncrement(bool $isAutoIncrement): void
+ {
+ $this->isAutoIncrement = $isAutoIncrement;
+ }
+}
diff --git a/Entity/GeneratorEntity.php b/Entity/GeneratorEntity.php
new file mode 100644
index 0000000..7fe7c3e
--- /dev/null
+++ b/Entity/GeneratorEntity.php
@@ -0,0 +1,25 @@
+template;
+ }
+}
diff --git a/Entity/TableEntity.php b/Entity/TableEntity.php
new file mode 100644
index 0000000..b2d3fa4
--- /dev/null
+++ b/Entity/TableEntity.php
@@ -0,0 +1,58 @@
+tableName;
+ }
+
+ public function setTableName(string $tableName): void
+ {
+ $this->tableName = $tableName;
+ }
+
+ public function getTableComment(): string
+ {
+ return $this->tableComment;
+ }
+
+ public function setTableComment(string $tableComment): void
+ {
+ $this->tableComment = $tableComment;
+ }
+
+ /**
+ * @return ColumnEntity[]
+ */
+ public function getColumns(): array
+ {
+ return $this->columns;
+ }
+
+ /**
+ * @param ColumnEntity[] $columns
+ */
+ public function setColumns(array $columns): void
+ {
+ $this->columns = $columns;
+ }
+}
diff --git a/Enums/TableColumnType.php b/Enums/TableColumnType.php
new file mode 100644
index 0000000..9439b88
--- /dev/null
+++ b/Enums/TableColumnType.php
@@ -0,0 +1,29 @@
+astParser->parse(file_get_contents($path));
+ $originTokens = $this->lexer->getTokens();
+ $this->handleAst($c, $traverser, $originStmts, $originTokens, $path, $namespace, $className);
+ $newStmts = $traverser->traverse($originStmts);
+ return $this->printer->printFormatPreserving($newStmts, $originStmts, $originTokens);
+ }
+ return $this->handleCreate($c, $path, $namespace, $className);
+ }
+
+ abstract protected function handleAst(Context $c, NodeTraverser $traverser, array $originStmts, array $originTokens, string $path, string $namespace, string $className): void;
+
+ abstract protected function handleCreate(Context $c, string $path, string $namespace, string $className): string;
+
+ private function initialAst(): void
+ {
+ $this->lexer = new Emulative([
+ 'usedAttributes' => [
+ 'comments',
+ 'startLine', 'endLine',
+ 'startTokenPos', 'endTokenPos',
+ ],
+ ]);
+ $this->astParser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7, $this->lexer);
+ $this->printer = new Standard();
+ }
+}
diff --git a/Processor/AbstractProcessor.php b/Processor/AbstractProcessor.php
new file mode 100644
index 0000000..1431010
--- /dev/null
+++ b/Processor/AbstractProcessor.php
@@ -0,0 +1,44 @@
+getClassName($c);
+ $namespace = $this->getNamespace($c);
+ $path = $this->getPath($namespace, $className);
+ return new GeneratorEntity($this->generator($c, $path, $namespace, $className));
+ }
+
+ abstract protected function generator(Context $c, string $path, string $namespace, string $className): string;
+
+ protected function getPath(string $namespace, string $className): string
+ {
+ return \Hyperf\Support\with(new Project())->path($namespace . '\\' . $className);
+ }
+
+ abstract protected function getNamespace(Context $c): string;
+
+ abstract protected function getClassName(Context $c): string;
+}
diff --git a/Processor/ControllerProcessor.php b/Processor/ControllerProcessor.php
new file mode 100644
index 0000000..d3f495f
--- /dev/null
+++ b/Processor/ControllerProcessor.php
@@ -0,0 +1,82 @@
+getConfig(), 'commands', []);
+ $stub = file_get_contents(__DIR__ . '/stubs/controller.stub');
+ $stub = str_replace('%namespace%', $namespace, $stub);
+ $stub = str_replace('%controllerName%', $className, $stub);
+ $stub = str_replace('%controllerMethods%', $this->handleMethods($c, $commands), $stub);
+ $stub = str_replace('%controllerExtends%', $this->handleExtends($c, $commands), $stub);
+ return str_replace('%use%', $this->handleUse($c, $commands), $stub);
+ }
+
+ protected function handleExtends(Context $c, array $commands): string
+ {
+ if (Arr::exists($commands, 'controller.extend')) {
+ return Arr::get($commands, 'controller.extend');
+ }
+
+ return AbstractController::class;
+ }
+
+ protected function handleMethods(Context $c, array $commands): string
+ {
+ $content = '';
+ $methods = Arr::get($commands, 'controller.methods', [
+ '__construct', 'list', 'create', 'save', 'delete',
+ ]);
+ foreach ($methods as $method) {
+ $content .= file_get_contents(__DIR__ . '/stubs/controller/' . $method . '.stub') . \PHP_EOL;
+ }
+
+ return $content;
+ }
+
+ protected function handleUse(Context $c, array $command): string
+ {
+ $use = '';
+ foreach (Arr::get($command, 'controller.use', []) as $item) {
+ $use .= 'use ' . $item . ';' . \PHP_EOL;
+ }
+ return $use;
+ }
+
+ protected function getNamespace(Context $c): string
+ {
+ if (Arr::has($c->getConfig(), 'controller.namespace')) {
+ return (string) Arr::get($c->getConfig(), 'controller.namespace');
+ }
+ return 'App\Controller';
+ }
+
+ protected function getClassName(Context $c): string
+ {
+ if (Arr::has($c->getConfig(), 'controller.name')) {
+ return Str::ucfirst((string) Arr::get($c->getConfig(), 'controller.name'));
+ }
+ return Str::ucfirst($c->getTable()->getTableName());
+ }
+}
diff --git a/Processor/ProcessorInterface.php b/Processor/ProcessorInterface.php
new file mode 100644
index 0000000..2a393f6
--- /dev/null
+++ b/Processor/ProcessorInterface.php
@@ -0,0 +1,21 @@
+