- New code generation made for CLI
This commit is contained in:
parent
ae212a4377
commit
c3e3d6a73a
@ -2,7 +2,7 @@
|
||||
|
||||
use Ulmus\ConnectionAdapter;
|
||||
|
||||
putenv('LEAN_API_PROJECT_PATH=' . $path = dirname(__DIR__, 2));
|
||||
define('LEAN_API_PROJECT_PATH', $path = dirname(__DIR__, 2));
|
||||
|
||||
return [
|
||||
'lean.api' => [
|
||||
@ -24,6 +24,10 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
'cli' => [
|
||||
'Lean\\Api\\Cli' => implode(DIRECTORY_SEPARATOR, [ $path, "src", "Cli", "" ]),
|
||||
],
|
||||
|
||||
'ulmus' => [
|
||||
'entities' => [ 'Lean\\Api\\Entity' => implode(DIRECTORY_SEPARATOR, [ $path, 'src', 'Entity', '' ]) ],
|
||||
'adapters' => [
|
||||
|
||||
63
skeleton/EntityGenerate/Api.php
Normal file
63
skeleton/EntityGenerate/Api.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%API_NS%;
|
||||
|
||||
use Notes\Attribute\Ignore;
|
||||
use Notes\Route\Attribute\Method\Route;
|
||||
use Psr\Http\Message\{ ServerRequestInterface, ResponseInterface };
|
||||
|
||||
use %NAMESPACE%\{Lib, %USE_ENTITY_NS%, %USE_FORM_NS%, };
|
||||
use function %NAMESPACE%\View\{_, lang, url, route, form};
|
||||
|
||||
#[\Notes\Route\Attribute\Object\Route(base:"%API_ROUTE_BASE%/%CLASSNAME_LC%")]
|
||||
class %CLASSNAME% {
|
||||
use Lib\ApiTrait;
|
||||
|
||||
#[Route(route: "/documentation", name: "api.%CLASSNAME_LC%:docs", method: "GET")]
|
||||
public function index(ServerRequestInterface $request, array $attributes): ResponseInterface
|
||||
{
|
||||
return $this->renderMarkdown(getenv("PROJECT_PATH") . "/meta/docs/%CLASSNAME_LC%.md", [ %ENTITY_NS%\%CLASSNAME%::class, ], [ %FORM_NS%\%SAVE_FORM_CONTEXT_CLASSNAME%::class, %FORM_NS%\%DELETE_FORM_CONTEXT_CLASSNAME%::class ]);
|
||||
}
|
||||
|
||||
#[Route("/", name: "api.%CLASSNAME_LC%:list", method: "GET")]
|
||||
public function list(ServerRequestInterface $request, array $attributes) : ResponseInterface
|
||||
{
|
||||
$request = $this->searchEntitiesFromRequest($request, %ENTITY_NS%\%CLASSNAME%::class);
|
||||
$result = $request->getAttribute("lean.searchRequest")[%ENTITY_NS%\%CLASSNAME%::class];
|
||||
|
||||
return $this->outputSearchResult($result);
|
||||
}
|
||||
|
||||
#[Route("/", name: "api.%CLASSNAME_LC%:add", method: "POST")]
|
||||
public function add(ServerRequestInterface $request, array $attributes) : ResponseInterface
|
||||
{
|
||||
$entity = new %ENTITY_NS%\%CLASSNAME%();
|
||||
|
||||
form($this->formFactory->%SAVE_FORM_CLASSNAME_LC%($entity), $this->formFactory->%SAVE_FORM_CONTEXT_CLASSNAME_LC%($request));
|
||||
|
||||
return $this->output($entity, (int) $entity->isLoaded());
|
||||
}
|
||||
|
||||
#[Route("/{id:\d+}", name: "api.%CLASSNAME_LC%:single", method: "GET")]
|
||||
#[Route("/{id:\d+}", name: "api.%CLASSNAME_LC%:edit", method: "PATCH")]
|
||||
public function single(ServerRequestInterface $request, array $attributes) : ResponseInterface
|
||||
{
|
||||
$request = $this->searchEntityFromRequest($request, %ENTITY_NS%\%CLASSNAME%::class);
|
||||
$result = $request->getAttribute("lean.searchRequest")[%ENTITY_NS%\%CLASSNAME%::class];
|
||||
|
||||
form($this->formFactory->%SAVE_FORM_CLASSNAME_LC%($result->getResult()), $this->formFactory->%SAVE_FORM_CONTEXT_CLASSNAME_LC%($request));
|
||||
|
||||
return $this->outputSearchResult($result);
|
||||
}
|
||||
|
||||
#[Route("/{id:\d+}", name: "api.%CLASSNAME_LC%:delete", method: "DELETE")]
|
||||
public function delete(ServerRequestInterface $request, array $attributes) : ResponseInterface
|
||||
{
|
||||
$request = $this->searchEntityFromRequest($request, %ENTITY_NS%\%CLASSNAME%::class);
|
||||
$result = $request->getAttribute("lean.searchRequest")[%ENTITY_NS%\%CLASSNAME%::class];
|
||||
|
||||
form($this->formFactory->%DELETE_FORM_CLASSNAME_LC%($result->getResult()), $this->formFactory->%DELETE_FORM_CONTEXT_CLASSNAME_LC%($request));
|
||||
|
||||
return $this->outputSearchResult($result);
|
||||
}
|
||||
}
|
||||
66
skeleton/EntityGenerate/Controller.php
Normal file
66
skeleton/EntityGenerate/Controller.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%WEB_NS%;
|
||||
|
||||
use Notes\Breadcrumb\Attribute\Method\Breadcrumb;
|
||||
use Notes\Route\Attribute\Method\Route;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface,
|
||||
Psr\Http\Message\ResponseInterface;
|
||||
|
||||
use %NAMESPACE%\{Lib, %USE_ENTITY_NS%, %USE_FORM_NS%, };
|
||||
|
||||
use function %NAMESPACE%\View\{_, lang, url, route, form};
|
||||
|
||||
#[\Notes\Route\Attribute\Object\Route(base:"%WEB_ROUTE_BASE%/%CLASSNAME_LC%")]
|
||||
class %CLASSNAME% {
|
||||
use Lib\ControllerTrait;
|
||||
|
||||
#[Route("/", name: "%CLASSNAME_LC%:index")]
|
||||
##[Breadcrumb(parent: "", icon: "", lang: "app.lang.breadcrumb")]
|
||||
public function index(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||
{
|
||||
$search = %ENTITY_NS%\%CLASSNAME%::searchRequest()->fromRequest($request) ;
|
||||
$list = %ENTITY_NS%\%CLASSNAME%::repository()->filterServerRequest($search)->loadAll();
|
||||
|
||||
return $this->renderView('%CLASSNAME_LC%/index', get_defined_vars());
|
||||
}
|
||||
|
||||
#[Route("/create", name: "%CLASSNAME_LC%:create", method: ["GET", "POST"])]
|
||||
##[Breadcrumb(parent: "%CLASSNAME_LC%:index", icon: "", lang: "app.lang.breadcrumb")]
|
||||
public function create(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||
{
|
||||
$entity = new %ENTITY_NS%\%CLASSNAME%();
|
||||
|
||||
form($this->formFactory->%SAVE_FORM_CLASSNAME_LC%($entity), $this->pushContext($this->formFactory->%SAVE_FORM_CONTEXT_CLASSNAME_LC%($request, "%CLASSNAME_LC%.create")));
|
||||
|
||||
if ($entity->isLoaded()) {
|
||||
return $this->redirect(route("%CLASSNAME_LC%:edit", [ 'id' => $entity->id ]) );
|
||||
}
|
||||
|
||||
return $this->renderView('%CLASSNAME_LC%/create', get_defined_vars());
|
||||
}
|
||||
|
||||
#[Route("/{id:\d+}/edit", name: "%CLASSNAME_LC%:edit", method: ["GET", "POST"])]
|
||||
##[Breadcrumb(parent: "%CLASSNAME_LC%:index", icon: "", lang: "app.lang.breadcrumb")]
|
||||
public function edit(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||
{
|
||||
$search = %ENTITY_NS%\%CLASSNAME%::searchRequest()->fromRequest($request);
|
||||
$entity = %ENTITY_NS%\%CLASSNAME%::repository()->filterServerRequest($search)->loadOne();
|
||||
|
||||
form($this->formFactory->%SAVE_FORM_CLASSNAME_LC%($entity), $this->pushContext($this->formFactory->%SAVE_FORM_CONTEXT_CLASSNAME_LC%($request, "%CLASSNAME_LC%.edit")));
|
||||
|
||||
return $this->renderView('%CLASSNAME_LC%/edit', get_defined_vars());
|
||||
}
|
||||
|
||||
#[Route("/{id:\d+}/delete", name: "%CLASSNAME_LC%:delete", method: ["POST", "DELETE"])]
|
||||
public function delete(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||
{
|
||||
$search = %ENTITY_NS%\%CLASSNAME%::searchRequest()->fromRequest($request);
|
||||
$entity = %ENTITY_NS%\%CLASSNAME%::repository()->filterServerRequest($search)->loadOne();
|
||||
|
||||
form($this->formFactory->%DELETE_FORM_CLASSNAME_LC%($entity), $this->pushContext($this->formFactory->%DELETE_FORM_CONTEXT_CLASSNAME_LC%($request, "%CLASSNAME_LC%.delete")));
|
||||
|
||||
return $this->redirect(route("%CLASSNAME_LC%:index"));
|
||||
}
|
||||
}
|
||||
20
skeleton/EntityGenerate/DeleteForm.php
Normal file
20
skeleton/EntityGenerate/DeleteForm.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%FORM_NS%;
|
||||
|
||||
use Picea\Ui\Method\{ FormContextInterface };
|
||||
use Lean\Api\Factory\MessageFactoryInterface;
|
||||
use Lean\LanguageHandler;
|
||||
|
||||
use %NAMESPACE%\{%USE_ENTITY_NS%, };
|
||||
|
||||
class %DELETE_FORM_CLASSNAME% extends \Lean\Api\Form\Delete
|
||||
{
|
||||
protected string $contextClass = %DELETE_FORM_CONTEXT_CLASSNAME%::class;
|
||||
|
||||
public function __construct(
|
||||
protected LanguageHandler $languageHandler,
|
||||
protected MessageFactoryInterface $message,
|
||||
protected %ENTITY_NS%\%CLASSNAME% $entity,
|
||||
) {}
|
||||
}
|
||||
22
skeleton/EntityGenerate/DeleteFormContext.php
Normal file
22
skeleton/EntityGenerate/DeleteFormContext.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%FORM_NS%;
|
||||
|
||||
use Lean\Api\Attribute\ContextField;
|
||||
use %NAMESPACE%\{ %USE_ENTITY_NS% };
|
||||
|
||||
#[ContextField]
|
||||
class %DELETE_FORM_CONTEXT_CLASSNAME% extends \Lean\Api\Lib\FormContext
|
||||
{
|
||||
# #[ContextField]
|
||||
# public string $name;
|
||||
|
||||
public function valid(? %ENTITY_NS%\%CLASSNAME% $entity = null) : bool
|
||||
{
|
||||
if ( ! $this->getEntity()->isLoaded() ) {
|
||||
$this->pushErrorMessage('lean.api.form.delete.error.entity');
|
||||
}
|
||||
|
||||
return parent::valid();
|
||||
}
|
||||
}
|
||||
43
skeleton/EntityGenerate/Entity.php
Normal file
43
skeleton/EntityGenerate/Entity.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%ENTITY_NS%;
|
||||
|
||||
use Ulmus\{
|
||||
Attribute\IndexTypeEnum,
|
||||
Attribute\Obj\Table,
|
||||
Attribute\Property\Field,
|
||||
Attribute\Property\Index,
|
||||
Attribute\Property\OrderBy,
|
||||
Attribute\Property\Relation,
|
||||
Attribute\Property\Virtual,
|
||||
Entity\EntityInterface,
|
||||
EntityCollection,
|
||||
Entity\Field\Datetime,
|
||||
Repository,
|
||||
SearchRequest,
|
||||
};
|
||||
|
||||
use Ulmus\SearchRequest\Attribute\SearchWhere;
|
||||
use Notes\Attribute\Ignore;
|
||||
|
||||
use %NAMESPACE%\Lib;
|
||||
|
||||
#[Table(name: "%CLASSNAME_LC%")]
|
||||
class %CLASSNAME% implements \JsonSerializable, EntityInterface
|
||||
{
|
||||
use Lib\EntityTrait;
|
||||
|
||||
#[Field\Id]
|
||||
public int $id;
|
||||
|
||||
#[Ignore]
|
||||
public static function searchRequest(...$arguments) : SearchRequest\SearchRequestInterface
|
||||
{
|
||||
return new #[SearchRequest\Attribute\SearchRequestParameter(%CLASSNAME%::class)] class(... $arguments) extends SearchRequest\SearchRequest {
|
||||
|
||||
#[SearchWhere(parameter: [ '%CLASSNAME_LC%_id', 'id' ], source: SearchRequest\Attribute\PropertyValueSource::RequestAttribute)]
|
||||
public int $id;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
20
skeleton/EntityGenerate/FactoryAppend.php
Normal file
20
skeleton/EntityGenerate/FactoryAppend.php
Normal file
@ -0,0 +1,20 @@
|
||||
public function %SAVE_FORM_CLASSNAME_LC%(EntityInterface|%ENTITY_NS%\%CLASSNAME% $entity): FormInterface
|
||||
{
|
||||
return new %FORM_NS%\%SAVE_FORM_CLASSNAME%($this->languageHandler, $this->message, $entity);
|
||||
}
|
||||
|
||||
public function %SAVE_FORM_CONTEXT_CLASSNAME_LC%(ServerRequestInterface $request, ? string $formName = ''): FormContextInterface
|
||||
{
|
||||
return new %FORM_NS%\%SAVE_FORM_CONTEXT_CLASSNAME%($this->languageHandler, $this->message, $request, $formName);
|
||||
}
|
||||
|
||||
public function %DELETE_FORM_CLASSNAME_LC%(EntityInterface|%ENTITY_NS%\%CLASSNAME% $entity): FormInterface
|
||||
{
|
||||
return new %FORM_NS%\%DELETE_FORM_CLASSNAME%($this->languageHandler, $this->message, $entity);
|
||||
}
|
||||
|
||||
public function %DELETE_FORM_CONTEXT_CLASSNAME_LC%(ServerRequestInterface $request, ? string $formName = ''): FormContextInterface
|
||||
{
|
||||
return new %FORM_NS%\%DELETE_FORM_CONTEXT_CLASSNAME%($this->languageHandler, $this->message, $request, $formName);
|
||||
}
|
||||
}
|
||||
5
skeleton/EntityGenerate/FactoryInterfaceAppend.php
Normal file
5
skeleton/EntityGenerate/FactoryInterfaceAppend.php
Normal file
@ -0,0 +1,5 @@
|
||||
public function %SAVE_FORM_CLASSNAME_LC%(EntityInterface|%ENTITY_NS%\%CLASSNAME% $entity): FormInterface;
|
||||
public function %SAVE_FORM_CONTEXT_CLASSNAME_LC%(ServerRequestInterface $request, ? string $formName = ''): FormContextInterface;
|
||||
public function %DELETE_FORM_CLASSNAME_LC%(EntityInterface|%ENTITY_NS%\%CLASSNAME% $entity): FormInterface;
|
||||
public function %DELETE_FORM_CONTEXT_CLASSNAME_LC%(ServerRequestInterface $request, ? string $formName = ''): FormContextInterface;
|
||||
}
|
||||
32
skeleton/EntityGenerate/FactoryTrait.php
Normal file
32
skeleton/EntityGenerate/FactoryTrait.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%FACTORY_TRAIT_NS%;
|
||||
|
||||
use %NAMESPACE%\{ %USE_ENTITY_NS%, %USE_FORM_NS%, };
|
||||
use Picea\Ui\Method\FormContextInterface;
|
||||
use Picea\Ui\Method\FormInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Ulmus\Entity\EntityInterface;
|
||||
|
||||
trait %CLASSNAME%Trait
|
||||
{
|
||||
public function %SAVE_FORM_CLASSNAME_LC%(EntityInterface|%ENTITY_NS%\%CLASSNAME% $entity): FormInterface
|
||||
{
|
||||
return new %FORM_NS%\%SAVE_FORM_CLASSNAME%($this->languageHandler, $this->messageFactory, $entity);
|
||||
}
|
||||
|
||||
public function %SAVE_FORM_CONTEXT_CLASSNAME_LC%(ServerRequestInterface $request, ? string $formName = ''): FormContextInterface
|
||||
{
|
||||
return new %FORM_NS%\%SAVE_FORM_CONTEXT_CLASSNAME%($this->languageHandler, $this->messageFactory, $request, $formName);
|
||||
}
|
||||
|
||||
public function %DELETE_FORM_CLASSNAME_LC%(EntityInterface|%ENTITY_NS%\%CLASSNAME% $entity): FormInterface
|
||||
{
|
||||
return new %FORM_NS%\%DELETE_FORM_CLASSNAME%($this->languageHandler, $this->messageFactory, $entity);
|
||||
}
|
||||
|
||||
public function %DELETE_FORM_CONTEXT_CLASSNAME_LC%(ServerRequestInterface $request, ? string $formName = ''): FormContextInterface
|
||||
{
|
||||
return new %FORM_NS%\%DELETE_FORM_CONTEXT_CLASSNAME%($this->languageHandler, $this->messageFactory, $request, $formName);
|
||||
}
|
||||
}
|
||||
20
skeleton/EntityGenerate/SaveForm.php
Normal file
20
skeleton/EntityGenerate/SaveForm.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%FORM_NS%;
|
||||
|
||||
use Picea\Ui\Method\{ FormContextInterface };
|
||||
use Lean\Api\Factory\MessageFactoryInterface;
|
||||
use Lean\LanguageHandler;
|
||||
|
||||
use %NAMESPACE%\{%USE_ENTITY_NS%, };
|
||||
|
||||
class %SAVE_FORM_CLASSNAME% extends \Lean\Api\Form\Save
|
||||
{
|
||||
protected string $contextClass = %SAVE_FORM_CONTEXT_CLASSNAME%::class;
|
||||
|
||||
public function __construct(
|
||||
protected LanguageHandler $languageHandler,
|
||||
protected MessageFactoryInterface $message,
|
||||
protected %ENTITY_NS%\%CLASSNAME% $entity,
|
||||
) {}
|
||||
}
|
||||
18
skeleton/EntityGenerate/SaveFormContext.php
Normal file
18
skeleton/EntityGenerate/SaveFormContext.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace %NAMESPACE%\%FORM_NS%;
|
||||
|
||||
use Lean\Api\Attribute\ContextField;
|
||||
use %NAMESPACE%\{ %USE_ENTITY_NS% };
|
||||
|
||||
#[ContextField]
|
||||
class %SAVE_FORM_CONTEXT_CLASSNAME% extends \Lean\Api\Lib\FormContext
|
||||
{
|
||||
# #[ContextField]
|
||||
# public string $name;
|
||||
|
||||
public function valid(? %ENTITY_NS%\%CLASSNAME% $entity = null) : bool
|
||||
{
|
||||
return parent::valid();
|
||||
}
|
||||
}
|
||||
21
skeleton/EntityGenerate/api-docs.md
Normal file
21
skeleton/EntityGenerate/api-docs.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Title
|
||||
|
||||
## API 1.0
|
||||
|
||||
[APP](../) / %CLASSNAME%
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### Routes
|
||||
|
||||
{route:descriptor}
|
||||
|
||||
{request:debugger}
|
||||
|
||||
### Forms
|
||||
|
||||
{form:descriptor}
|
||||
|
||||
### Entities
|
||||
|
||||
{entity:descriptor}
|
||||
599
src/Action/Console/EntityGenerate.php
Normal file
599
src/Action/Console/EntityGenerate.php
Normal file
@ -0,0 +1,599 @@
|
||||
<?php
|
||||
|
||||
namespace Lean\Api\Action\Console;
|
||||
|
||||
use Lean\Application;
|
||||
use Lean\Composer;
|
||||
use Mcnd\CLI\Terminal;
|
||||
|
||||
class EntityGenerate
|
||||
{
|
||||
# public string $applicationPath;
|
||||
public string $namespace;
|
||||
public string $entityNamespace;
|
||||
public string $formNamespace;
|
||||
public string $saveForm;
|
||||
public string $saveContext;
|
||||
public string $deleteForm;
|
||||
public string $deleteContext;
|
||||
public string $apiNamespace;
|
||||
public string $apiBase;
|
||||
public string $webNamespace;
|
||||
public string $webBase;
|
||||
public string $factoryAction;
|
||||
public string $factoryNamespace;
|
||||
public string $factoryTraitNamespace;
|
||||
public string $factoryFile;
|
||||
public string $factoryInterfaceFile;
|
||||
public bool $includeDocs = false;
|
||||
|
||||
public readonly string $compiledEntity;
|
||||
public readonly string $compiledSaveForm;
|
||||
public readonly string $compiledSaveFormContext;
|
||||
public readonly string $compiledDeleteForm;
|
||||
public readonly string $compiledDeleteFormContext;
|
||||
public readonly string $compiledFactory;
|
||||
public readonly string $compiledFactoryTrait;
|
||||
public readonly string $compiledFactoryInterface;
|
||||
public readonly string $compiledApi;
|
||||
public readonly string $compiledWeb;
|
||||
public readonly string $compiledDocs;
|
||||
|
||||
public function __construct(
|
||||
public Application $application,
|
||||
public string $name,
|
||||
public bool $overwrite,
|
||||
public bool $default,
|
||||
) {}
|
||||
|
||||
public function writeToDisc() : void
|
||||
{
|
||||
$entityPath = $this->pathFromNamespace($this->entityNamespace, $this->application->entities);
|
||||
|
||||
if (empty($entityPath)) {
|
||||
throw new \InvalidArgumentException("Could not find entities path from given namespaces.");
|
||||
}
|
||||
|
||||
if (isset($this->webNamespace)) {
|
||||
$webPath = $this->pathFromNamespace($this->webNamespace, $this->application->routes);
|
||||
|
||||
if (empty($webPath)) {
|
||||
throw new \InvalidArgumentException("Could not find web path routes from given namespaces.");
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->apiNamespace)) {
|
||||
$apiPath = $this->pathFromNamespace($this->apiNamespace, $this->application->routes);
|
||||
|
||||
if (empty($apiPath)) {
|
||||
throw new \InvalidArgumentException("Could not find web path routes from given namespaces.");
|
||||
}
|
||||
|
||||
if ($this->includeDocs) {
|
||||
$docPath = implode(DIRECTORY_SEPARATOR, [ getenv('META_PATH'), "docs" ]);
|
||||
$docPath = $this->readline(sprintf("Path of API's documentation output (default: %s) : ", $docPath), $docPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->formNamespace)) {
|
||||
$formPath = implode(DIRECTORY_SEPARATOR, [ $this->pathFromPSR($this->formNamespace), $this->formNamespace ]);
|
||||
$formPath = $this->readline(sprintf("Path of Forms (default: %s) : ", $formPath), $formPath);
|
||||
}
|
||||
|
||||
if (isset($this->factoryNamespace)) {
|
||||
$factoryPath = implode(DIRECTORY_SEPARATOR, [ $this->pathFromPSR($this->factoryNamespace), $this->factoryNamespace ]);
|
||||
$factoryPath = $this->readline(sprintf("Path of Factory (default: %s) : ", $factoryPath), $factoryPath);
|
||||
}
|
||||
|
||||
if ( Terminal::proposeListChoice("Input completed, write to files ?", [ true => 'Yes', false => 'No', ]) ) {
|
||||
$this->writeToFile($entityPath, $this->name, $this->compiledEntity, );
|
||||
|
||||
if (isset($webPath)) {
|
||||
$this->writeToFile($webPath, $this->name, $this->compiledWeb, );
|
||||
}
|
||||
|
||||
if (isset($apiPath)) {
|
||||
$this->writeToFile($apiPath, $this->name, $this->compiledApi, );
|
||||
|
||||
if ($this->includeDocs) {
|
||||
$this->writeToFile($docPath , strtolower($this->name), $this->compiledDocs, ".md");
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($formPath)) {
|
||||
if ($this->saveForm) {
|
||||
$this->writeToFile($formPath, $this->saveForm, $this->compiledSaveForm,);
|
||||
$this->writeToFile($formPath, $this->saveContext, $this->compiledSaveFormContext,);
|
||||
}
|
||||
|
||||
if ($this->deleteForm) {
|
||||
$this->writeToFile($formPath, $this->deleteForm, $this->compiledDeleteForm,);
|
||||
$this->writeToFile($formPath, $this->deleteContext, $this->compiledDeleteFormContext,);
|
||||
}
|
||||
|
||||
if (isset($this->factoryNamespace)) {
|
||||
if (isset($this->factoryTraitNamespace)) {
|
||||
$traitName = $this->name . "Trait";
|
||||
|
||||
$this->writeToFile(implode(DIRECTORY_SEPARATOR, [$factoryPath, "Factories"]), $traitName, $this->compiledFactoryTrait,);
|
||||
$this->appendToFile($factoryPath, $this->factoryFile, "\tuse Factories\\$traitName;\n}", "");
|
||||
}
|
||||
else {
|
||||
$this->appendToFile($factoryPath, $this->factoryFile, $this->compiledFactory, "");
|
||||
}
|
||||
|
||||
$this->appendToFile($factoryPath, $this->factoryInterfaceFile, $this->compiledFactoryInterface, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function appendToFile(string $path, string $filename, string $content, string $extension = ".php"): void
|
||||
{
|
||||
$fullpath = implode(DIRECTORY_SEPARATOR, [ rtrim($path, DIRECTORY_SEPARATOR), $filename . "$extension" ]);
|
||||
|
||||
$existingFileContent = file_get_contents($fullpath);
|
||||
|
||||
$this->writeToFile($path, $filename, rtrim($existingFileContent, '} ') . $content, $extension);
|
||||
}
|
||||
|
||||
protected function writeToFile(string $path, string $filename, string $content, string $extension = ".php"): void
|
||||
{
|
||||
$fullpath = implode(DIRECTORY_SEPARATOR, [ rtrim($path, DIRECTORY_SEPARATOR), $filename . "$extension" ]);
|
||||
|
||||
if (file_exists($fullpath)) {
|
||||
if ((! $this->overwrite) && Terminal::proposeListChoice(sprintf("Trying to write over an existing file '%s',\nOverwrite file ?", $fullpath), [ false => 'Yes', true => 'No', ])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
elseif (! file_exists(dirname($fullpath))) {
|
||||
mkdir(dirname($fullpath), 0755, true);
|
||||
}
|
||||
|
||||
file_put_contents($fullpath, $content, \LOCK_EX);
|
||||
|
||||
Terminal::sprintfline("File successfully written '%s'", $fullpath);
|
||||
}
|
||||
|
||||
protected function pathFromNamespace(string $namespace, array $source) : false|string
|
||||
{
|
||||
$split = explode('\\', $namespace);
|
||||
|
||||
while($split) {
|
||||
$ns = $this->namespace . "\\" . implode('\\', $split);
|
||||
|
||||
if ( isset($source[$ns]) ) {
|
||||
return rtrim($source[$ns], DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
array_pop($split);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function pathFromPSR(string $namespace) : false|string
|
||||
{
|
||||
$source = $this->readComposerPsr4();
|
||||
$split = explode('\\', $namespace);
|
||||
|
||||
while($split) {
|
||||
$ns = $this->namespace . "\\" . implode('\\', $split);
|
||||
|
||||
if (! str_ends_with($ns, '\\')) {
|
||||
$ns .= "\\";
|
||||
}
|
||||
|
||||
if ( isset($source[$ns]) ) {
|
||||
return $source[$ns][0];
|
||||
}
|
||||
|
||||
array_pop($split);
|
||||
}
|
||||
|
||||
return $source[$this->namespace . "\\"][0] ?? false;
|
||||
}
|
||||
|
||||
public function outputResults() : void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function readline(? string $prompt, mixed $default = null): string|false
|
||||
{
|
||||
$result = Terminal::readline($prompt);
|
||||
|
||||
if ($this->default && $default !== null) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $result ?: $default;
|
||||
}
|
||||
|
||||
public function readNamespace() : void
|
||||
{
|
||||
$namespace = $this->readComposerNamespace();
|
||||
$this->namespace = $this->readline(sprintf('Namespace (default: %s) : ', $namespace), $namespace);
|
||||
}
|
||||
|
||||
public function readApi() : void
|
||||
{
|
||||
$this->apiNamespace = $this->readline('API namespace (default: Api\\) : ', 'Api');
|
||||
$this->apiBase = $this->readline('API URL base (default: /api) : ', '/api');
|
||||
}
|
||||
|
||||
public function readWeb() : void
|
||||
{
|
||||
$this->webNamespace = $this->readline('Controller namespace (default: Controller\\) : ', 'Controller');
|
||||
$this->webBase = $this->readline('Controller URL base (default: /) : ', "");
|
||||
}
|
||||
|
||||
public function readEntity() : void
|
||||
{
|
||||
$this->entityNamespace = $this->readline('Entity namespace (default: Entity\\) : ', 'Entity');
|
||||
}
|
||||
|
||||
public function readFactory() : void
|
||||
{
|
||||
$this->factoryNamespace ??= $this->readline('Factory namespace (default: Factory\\) : ', 'Factory');
|
||||
$this->factoryFile = $this->readline('Form factory interface file (default: FormFactory.php) : ', 'FormFactory.php');
|
||||
$this->factoryInterfaceFile = $this->readline('Form factory interface file (default: FormFactoryInterface.php) : ', 'FormFactoryInterface.php');
|
||||
|
||||
$this->factoryAction = Terminal::proposeListChoice("Use new trait or append to file ?", [ 'trait' => 'Use trait', 'append' => 'Append to file', ]);
|
||||
|
||||
if ($this->factoryAction === 'trait') {
|
||||
$this->factoryTraitNamespace = implode('\\', [ $this->factoryNamespace, 'Factories' ]);
|
||||
$this->factoryTraitNamespace = $this->readline(sprintf("Factory trait namespace (default: %s) : ", $this->factoryTraitNamespace), $this->factoryTraitNamespace);
|
||||
}
|
||||
}
|
||||
|
||||
public function readSaveForm() : void
|
||||
{
|
||||
$this->formNamespace ??= $this->readline('Form namespace (default: Form\\) : ', 'Form');
|
||||
|
||||
$this->saveForm = ucfirst($this->name) . "Save";
|
||||
$this->saveForm = $this->readline(sprintf('Form "create/update" name (default: %s) : ', $this->saveForm), $this->saveForm);
|
||||
|
||||
$this->saveContext = $this->saveForm . "Context";
|
||||
$this->saveContext = $this->readline(sprintf('Context "create/update" (default: %s) : ', $this->saveContext), $this->saveContext);
|
||||
}
|
||||
|
||||
public function readDeleteForm() : void
|
||||
{
|
||||
$this->formNamespace ??= $this->readline('Form namespace (default: Form\\) : ') ?: 'Form';
|
||||
|
||||
$this->deleteForm = ucfirst($this->name) . "Delete";
|
||||
$this->deleteForm = $this->readline(sprintf('Form "delete" name (default: %s) : ', $this->deleteForm), $this->deleteForm);
|
||||
|
||||
$this->deleteContext = $this->deleteForm . "Context";
|
||||
$this->deleteContext = $this->readline(sprintf('Context "delete" (default: %s) : ', $this->deleteContext), $this->deleteContext);
|
||||
}
|
||||
|
||||
/*public function readApplicationPath(string $default) : void
|
||||
{
|
||||
$this->applicationPath = $this->readline(sprintf('Application path base (default: %s) : ', $default)) ?: $default;
|
||||
}*/
|
||||
|
||||
public function generate() : void
|
||||
{
|
||||
$this->namespace = trim($this->namespace, '\\');
|
||||
$this->formNamespace = trim($this->formNamespace, '\\');
|
||||
$this->entityNamespace = trim($this->entityNamespace, '\\');
|
||||
|
||||
$this->compiledEntity = $this->defineEntityBoilerplate();
|
||||
|
||||
if (isset($this->saveForm)) {
|
||||
$this->compiledSaveForm = $this->defineSaveFormBoilerplate();
|
||||
$this->compiledSaveFormContext = $this->defineSaveFormContextBoilerplate();
|
||||
}
|
||||
|
||||
if (isset($this->deleteForm)) {
|
||||
$this->compiledDeleteForm = $this->defineDeleteFormBoilerplate();
|
||||
$this->compiledDeleteFormContext = $this->defineDeleteFormContextBoilerplate();
|
||||
}
|
||||
|
||||
if (isset($this->apiNamespace)) {
|
||||
$this->compiledApi = $this->defineApiBoilerplate();
|
||||
|
||||
if ($this->includeDocs) {
|
||||
$this->compiledDocs = $this->defineDocsBoilerplate();
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->webNamespace)) {
|
||||
$this->compiledWeb = $this->defineWebBoilerplate();
|
||||
}
|
||||
|
||||
if (isset($this->factoryNamespace)) {
|
||||
if (isset($this->factoryTraitNamespace)) {
|
||||
$this->compiledFactoryTrait = $this->defineFactoryTraitBoilerplate();
|
||||
}
|
||||
else {
|
||||
$this->compiledFactory = $this->defineFactoryBoilerplate();
|
||||
}
|
||||
|
||||
$this->compiledFactoryInterface = $this->defineFactoryInterfaceBoilerplate();
|
||||
}
|
||||
}
|
||||
|
||||
protected function defineEntityBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('Entity'));
|
||||
}
|
||||
|
||||
protected function defineSaveFormBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('SaveForm'));
|
||||
}
|
||||
|
||||
protected function defineSaveFormContextBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('SaveFormContext'));
|
||||
}
|
||||
|
||||
protected function defineDeleteFormBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('DeleteForm'));
|
||||
}
|
||||
|
||||
protected function defineDeleteFormContextBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('DeleteFormContext'));
|
||||
}
|
||||
|
||||
protected function defineFactoryInterfaceBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('FactoryInterfaceAppend'));
|
||||
}
|
||||
|
||||
protected function defineFactoryTraitBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('FactoryTrait'));
|
||||
}
|
||||
|
||||
protected function defineFactoryBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('FactoryAppend'));
|
||||
}
|
||||
|
||||
protected function defineApiBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('Api'));
|
||||
}
|
||||
|
||||
protected function defineDocsBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('api-docs', '.md'));
|
||||
}
|
||||
|
||||
protected function defineWebBoilerplate() : string
|
||||
{
|
||||
return $this->replaceBoilerplateCode($this->getBoilerplateFile('Controller'));
|
||||
}
|
||||
|
||||
protected function getBoilerplateFile(string $fileName, string $extension = ".php") : string
|
||||
{
|
||||
$path = implode(DIRECTORY_SEPARATOR, [ LEAN_API_PROJECT_PATH , 'skeleton', 'EntityGenerate', "{$fileName}{$extension}" ]);
|
||||
$bp = file_get_contents($path);
|
||||
|
||||
if (! $bp ) {
|
||||
throw new \InvalidArgumentException("Boilerplate file not found in path " . $path);
|
||||
}
|
||||
|
||||
return $bp;
|
||||
}
|
||||
|
||||
protected function getEntityBoilerplate() : string
|
||||
{
|
||||
$path = implode(DIRECTORY_SEPARATOR, [ LEAN_API_PROJECT_PATH , 'skeleton', 'EntityGenerate', 'Entity.php' ]);
|
||||
$bp = file_get_contents($path);
|
||||
|
||||
if (! $bp ) {
|
||||
throw new \InvalidArgumentException("Entity boilerplate file not found in path " . $path);
|
||||
}
|
||||
|
||||
return $bp;
|
||||
}
|
||||
|
||||
protected function replaceBoilerplateCode(string $boilerplate) : string
|
||||
{
|
||||
# to be reworked with the |> operator in 8.5+
|
||||
$boilerplate = $this->replaceNamespace($boilerplate);
|
||||
$boilerplate = $this->replaceClassname($boilerplate);
|
||||
$boilerplate = $this->replaceEntityNamespace($boilerplate);
|
||||
$boilerplate = $this->replaceFormNamespace($boilerplate);
|
||||
$boilerplate = $this->replaceSaveFormClassname($boilerplate);
|
||||
$boilerplate = $this->replaceSaveFormContextClassname($boilerplate);
|
||||
$boilerplate = $this->replaceDeleteFormClassname($boilerplate);
|
||||
$boilerplate = $this->replaceDeleteFormContextClassname($boilerplate);
|
||||
$boilerplate = $this->replaceFactoryNamespace($boilerplate);
|
||||
$boilerplate = $this->replaceFactoryTraitNamespace($boilerplate);
|
||||
$boilerplate = $this->replaceApiNamespace($boilerplate);
|
||||
$boilerplate = $this->replaceApiBase($boilerplate);
|
||||
$boilerplate = $this->replaceWebNamespace($boilerplate);
|
||||
$boilerplate = $this->replaceWebBase($boilerplate);
|
||||
|
||||
return $boilerplate;
|
||||
}
|
||||
|
||||
protected function replaceNamespace(string $boilerplate) : string
|
||||
{
|
||||
return str_replace('%NAMESPACE%', $this->namespace, $boilerplate);
|
||||
}
|
||||
|
||||
protected function replaceEntityNamespace(string $boilerplate) : string
|
||||
{
|
||||
return match($this->entityNamespace ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%USE_ENTITY_NS%', '%ENTITY_NS%' ],
|
||||
[ strstr($this->entityNamespace, '\\', true) ?: $this->entityNamespace, $this->entityNamespace ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceSaveFormClassname(string $boilerplate) : string
|
||||
{
|
||||
return match($this->saveForm ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%SAVE_FORM_CLASSNAME%', '%SAVE_FORM_CLASSNAME_LC%' ],
|
||||
[ $this->saveForm, lcfirst($this->saveForm) ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceSaveFormContextClassname(string $boilerplate) : string
|
||||
{
|
||||
return match($this->saveContext ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%SAVE_FORM_CONTEXT_CLASSNAME%', '%SAVE_FORM_CONTEXT_CLASSNAME_LC%' ],
|
||||
[ $this->saveContext, lcfirst($this->saveContext) ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceDeleteFormClassname(string $boilerplate) : string
|
||||
{
|
||||
return match($this->deleteForm ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%DELETE_FORM_CLASSNAME%', '%DELETE_FORM_CLASSNAME_LC%' ],
|
||||
[ $this->deleteForm, lcfirst($this->deleteForm) ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceDeleteFormContextClassname(string $boilerplate) : string
|
||||
{
|
||||
return match($this->deleteContext ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%DELETE_FORM_CONTEXT_CLASSNAME%', '%DELETE_FORM_CONTEXT_CLASSNAME_LC%' ],
|
||||
[ $this->deleteContext, lcfirst($this->deleteContext) ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceFormNamespace(string $boilerplate) : string
|
||||
{
|
||||
return match($this->formNamespace ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%USE_FORM_NS%', '%FORM_NS%', ],
|
||||
[ strstr($this->formNamespace, '\\', true) ?: $this->formNamespace, $this->formNamespace ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceApiNamespace(string $boilerplate) : string
|
||||
{
|
||||
return match($this->apiNamespace ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%API_NS%', ],
|
||||
[ rtrim($this->apiNamespace, '\\') ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceApiBase(string $boilerplate) : string
|
||||
{
|
||||
return match($this->apiBase ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%API_ROUTE_BASE%', ],
|
||||
[ $this->apiBase ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceWebNamespace(string $boilerplate) : string
|
||||
{
|
||||
return match($this->webNamespace ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%WEB_NS%', ],
|
||||
[ rtrim($this->webNamespace, '\\') ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceWebBase(string $boilerplate) : string
|
||||
{
|
||||
return match($this->webBase ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%WEB_ROUTE_BASE%', ],
|
||||
[ $this->webBase ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceFactoryNamespace(string $boilerplate) : string
|
||||
{
|
||||
return match($this->factoryNamespace ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%FACTORY_NS%', ],
|
||||
[ rtrim($this->factoryNamespace, '\\') ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceFactoryTraitNamespace(string $boilerplate) : string
|
||||
{
|
||||
return match($this->factoryTraitNamespace ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%FACTORY_TRAIT_NS%', ],
|
||||
[ rtrim($this->factoryTraitNamespace, '\\') ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function replaceClassname(string $boilerplate) : string
|
||||
{
|
||||
return match($this->apiBase ?? false) {
|
||||
false => $boilerplate,
|
||||
default => str_replace(
|
||||
[ '%CLASSNAME_LC%', '%CLASSNAME%' ],
|
||||
[ strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $this->name)), $this->name ],
|
||||
$boilerplate
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
protected function readComposerNamespace() : ? string
|
||||
{
|
||||
if ( false !== $composerJson = Composer::readComposerJson() ) {
|
||||
if ($psr4 = $composerJson['autoload']['psr-4'] ?? false) {
|
||||
foreach ($psr4 as $ns => $directory) {
|
||||
if ($directory === 'src/') {
|
||||
return $ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function readComposerPsr4() : array
|
||||
{
|
||||
return include(implode(DIRECTORY_SEPARATOR, [ getenv('PROJECT_PATH'), 'vendor' , 'composer', 'autoload_psr4.php' ]));
|
||||
}
|
||||
}
|
||||
120
src/Cli/CodeGeneration.php
Normal file
120
src/Cli/CodeGeneration.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Lean\Api\Cli;
|
||||
|
||||
use DI\Attribute\Inject;
|
||||
use Lean\Lean;
|
||||
use Lean\Api\Action;
|
||||
use Mcnd\CLI\{Terminal, OptionValueTypeEnum, OptionStack};
|
||||
use Notes\CLI\Attribute\{Option, Command};
|
||||
use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
|
||||
|
||||
#[Command(description: PHP_EOL . <<<CLI
|
||||
#[color:gray, bg: black]╔═══════════════════════════════════════════════════════════════════╗[#]
|
||||
#[color:gray, bg: black]║ ║[#]
|
||||
#[color:gray, bg: black]║ ║[#]
|
||||
#[color:gray, bg: black]║ ║[#]
|
||||
#[color:gray, bg: black]║ ║[#]
|
||||
#[color:gray, bg: black]║ ░▒▓█▓▒░ ░▒▓████████▓▒░░▒▓██████▓▒░░▒▓███████▓▒░ ║[#]
|
||||
#[color:gray, bg: black]║ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ║[#]
|
||||
#[color:gray, bg: black]║ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ║[#]
|
||||
#[color:gray, bg: black]║ ░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░ ║[#]
|
||||
#[color:gray, bg: black]║ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ║[#]
|
||||
#[color:gray, bg: black]║ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ║[#]
|
||||
#[color:gray, bg: black]║ ░▒▓████████▓▒░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ║[#]
|
||||
#[color:gray, bg: black]║ ║[#]
|
||||
#[color:gray, bg: black]║ ║[#]
|
||||
#[color:gray, bg: black]║ A P I ║[#]
|
||||
#[color:gray, bg: black]║ ║[#]
|
||||
#[color:gray, bg: black]╚═══════════════════════════════════════════════════════════════════╝[#]
|
||||
|
||||
Try #[color:gray, bg: black]'lean api --help'[#] for more information.
|
||||
CLI
|
||||
, command: 'lean-api')]
|
||||
#[Option(switch: ['-h', '--help'], description: "Display help for the given command. When no command is given display help for the list command")]
|
||||
class CodeGeneration
|
||||
{
|
||||
use \Lean\ControllerTrait;
|
||||
|
||||
#[Inject]
|
||||
public Lean $lean;
|
||||
|
||||
#[Command(description: "Create an entity and it's related boilerplate", command: "entity:generate")]
|
||||
#[Option(switch: ['-p', '--application'], description: "Application to target", value: OptionValueTypeEnum::RequiredValue)]
|
||||
#[Option(switch: ['-n', '--name'], description: "Write generated content into project", value: OptionValueTypeEnum::RequiredValue)]
|
||||
#[Option(switch: ['-m', '--namespace'], description: "Which PSR-4 namespace should be used", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-f', '--form'], description: "Form and context name", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-s', '--saveForm'], description: "Include or not a save form", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-d', '--deleteForm'], description: "Include or not a delete form", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-a', '--api'], description: "Include or not an API controller", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-c', '--api-docs'], description: "Include or not an API documentation page", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-w', '--web'], description: "Include or not a web controller", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-f', '--factory'], description: "Factory file to add to", value: OptionValueTypeEnum::OptionalValue)]
|
||||
#[Option(switch: ['-w', '--write'], description: "Write generated content into project's folder path",)]
|
||||
#[Option(switch: ['-o', '--overwrite'], description: "Overwrite every files by default", value: OptionValueTypeEnum::NoValue)]
|
||||
#[Option(switch: ['-t', '--default-answers'], description: "Auto-accept every default answers", value: OptionValueTypeEnum::NoValue)]
|
||||
##[Option(switch: ['-p', '--path'], description: "Base project save path", value: OptionValueTypeEnum::OptionalValue)]
|
||||
public function generate(ServerRequestInterface $request, array $arguments, OptionStack $options, string $rest): ResponseInterface
|
||||
{
|
||||
$name = $options->get('name')->value() ?: readline('Entity name : ');
|
||||
|
||||
if ( empty($name)) {
|
||||
throw new \InvalidArgumentException("An entity name must be provided");
|
||||
}
|
||||
|
||||
$applicationList = array_reverse(array_map(fn($e) => $e->name, $this->lean->applications));
|
||||
$app = $options->get('application')->value() ?? Terminal::proposeListChoice("Select an application : ", $applicationList);
|
||||
|
||||
$entityGenerate = new Action\Console\EntityGenerate(
|
||||
application: $this->lean->getApplication($applicationList[$app]),
|
||||
name: $name,
|
||||
overwrite: $options->get('overwrite')->value() ?? false,
|
||||
default: $options->get('default-answers')->value() ?? false,
|
||||
);
|
||||
|
||||
if ("" === ( $entityGenerate->namespace = $options->get('namespace')->value() ?: "" )) {
|
||||
$entityGenerate->readNamespace();
|
||||
}
|
||||
|
||||
$entityGenerate->readEntity();
|
||||
|
||||
if ($options->get('saveForm')->value() ?? Terminal::proposeListChoice("Add a save form ?", [ true => 'Yes', false => 'No', ])) {
|
||||
$entityGenerate->readSaveForm();
|
||||
$hasFactory = true;
|
||||
}
|
||||
|
||||
if ($options->get('deleteForm')->value() ?? Terminal::proposeListChoice("Add a delete form ?", [ true => 'Yes', false => 'No', ])) {
|
||||
$entityGenerate->readDeleteForm();
|
||||
$hasFactory = true;
|
||||
}
|
||||
|
||||
if (isset($hasFactory) && (
|
||||
$options->get('factory')->value() ?? Terminal::proposeListChoice("Add to form factory ?", [ true => 'Yes', false => 'No', ]))
|
||||
) {
|
||||
$entityGenerate->readFactory();
|
||||
}
|
||||
|
||||
if ($options->get('web')->value() ?? Terminal::proposeListChoice("Add a Web controller ?", [ true => 'Yes', false => 'No', ])) {
|
||||
$entityGenerate->readWeb();
|
||||
}
|
||||
|
||||
if ($options->get('api')->value() ?? Terminal::proposeListChoice("Add an API controller ?", [ true => 'Yes', false => 'No', ])) {
|
||||
$entityGenerate->readApi();
|
||||
|
||||
if ($options->get('api-docs')->value() ?? Terminal::proposeListChoice("Provides documentation for this route ?", [ true => 'Yes', false => 'No', ])) {
|
||||
$entityGenerate->includeDocs = true;
|
||||
}
|
||||
}
|
||||
|
||||
$entityGenerate->generate();
|
||||
|
||||
if ($options->get('write')->value() ?? Terminal::proposeListChoice("Write to disc or output results only ?", [ true => 'Write to disc', false => 'Output results only', ])) {
|
||||
$entityGenerate->writeToDisc();
|
||||
}
|
||||
else {
|
||||
$entityGenerate->outputResults();
|
||||
}
|
||||
|
||||
return $this->renderCLI($request, "done");
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,6 @@ class Debug {
|
||||
#[Route("/", name: "lean.api:debug-doc", method: "GET", description: "Documentation section")]
|
||||
public function documentation(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||
{
|
||||
return $this->renderMarkdown(getenv("LEAN_API_PROJECT_PATH") . "/meta/docs/lean-api.md", [ Entity\Error::class, ], [ Form\Debug\ErrorContext::class ]);
|
||||
return $this->renderMarkdown(LEAN_API_PROJECT_PATH . "/meta/docs/lean-api.md", [ Entity\Error::class, ], [ Form\Debug\ErrorContext::class ]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ class Errors {
|
||||
#[Route("/documentation", name: "lean.api:errors-doc", method: "GET", description: "Documentation section")]
|
||||
public function documentation(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||
{
|
||||
return $this->renderMarkdown(getenv("LEAN_API_PROJECT_PATH") . "/meta/docs/debug/errors.md", [ Entity\Error::class, ], [ Form\Debug\ErrorContext::class ]);
|
||||
return $this->renderMarkdown(LEAN_API_PROJECT_PATH . "/meta/docs/debug/errors.md", [ Entity\Error::class, ], [ Form\Debug\ErrorContext::class ]);
|
||||
}
|
||||
|
||||
#[Route("/", name: "lean.api:errors-list", method: [ "GET" ], description: "List every errors received")]
|
||||
|
||||
@ -8,17 +8,6 @@ use Ulmus\Entity\EntityInterface;
|
||||
|
||||
abstract class Delete extends Form implements \Picea\Ui\Method\FormInterface {
|
||||
|
||||
public function validate(FormContextInterface $context) : bool
|
||||
{
|
||||
if ( ! $this->getEntity()->isLoaded() ) {
|
||||
$context->pushMessage($this->message::generateError(
|
||||
$this->lang('lean.api.form.delete.error.entity')
|
||||
));
|
||||
}
|
||||
|
||||
return $context->valid($this->getEntity()->isLoaded() ? $this->getEntity() : null);
|
||||
}
|
||||
|
||||
public function execute(FormContextInterface $context) : void
|
||||
{
|
||||
try {
|
||||
|
||||
@ -10,12 +10,19 @@ use Ulmus\EntityCollection;
|
||||
|
||||
abstract class Form
|
||||
{
|
||||
protected string $contextClass;
|
||||
|
||||
public function __construct(
|
||||
protected LanguageHandler $languageHandler,
|
||||
protected MessageFactoryInterface $message,
|
||||
# public EntityInterface $entity,
|
||||
) {}
|
||||
|
||||
public function validate(FormContextInterface $context) : bool
|
||||
{
|
||||
return $context->valid($this->getEntity()->isLoaded() ? $this->getEntity() : null);
|
||||
}
|
||||
|
||||
public function initialize(FormContextInterface $context) : void
|
||||
{
|
||||
if(isset($this->contextClass) && ! $context instanceof $this->contextClass ) {
|
||||
|
||||
@ -19,8 +19,6 @@ abstract class Save extends Form implements \Picea\Ui\Method\FormInterface {
|
||||
|
||||
protected array $reflectedProperties;
|
||||
|
||||
protected string $contextClass;
|
||||
|
||||
public function initialize(FormContextInterface $context) : void
|
||||
{
|
||||
if ( ! $this->getEntity()->isLoaded() ) {
|
||||
@ -74,7 +72,7 @@ abstract class Save extends Form implements \Picea\Ui\Method\FormInterface {
|
||||
$context->pushErrorMessage($ex->getMessage());
|
||||
}
|
||||
|
||||
return $saved;
|
||||
return $saved ?? false;
|
||||
}
|
||||
|
||||
protected function validateContextFields(FormContextInterface $context) : void
|
||||
|
||||
1
view/lean-api/entity-generate/create.phtml
Normal file
1
view/lean-api/entity-generate/create.phtml
Normal file
@ -0,0 +1 @@
|
||||
@todo!
|
||||
1
view/lean-api/entity-generate/edit.phtml
Normal file
1
view/lean-api/entity-generate/edit.phtml
Normal file
@ -0,0 +1 @@
|
||||
@todo!
|
||||
1
view/lean-api/entity-generate/index.phtml
Normal file
1
view/lean-api/entity-generate/index.phtml
Normal file
@ -0,0 +1 @@
|
||||
@todo!
|
||||
Loading…
x
Reference in New Issue
Block a user