From a8c514d084736ced2e6479ed74ea22210ec20eb3 Mon Sep 17 00:00:00 2001 From: Oscar Cabrera Date: Sun, 28 Jul 2024 11:32:10 -0600 Subject: [PATCH 1/2] refactoring with phpinsights --- ci-scripts/Analyzer/Analyzer.php | 191 +++++------------ ci-scripts/Analyzer/AnalyzerSettings.php | 135 ++++++++---- ci-scripts/Analyzer/ArgumentHandler.php | 45 ++++ ci-scripts/Analyzer/CommandBuilder.php | 48 +++++ ci-scripts/Analyzer/Constants/Color.php | 18 +- ci-scripts/Analyzer/Constants/Icon.php | 18 +- ci-scripts/Analyzer/FileHandler.php | 74 +++++++ ci-scripts/PhpMD/PhpMDAnalyzer.php | 28 +++ ci-scripts/PhpMD/run.php | 11 + ci-scripts/PhpStan/PhpStanAnalyzer.php | 28 +++ ci-scripts/PhpStan/phpstan.neon | 17 ++ ci-scripts/PhpStan/run.php | 11 + ci-scripts/Pint/PintAnalyzer.php | 17 +- ci-scripts/Pint/run.php | 7 +- ci-scripts/phpMD/PhpMDAnalyzer.php | 22 -- ci-scripts/phpMD/run.php | 13 -- ci-scripts/phpStan/PhpStanAnalyzer.php | 21 -- ci-scripts/phpStan/phpstan.neon | 10 - ci-scripts/phpStan/run.php | 13 -- composer.json | 10 +- config/binding-provider.php | 4 +- docs/binding-service-provider/introduction.md | 5 +- docs/repository-interfaces/ICreateModel.md | 2 - docs/repository-interfaces/IDeleteModel.md | 4 - docs/repository-interfaces/IEntityCount.md | 5 - docs/repository-interfaces/IEntitySearch.md | 5 - docs/repository-interfaces/IListModel.md | 4 - docs/repository-interfaces/IReadModel.md | 4 - docs/repository-interfaces/IUpdateModel.md | 4 - phpinsights.php | 38 ++++ src/BindingServiceProvider.php | 19 +- src/Classes/Options.php | 82 +++++--- src/Commands/Handlers.php | 74 +++++-- src/Contracts/Resources/ICreateModel.php | 7 +- src/Contracts/Resources/IDeleteModel.php | 9 +- src/Contracts/Resources/IEntityCount.php | 13 +- src/Contracts/Resources/IEntitySearch.php | 10 +- src/Contracts/Resources/IListModel.php | 9 +- src/Contracts/Resources/IReadModel.php | 9 +- .../Resources/IRepositoryResource.php | 2 + src/Contracts/Resources/IUpdateModel.php | 5 +- .../Command/CreateStructureException.php | 6 +- src/Exception/Command/StubException.php | 9 +- src/Exception/CustomException.php | 57 +++--- src/Handlers/BindingServices.php | 72 ++----- src/Handlers/MainCommand.php | 193 ++++++------------ src/Handlers/Makers/MakeController.php | 50 ++--- .../Makers/MakeInterfaceRepository.php | 56 ++--- src/Handlers/Makers/MakeInterfaceServices.php | 56 ++--- src/Handlers/Makers/MakeModel.php | 25 +-- src/Handlers/Makers/MakeRepository.php | 67 +++--- src/Handlers/Makers/MakeRequest.php | 50 ++--- src/Handlers/Makers/MakeService.php | 72 ++++--- src/Handlers/Makers/MakeStructure.php | 93 ++++----- src/RepositoryCommandServiceProvider.php | 15 +- src/Trait/ArrayHandlerBindingTrait.php | 118 +++++++++++ src/Trait/FailedValidationTrait.php | 17 +- src/Trait/OptionsTrait.php | 31 +++ src/Trait/PopulatesOptionsTrait.php | 92 +++++++++ stubs/Controller.stub | 18 -- stubs/InterfaceService.stub | 25 +-- stubs/Repository.stub | 25 +-- stubs/Service.stub | 40 ++-- 63 files changed, 1279 insertions(+), 959 deletions(-) create mode 100644 ci-scripts/Analyzer/ArgumentHandler.php create mode 100644 ci-scripts/Analyzer/CommandBuilder.php create mode 100644 ci-scripts/Analyzer/FileHandler.php create mode 100644 ci-scripts/PhpMD/PhpMDAnalyzer.php create mode 100644 ci-scripts/PhpMD/run.php create mode 100644 ci-scripts/PhpStan/PhpStanAnalyzer.php create mode 100644 ci-scripts/PhpStan/phpstan.neon create mode 100644 ci-scripts/PhpStan/run.php delete mode 100644 ci-scripts/phpMD/PhpMDAnalyzer.php delete mode 100644 ci-scripts/phpMD/run.php delete mode 100644 ci-scripts/phpStan/PhpStanAnalyzer.php delete mode 100644 ci-scripts/phpStan/phpstan.neon delete mode 100644 ci-scripts/phpStan/run.php create mode 100644 phpinsights.php create mode 100644 src/Trait/ArrayHandlerBindingTrait.php create mode 100644 src/Trait/OptionsTrait.php create mode 100644 src/Trait/PopulatesOptionsTrait.php diff --git a/ci-scripts/Analyzer/Analyzer.php b/ci-scripts/Analyzer/Analyzer.php index 7152562..5891cdf 100644 --- a/ci-scripts/Analyzer/Analyzer.php +++ b/ci-scripts/Analyzer/Analyzer.php @@ -1,14 +1,10 @@ color = new Color(); - $this->icon = new Icon(); - } - /** * Execute the analyzer * - * @return bool Returns an exit status code. 0 indicates success (OK), - * and any other number indicates an error. + * Returns an exit status code. 0 indicates success (OK), + * and any other number indicates an error. */ public function analyze(): bool { try { - $modifiedFiles = $this->getFiles(); - if (empty($modifiedFiles)) { - $this->echoColor( - 'No files modified to analyze', - $this->color::get('BLUE'), - $this->icon::get('NO_FILES') - ); - return true; - } - if (!$this->execute($modifiedFiles)) { - $this->echoColor( - "$this->tool analysis failed", - $this->color::get('RED'), - $this->icon::get('CRITICAL_ERROR') - ); - return false; - } - - $this->echoColor( - "$this->tool analysis succeeded", - $this->color::get('BLUE'), - $this->icon::get('SUCCESS') - ); - return true; - } catch (RuntimeException|Exception $e) { - $this->echoColor($e->getMessage(), $this->color::get('RED'), $this->icon::get('EXCEPTION')); + return $this->executeAnalysis(); + } catch (RuntimeException|Exception $exception) { + $this->reportExceptionThrown($exception); return false; } } /** - * Get files to analyze + * Execute the analysis and report the result. * - * @return string Returns a string representation of the files to analyze. * @throws Exception */ - private function getFiles(): string + protected function executeAnalysis(): bool { - $allFlag = in_array('--all', $this->args, true); - if ($allFlag) { - $this->echoColor('Executing analysis on .', $this->color::get('YELLOW'), $this->icon::get('STACK_TRACE')); - return '.'; + $files = $this->getFiles(); + if ($files === '') { + $this->reportNoFilesAnalyze(); + return true; + } + if (!$this->execute($files)) { + $this->reportAnalysisFailed(); + return false; } - $dir = $this->getDirFlag(); - return $dir ?? $this->getDiffBranch(); + $this->reportAnalysisSucceeded(); + return true; } /** - * Get the directory flag value from the command line arguments + * Get files to analyze + * + * Returns a string representation of the files to analyze. * - * @return string|null Returns the directory flag value if found, null otherwise + * @throws Exception */ - private function getDirFlag(): ?string + protected function getFiles(): string { - foreach ($this->args as $arg) { - if (str_starts_with($arg, '--dir=')) { - $file = substr($arg, strlen('--dir=')); - $this->echoColor( - 'Executing analysis on ' . $file, - $this->color::get('YELLOW'), - $this->icon::get('STACK_TRACE') - ); - return $file; - } - } - return null; + return $this->argumentHandler->shouldAnalyzeAll() ? + $this->analyzeAllFiles() : + $this->getDirectoryOrBranchFiles(); } /** - * Returns an array of modified files in the git log. + * Analyze all files * - * @return string An array of modified files - * @throws Exception + * This method runs the analysis process for all files. */ - private function getDiffBranch(): string + protected function analyzeAllFiles(): string { - $gitLog = shell_exec("git diff --name-only $this->branch 2>&1"); - if ($gitLog === null) { - throw new RuntimeException('git log command failed'); - } - - return $this->getModifiedFiles(!$gitLog ? '' : $gitLog); + $this->echoAnalyzeAll(); + return '.'; } /** - * Returns an array of escaped shell arguments corresponding to modified files in the git log. + * Get the directory flag value from the command line arguments * - * @param string $gitLog The git log containing a list of modified files - * @return string + * @throws Exception */ - private function getModifiedFiles(string $gitLog): string + protected function getDirectoryOrBranchFiles(): string { - $gitLogLines = array_filter(explode("\n", trim($gitLog))); - $escapedFiles = []; - foreach ($gitLogLines as $line) { - if (str_ends_with($line, ".$this->extension") && is_file($line)) { - $escapedFiles[] = escapeshellarg($line); - } - } - if (empty($escapedFiles)) { - return ''; + $dir = $this->argumentHandler->getDirArg(); + if ($dir === '') { + return $this->fileHandler->getModifiedFilesGit(); } - return implode(' ', $escapedFiles); + return $this->extractDirFromArg($dir); } /** - * Echoes a colored message to the console. - * - * @param string $message The message to be echoed - * @param string $color The color to be applied to the message - * @param string $icon - * @return void + * Extract the directory from the argument. */ - private function echoColor(string $message, string $color, string $icon = ''): void + protected function extractDirFromArg(string $dir): string { - echo "\n"; - echo $icon . $color . ' ' . $message . $this->color::get('END'); - echo "\n"; - echo "\n"; + $dirFiles = $this->fileHandler->getModifiedFilesComa($dir); + $this->reportAnalysisExecute($dirFiles); + + return $dirFiles; } /** * Executes analysis on the files. * - * @param string $modifiedFiles The list of modified files passed as shell arguments - * @return bool Returns true if the analysis returns non-zero exit code, false otherwise + * Returns true if the analysis returns non-zero exit code, false otherwise */ - private function execute(string $modifiedFiles): bool + protected function execute(string $modifiedFiles): bool { - $additionalArgs = $this->getAdditionalArgs(); - $this->echoColor( - str_replace('%FILES%', $modifiedFiles, $this->command) . implode(' ', $additionalArgs), - $this->color::get('GREEN'), - $this->icon::get('COMMAND') - ); - $command = str_replace('%FILES%', $modifiedFiles, $this->command). ' ' . implode(' ', $additionalArgs); - passthru($command, $returnVar); - return $returnVar === 0; - } + echo $this->commandBuilder->buildCommand($modifiedFiles) . PHP_EOL; - /** - * Get the arguments for the analyzer - * - * @return array Returns an array of arguments to be passed to the analyzer - */ - private function getAdditionalArgs(): array - { - $toRemove = ['--all']; - $prefixToRemove = '--dir='; + passthru($this->commandBuilder->buildCommand($modifiedFiles), $returnVar); - return array_filter( - $this->args, - static function ($arg) use ($toRemove, $prefixToRemove) { - return !in_array($arg, $toRemove) && !str_starts_with($arg, $prefixToRemove); - } - ); + return $returnVar === 0; } } diff --git a/ci-scripts/Analyzer/AnalyzerSettings.php b/ci-scripts/Analyzer/AnalyzerSettings.php index d08badc..2b6230b 100644 --- a/ci-scripts/Analyzer/AnalyzerSettings.php +++ b/ci-scripts/Analyzer/AnalyzerSettings.php @@ -1,7 +1,14 @@ + * Constructor. + * + * @param array $args The arguments. Defaults to an empty array. */ - protected array $args; + public function __construct( + protected string $tool, + protected string $command, + protected array $args = [], + protected string $extension = 'php', + protected string $branch = 'origin/develop', + ) { + $this->color = new Color(); + $this->icon = new Icon(); + $this->fileHandler = new FileHandler($extension, $branch); + $this->commandBuilder = new CommandBuilder($command, $args); + $this->argumentHandler = new ArgumentHandler($args); + } /** - * @var string + * Echoes a colored message to the console. */ - protected string $extension = 'php'; + protected function echoColor( + string $message, + string $color, + string $icon = '' + ): void { + echo "\n"; + echo $icon . $color . ' ' . $message . $this->color::get('END'); + echo "\n"; + echo "\n"; + } /** - * @var string + * Report that no files were modified to analyze */ - protected string $tool = 'PHPStan'; + protected function reportNoFilesAnalyze(): void + { + $this->echoColor( + 'No files modified to analyze', + $this->color::get('BLUE'), + $this->icon::get('NO_FILES') + ); + } /** - * @var string + * Report that the analysis failed */ - protected string $command; + protected function reportAnalysisFailed(): void + { + $this->echoColor( + "{$this->tool} analysis succeeded", + $this->color::get('BLUE'), + $this->icon::get('SUCCESS') + ); + } /** - * Set the branch for the application. - * - * @param string $branch The branch name to set. - * @return void + * Report that the analysis succeeded */ - public function setBranch(string $branch): void + protected function reportAnalysisSucceeded(): void { - $this->branch = $branch; + $this->successMessage("{$this->tool} analysis succeeded"); } /** - * Sets the arguments. - * - * @param array $args The array of arguments. - * @return void + * Report that the analysis succeeded */ - public function setArgs(array $args): void + protected function successMessage(string $message, string $icon = ''): void { - $this->args = $args; + $this->echoColor( + $message, + $this->color::get('GREEN'), + $icon === '' ? $this->icon::get('SUCCESS') : $icon + ); } /** - * Set the extension for the given file. - * - * @param string $extension The extension to be set. - * @return void + * Report that Exception was thrown */ - public function setExtension(string $extension): void - { - $this->extension = $extension; + protected function reportExceptionThrown( + RuntimeException|Exception $exception + ): void { + $this->echoColor( + $exception->getMessage(), + $this->color::get('RED'), + $this->icon::get('EXCEPTION') + ); } /** - * Set the tool for the application. - * - * @param string $tool The tool to set. - * @return void + * Report analysis execute */ - public function setTool(string $tool): void + protected function reportAnalysisExecute(string $file): void { - $this->tool = $tool; + $this->echoColor( + 'Executing analysis on ' . $file, + $this->color::get('YELLOW'), + $this->icon::get('STACK_TRACE') + ); } /** - * Set the command. - * - * @param string $command The command to set. - * @return void + * Echo the analyzer all message. */ - public function setCommand(string $command): void + protected function echoAnalyzeAll(): void { - $this->command = $command; + $this->echoColor( + 'Executing analysis on .', + $this->color::get('YELLOW'), + $this->icon::get('STACK_TRACE') + ); } } diff --git a/ci-scripts/Analyzer/ArgumentHandler.php b/ci-scripts/Analyzer/ArgumentHandler.php new file mode 100644 index 0000000..312d351 --- /dev/null +++ b/ci-scripts/Analyzer/ArgumentHandler.php @@ -0,0 +1,45 @@ + $args The arguments. Defaults to an empty array. + */ + public function __construct( + protected array $args + ) { + } + + /** + * Check if it should analyze all files. + */ + public function shouldAnalyzeAll(): bool + { + return in_array('--all', $this->args, true); + } + + /** + * Get the directory argument from the list of arguments. + */ + public function getDirArg(): string + { + foreach ($this->args as $arg) { + if (str_starts_with($arg, '--dir=')) { + return $this->extractDirFromArg($arg); + } + } + return ''; + } + + /** + * Extract the directory from the argument. + */ + private function extractDirFromArg(string $arg): string + { + return substr($arg, strlen('--dir=')); + } +} diff --git a/ci-scripts/Analyzer/CommandBuilder.php b/ci-scripts/Analyzer/CommandBuilder.php new file mode 100644 index 0000000..ddf1363 --- /dev/null +++ b/ci-scripts/Analyzer/CommandBuilder.php @@ -0,0 +1,48 @@ + $args The arguments. Defaults to an empty array. + */ + public function __construct( + protected string $command, + protected array $args = [] + ) { + } + + /** + * Build the command to execute. + */ + public function buildCommand(string $modifiedFiles): string + { + $commandWithFiles = str_replace('%FILES%', $modifiedFiles, $this->command); + $moreArgs = implode(' ', $this->getAdditionalArgs()); + + return "{$commandWithFiles} {$moreArgs}"; + } + + /** + * Get the arguments for the analyzer + * + * @return array Returns an array of arguments to be + * passed to the analyzer + */ + protected function getAdditionalArgs(): array + { + $toRemove = ['--all']; + $prefixToRemove = '--dir='; + + return array_filter( + $this->args, + static function ($arg) use ($toRemove, $prefixToRemove) { + return !in_array($arg, $toRemove) && + !str_starts_with($arg, $prefixToRemove); + } + ); + } +} diff --git a/ci-scripts/Analyzer/Constants/Color.php b/ci-scripts/Analyzer/Constants/Color.php index 4023c0d..696ea19 100644 --- a/ci-scripts/Analyzer/Constants/Color.php +++ b/ci-scripts/Analyzer/Constants/Color.php @@ -1,5 +1,7 @@ getGitLog(); + $gitLogLines = array_filter(explode("\n", $gitLog)); + return $this->sanitizeFiles($gitLogLines); + } + + /** + * Get the modified files git log. + */ + public function getModifiedFilesComa(string $files): string + { + $fileLines = array_filter(explode(',', $files)); + return $this->sanitizeFiles($fileLines); + } + + /** + * Returns an array of escaped shell arguments corresponding to + * modified files in the git log. + * + * @param array $gitLogLines + */ + public function sanitizeFiles(array $gitLogLines): string + { + $escapedFiles = array_map( + 'escapeshellarg', + array_filter($gitLogLines, function ($line) { + return $this->isValidFile($line); + }) + ); + return implode(' ', $escapedFiles); + } + + /** + * Check if the file is valid for analysis. + */ + protected function isValidFile(string $line): bool + { + return str_ends_with($line, ".{$this->extension}") && is_file($line); + } + + /** + * Get the git log. + */ + private function getGitLog(): string + { + $gitLog = shell_exec("git diff --name-only {$this->branch} 2>&1"); + if ($gitLog === null || $gitLog === false) { + throw new RuntimeException('git log command failed'); + } + return trim($gitLog); + } +} diff --git a/ci-scripts/PhpMD/PhpMDAnalyzer.php b/ci-scripts/PhpMD/PhpMDAnalyzer.php new file mode 100644 index 0000000..b73119a --- /dev/null +++ b/ci-scripts/PhpMD/PhpMDAnalyzer.php @@ -0,0 +1,28 @@ + $args + * Constructor for the class, command is for validated in the + * PHP Mess Detector. + */ + public function __construct(array $args) + { + parent::__construct( + 'PHP Mess Detector', + <<analyze() ? 0 : 1); diff --git a/ci-scripts/PhpStan/PhpStanAnalyzer.php b/ci-scripts/PhpStan/PhpStanAnalyzer.php new file mode 100644 index 0000000..6f4bf19 --- /dev/null +++ b/ci-scripts/PhpStan/PhpStanAnalyzer.php @@ -0,0 +1,28 @@ + $args + * Constructor for the class, command is for validated in the PhpStan. + */ + public function __construct(array $args) + { + parent::__construct( + 'PHPStan', + <<analyze() ? 0 : 1); diff --git a/ci-scripts/Pint/PintAnalyzer.php b/ci-scripts/Pint/PintAnalyzer.php index ff4ef8d..b392d58 100644 --- a/ci-scripts/Pint/PintAnalyzer.php +++ b/ci-scripts/Pint/PintAnalyzer.php @@ -1,8 +1,8 @@ setArgs($args); - $this->setTool('Pint'); - $this->setCommand('./vendor/bin/pint --test --config ci-scripts/Pint/pint.json --ansi %FILES%'); - parent::__construct(); + parent::__construct( + 'Pint', + <<analyze() ? 0 : 1); diff --git a/ci-scripts/phpMD/PhpMDAnalyzer.php b/ci-scripts/phpMD/PhpMDAnalyzer.php deleted file mode 100644 index 5ffb4dd..0000000 --- a/ci-scripts/phpMD/PhpMDAnalyzer.php +++ /dev/null @@ -1,22 +0,0 @@ - $args - * Constructor for the class, command is for validated in the PHP Mess Detector. - */ - public function __construct(array $args) - { - $this->setArgs($args); - $this->setTool('PHP Mess Detector'); - $this->setCommand('./vendor/bin/phpmd %FILES% ansi cleancode,codesize,controversial,design,unusedcode --exclude *vendor'); - parent::__construct(); - } -} diff --git a/ci-scripts/phpMD/run.php b/ci-scripts/phpMD/run.php deleted file mode 100644 index 68b792e..0000000 --- a/ci-scripts/phpMD/run.php +++ /dev/null @@ -1,13 +0,0 @@ -analyze() ? 0 : 1); diff --git a/ci-scripts/phpStan/PhpStanAnalyzer.php b/ci-scripts/phpStan/PhpStanAnalyzer.php deleted file mode 100644 index e74773d..0000000 --- a/ci-scripts/phpStan/PhpStanAnalyzer.php +++ /dev/null @@ -1,21 +0,0 @@ - $args - * Constructor for the class, command is for validated in the PhpStan. - */ - public function __construct(array $args) - { - $this->setArgs($args); - $this->setCommand('./vendor/bin/phpstan analyse --memory-limit=1G -c ci-scripts/phpStan/phpstan.neon --ansi %FILES%'); - parent::__construct(); - } -} diff --git a/ci-scripts/phpStan/phpstan.neon b/ci-scripts/phpStan/phpstan.neon deleted file mode 100644 index eecec87..0000000 --- a/ci-scripts/phpStan/phpstan.neon +++ /dev/null @@ -1,10 +0,0 @@ -includes: -parameters: - paths: - - ../../src - # Level 9 is the highest level - level: 9 - ignoreErrors: - excludePaths: - - ../../vendor/* - checkMissingIterableValueType: true diff --git a/ci-scripts/phpStan/run.php b/ci-scripts/phpStan/run.php deleted file mode 100644 index 12579ff..0000000 --- a/ci-scripts/phpStan/run.php +++ /dev/null @@ -1,13 +0,0 @@ -analyze() ? 0 : 1); diff --git a/composer.json b/composer.json index 33b3b74..006760d 100644 --- a/composer.json +++ b/composer.json @@ -47,8 +47,14 @@ "phpmd/phpmd": "^2.15" }, "scripts": { - "phpstan": "php ci-scripts/phpStan/run.php", + "phpstan": "php ci-scripts/PhpStan/run.php", "pint": "php ci-scripts/Pint/run.php", - "phpmd": "php ci-scripts/phpMD/run.php" + "phpmd": "php ci-scripts/PhpMD/run.php" + + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } } } diff --git a/config/binding-provider.php b/config/binding-provider.php index cfcee60..4c4b12e 100644 --- a/config/binding-provider.php +++ b/config/binding-provider.php @@ -1,6 +1,8 @@ [ - ] + ], ]; diff --git a/docs/binding-service-provider/introduction.md b/docs/binding-service-provider/introduction.md index 59a214c..9947623 100644 --- a/docs/binding-service-provider/introduction.md +++ b/docs/binding-service-provider/introduction.md @@ -52,9 +52,8 @@ class BindingServiceProvider extends ServiceProvider /** * Registers the necessary commands for the application. - * Only registers the command if the application is running in the console and is in the local environment. - * - * @return void + * Only registers the command if the application is running in the + * console and is in the local environment. */ public function register(): void { diff --git a/docs/repository-interfaces/ICreateModel.md b/docs/repository-interfaces/ICreateModel.md index 2fe050d..20a4633 100644 --- a/docs/repository-interfaces/ICreateModel.md +++ b/docs/repository-interfaces/ICreateModel.md @@ -21,8 +21,6 @@ interface ICreateModel * Create a new record in the database. * * @param array $entity The object to be created. - * - * @return Model The created object. */ public function create(array $entity): Model; } diff --git a/docs/repository-interfaces/IDeleteModel.md b/docs/repository-interfaces/IDeleteModel.md index d2e0e0b..5bf3125 100644 --- a/docs/repository-interfaces/IDeleteModel.md +++ b/docs/repository-interfaces/IDeleteModel.md @@ -19,10 +19,6 @@ interface IDeleteModel { /** * Deletes a record from the database based on the given ID. - * - * @param Model $entity - * - * @return bool True if the record is successfully deleted, false otherwise. */ public function delete(Model $entity): bool; } diff --git a/docs/repository-interfaces/IEntityCount.md b/docs/repository-interfaces/IEntityCount.md index 93ec6d0..d352252 100644 --- a/docs/repository-interfaces/IEntityCount.md +++ b/docs/repository-interfaces/IEntityCount.md @@ -18,11 +18,6 @@ interface IEntityCount { /** * Counts the number of records in the database that match the given conditions. - * - * @param QueryFilters $options - * An associative array of conditions to match the records against. - * - * @return int The number of records that match the conditions. */ public function count(QueryFilters $options): int; } diff --git a/docs/repository-interfaces/IEntitySearch.md b/docs/repository-interfaces/IEntitySearch.md index 23b15b4..ca28fd4 100644 --- a/docs/repository-interfaces/IEntitySearch.md +++ b/docs/repository-interfaces/IEntitySearch.md @@ -19,11 +19,6 @@ interface IEntitySearch { /** * Finds a single record from the database that matches the given conditions. - * - * @param QueryFilters $options - * An associative array of conditions to match the record against. - * - * @return Model The fetched record if found. */ public function search(QueryFilters $options): Model; } diff --git a/docs/repository-interfaces/IListModel.md b/docs/repository-interfaces/IListModel.md index d9ba683..e2566f7 100644 --- a/docs/repository-interfaces/IListModel.md +++ b/docs/repository-interfaces/IListModel.md @@ -20,10 +20,6 @@ interface IListModel { /** * Lists records from the database based on the given conditions. - * - * @param QueryFilters $options - * - * @return LengthAwarePaginator An array of records that match the conditions. */ public function list(QueryFilters $options): LengthAwarePaginator; } diff --git a/docs/repository-interfaces/IReadModel.md b/docs/repository-interfaces/IReadModel.md index df985d9..6a58796 100644 --- a/docs/repository-interfaces/IReadModel.md +++ b/docs/repository-interfaces/IReadModel.md @@ -19,10 +19,6 @@ interface IReadModel { /** * Reads a record from the database based on the given ID. - * - * @param string $id The ID of the record to be fetched. - * - * @return Model The fetched record. */ public function read(string $id): Model; } diff --git a/docs/repository-interfaces/IUpdateModel.md b/docs/repository-interfaces/IUpdateModel.md index d6c3da9..2a5e57e 100644 --- a/docs/repository-interfaces/IUpdateModel.md +++ b/docs/repository-interfaces/IUpdateModel.md @@ -19,11 +19,7 @@ interface IUpdateModel { /** * Updates the given record in the database. - * - * @param Model $entity The record to be updated. * @param array $dataEntity - * - * @return bool True if the record was successfully updated, false otherwise. */ public function update(Model $entity, array $dataEntity): bool; } diff --git a/phpinsights.php b/phpinsights.php new file mode 100644 index 0000000..a579237 --- /dev/null +++ b/phpinsights.php @@ -0,0 +1,38 @@ + 'default', + 'remove' => [ + SlevomatCodingStandard\Sniffs\Classes\SuperfluousTraitNamingSniff::class, + NunoMaduro\PhpInsights\Domain\Insights\ForbiddenTraits::class, + PHP_CodeSniffer\Standards\Generic\Sniffs\Files\OneTraitPerFileSniff::class, + NunoMaduro\PhpInsights\Domain\Insights\ForbiddenNormalClasses::class, + SlevomatCodingStandard\Sniffs\Classes\SuperfluousExceptionNamingSniff::class, + SlevomatCodingStandard\Sniffs\Classes\SuperfluousInterfaceNamingSniff::class, + PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff::class, + PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\BacktickOperatorSniff::class, + SlevomatCodingStandard\Sniffs\TypeHints\DisallowMixedTypeHintSniff::class, + SlevomatCodingStandard\Sniffs\Commenting\InlineDocCommentDeclarationSniff::class, + ], + 'config' => [ + PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff::class => [ + 'lineLimit' => 120, + 'absoluteLineLimit' => 120, + ], + SlevomatCodingStandard\Sniffs\Functions\FunctionLengthSniff::class => [ + 'maxLinesLength' => 30, + ], + NunoMaduro\PhpInsights\Domain\Insights\CyclomaticComplexityIsHigh::class => [ + 'maxComplexity' => 7, + ], + NunoMaduro\PhpInsights\Domain\Insights\ForbiddenGlobals::class => [ + 'exclude' => [ + 'ci-scripts/phpMD/run.php', + 'ci-scripts/phpStan/run.php', + 'ci-scripts/Pint/run.php', + ], + ], + ], +]; diff --git a/src/BindingServiceProvider.php b/src/BindingServiceProvider.php index 5f52684..77c5bff 100644 --- a/src/BindingServiceProvider.php +++ b/src/BindingServiceProvider.php @@ -1,5 +1,7 @@ mergeConfigFrom(__DIR__ . '/../config/binding-provider.php', 'binding-provider'); + $this->mergeConfigFrom( + __DIR__ . '/../config/binding-provider.php', + 'binding-provider' + ); $this->bindInterfaces(); } /** * Binds interfaces to their implementations. - * - * @return void */ private function bindInterfaces(): void { @@ -41,7 +43,10 @@ private function bindInterfaces(): void } foreach ($bindings as $binding) { if (isset($binding['interface'], $binding['implementation'])) { - $this->app->bind($binding['interface'], $binding['implementation']); + $this->app->bind( + $binding['interface'], + $binding['implementation'] + ); } } } diff --git a/src/Classes/Options.php b/src/Classes/Options.php index ed188a5..7e138a1 100644 --- a/src/Classes/Options.php +++ b/src/Classes/Options.php @@ -1,5 +1,7 @@ seeder; + } /** - * @var bool $hasFactory Indicates if the factory would be to created + * Determines if the migration should be created. */ - public bool $hasFactory = false; + public function hasMigration(): bool + { + return $this->migration; + } /** - * @var bool $hasController Indicates if the controller would be to created + * Determines if the factory should be created. */ - public bool $hasController = false; + public function hasFactory(): bool + { + return $this->factory; + } /** - * @var bool $hasRequest Indicates if the request would be to created + * Determines if the service should be created. */ - public bool $hasRequest = false; + public function hasService(): bool + { + return $this->service; + } /** - * @var bool $hasService Indicates if the service would be to created + * Determines if the controller should be created. */ - public bool $hasService = false; + public function hasController(): bool + { + return $this->controller; + } /** - * @var bool $hasSeeder Indicates if the seeder would be to created + * Determines if the request should be created. */ - public bool $hasSeeder = false; + public function hasRequest(): bool + { + return $this->request; + } /** - * @var bool $force Indicates if the command should be forced + * Determines if the operation should be forced. */ - public bool $force = false; + public function isForce(): bool + { + return $this->force; + } /** * Set all force options to true if $all is true. - * - * @param bool $all Whether to force all options or not. - * @return void */ - public function forceAll(bool $all): void + public function forceAll(): void { - if (!$all) { - return; - } - $this->hasMigration = true; - $this->hasController = true; - $this->hasRequest = true; - $this->hasService = true; - $this->hasSeeder = true; - $this->hasFactory = true; + $this->seeder = true; + $this->migration = true; + $this->factory = true; + $this->service = true; + $this->controller = true; + $this->request = true; } } diff --git a/src/Commands/Handlers.php b/src/Commands/Handlers.php index 32cd556..bd73a96 100644 --- a/src/Commands/Handlers.php +++ b/src/Commands/Handlers.php @@ -1,47 +1,81 @@ argument('name'); $mainCommand->setOutput($this->components); - /** @var string $name */ - $mainCommand->handle($this, $name, new Options()); + $mainCommand->handle($this, $name, $this->getOptionsCommand()); + } + + /** + * Retrieve the options from the command input. + */ + private function getOptionsCommand(): Options + { + $optionsList = $this->getOptionsList(); + $optionValues = $this->initializeOptionValues($optionsList); + + foreach ($optionsList as $option => $commandOption) { + $optionValues[$option] = $this->evaluateOption($commandOption); + } + + $options = $this->createOptionsObject($optionValues); + + if ($this->shouldForceAll()) { + $options->forceAll(); + } + + return $options; } } diff --git a/src/Contracts/Resources/ICreateModel.php b/src/Contracts/Resources/ICreateModel.php index d358d5a..ab0a6e8 100644 --- a/src/Contracts/Resources/ICreateModel.php +++ b/src/Contracts/Resources/ICreateModel.php @@ -1,5 +1,7 @@ $entity The object to be created. - * - * @return Model The created object. */ public function create(array $entity): Model; } diff --git a/src/Contracts/Resources/IDeleteModel.php b/src/Contracts/Resources/IDeleteModel.php index 95c4eac..4f95a0b 100644 --- a/src/Contracts/Resources/IDeleteModel.php +++ b/src/Contracts/Resources/IDeleteModel.php @@ -1,5 +1,7 @@ $dataEntity - * - * @return bool True if the record was successfully updated, false otherwise. */ public function update(Model $entity, array $dataEntity): bool; } diff --git a/src/Exception/Command/CreateStructureException.php b/src/Exception/Command/CreateStructureException.php index 6b9ff47..f0eb15a 100644 --- a/src/Exception/Command/CreateStructureException.php +++ b/src/Exception/Command/CreateStructureException.php @@ -1,5 +1,7 @@ $type, 'path' => $path] ); } diff --git a/src/Exception/CustomException.php b/src/Exception/CustomException.php index b534e87..2ce69c4 100644 --- a/src/Exception/CustomException.php +++ b/src/Exception/CustomException.php @@ -1,5 +1,7 @@ $input Optional. An array of input data associated with the error. + * @param array $input Optional. An array + * of input data associated with the error. * Default is an empty array. - * this used to store the input data who caused the error, not has a structure or typed defined. + * this used to store the input data who caused the error, + * not has a structure or typed defined. * For this reason, use mixed - * @param int $code Optional. The error code. Default is Response::HTTP_BAD_REQUEST. - * @param Exception|null $previous Optional. The previous exception used for the exception chaining. Default is null. */ public function __construct( string $title, @@ -57,15 +58,28 @@ public function __construct( $this->input = $input; } + /** + * Returns a string representation of the object. + * + * The returned string includes the name of the class, the error code, and + * the error message. + */ + public function __toString(): string + { + $message = " [{$this->code}] {$this->title}: {$this->message}\n"; + return static::class . $message; + } + /** * Returns the input data stored in the object. * - * This method returns an array containing the input data stored in the object. - * The input data represents the information provided to the object during its creation or at a later stage. + * This method returns an array containing the input data + * stored in the object. + * The input data represents the information provided to the object + * during its creation or at a later stage. * * @return array The input data stored in the object. * It is mixed because we can have anything to identify the error - * */ public function getInput(): array { @@ -76,24 +90,9 @@ public function getInput(): array * Returns the title of the object. * * The returned array contains the title of the object. - * - * @return string The title of the object. */ public function getTitle(): string { return $this->title; } - - - /** - * Returns a string representation of the object. - * - * The returned string includes the name of the class, the error code, and the error message. - * - * @return string A string representation of the object. - */ - public function __toString(): string - { - return get_class($this) . " [$this->code] $this->title: $this->message\n"; - } } diff --git a/src/Handlers/BindingServices.php b/src/Handlers/BindingServices.php index a0189de..969761c 100644 --- a/src/Handlers/BindingServices.php +++ b/src/Handlers/BindingServices.php @@ -1,78 +1,34 @@ - [ - 'interface' => $interfaceClass, - 'implementation' => $serviceClass, - ] + $name => [ + 'interface' => $interfaceClass, + 'implementation' => $serviceClass, + ], ]; $configContent = $this->formatConfigFile($config, $newBindings); file_put_contents($configPath, $configContent); } - - /** - * Format the configuration file content. - * - * @param array{interfaces: array} $config The existing configuration array. - * @param array $newBindings The new bindings to be added. - * @return string The formatted configuration file content. - */ - private function formatConfigFile(array $config, array $newBindings): string - { - $config['interfaces'] = array_merge($config['interfaces'], $newBindings); - - return 'formatArray($config) . PHP_EOL . '];' . PHP_EOL; - } - - /** - * Format an array into a string representation. - * - * @param array $array The array to format. - * @param int $indentLevel The level of indentation to use. - * @return string The formatted array as a string. - */ - public function formatArray(array $array, int $indentLevel = 1): string - { - $indent = str_repeat(' ', $indentLevel); - $lines = []; - - foreach ($array as $key => $value) { - if (is_array($value)) { - $lines[] = $indent . "'" . $key . "' => ["; - $lines[] = $this->formatArray($value, $indentLevel + 1); - $lines[] = $indent . "],"; - continue; - } - if (str_contains($key, 'interface') || str_contains($key, 'implementation')) { - $lines[] = $indent . "'" . $key . "' => " . $value . '::class,'; - continue; - } - - $lines[] = $indent . "'" . $key . "' => '" . $value . "',"; - } - - return implode(PHP_EOL, $lines); - } } diff --git a/src/Handlers/MainCommand.php b/src/Handlers/MainCommand.php index b72f12f..e03740d 100644 --- a/src/Handlers/MainCommand.php +++ b/src/Handlers/MainCommand.php @@ -1,5 +1,7 @@ */ - protected string $name; + private array $hasBinding = [ + MakeRepository::class, + MakeService::class, + ]; /** * Constructor for the class. - * - * @param MakeModel $makeModel The MakeModel instance. - * @param MakeRepository $makeRepository The MakeRepository instance. - * @param MakeService $makeService The MakeService instance. - * @param MakeInterfaceServices $makeInterfaceServices The MakeInterface instance. - * @param MakeController $makeController The MakeController instance. - * @param MakeRequest $makeRequest The MakeRequest instance. */ public function __construct( protected MakeModel $makeModel, @@ -58,51 +49,31 @@ public function __construct( ) { } - /** * Sets the output object to be used for displaying messages. - * - * @param Factory $output The output object to be set. - * @return void */ public function setOutput(Factory $output): void { $this->output = $output; } - public function handle(Command $command, string $name, Options $options): void - { + /** + * Handles the command execution. + */ + public function handle( + Command $command, + string $name, + Options $options + ): void { $this->command = $command; $this->name = $name; $this->options = $options; - $this->getOptions(); $this->run(); } /** - * Retrieves the options from the command line arguments and assigns them to the corresponding properties. - * - * This method checks for the presence of specific options and assigns the corresponding values to the - * properties of the class instance. - * - * @return void - */ - private function getOptions(): void - { - $this->options->hasSeeder = boolval($this->command->option('seed')); - $this->options->hasMigration = boolval($this->command->option('migration')); - $this->options->hasFactory = boolval($this->command->option('factory')); - $this->options->hasService = boolval($this->command->option('service')); - $this->options->hasController = boolval($this->command->option('controller')); - $this->options->hasRequest = boolval($this->command->option('request')); - $this->options->forceAll(boolval($this->command->option('all'))); - $this->options->force = boolval($this->command->option('force')); - } - - /** - * Executes the series of commands to generate the necessary files for a given resource. - * - * @return void + * Executes the series of commands to generate the necessary files for a + * given resource. */ public function run(): void { @@ -119,20 +90,23 @@ public function run(): void * Displays an info message about a command. * * @param array{type: string, path: string} $info - * - * @return void */ public function infoCommand(array $info): void { - $this->output->info(sprintf('%s [%s] created successfully.', $info['type'], $info['path'])); + $this->output->info( + sprintf( + '%s [%s] created successfully.', + $info['type'], + $info['path'] + ) + ); } /** * Displays an error message. * - * @param string $message The error message to be displayed. - * @param array{type: string, path: string} $info Additional information about the error. - * @return void + * @param array{type: string, path: string} $info Additional information + * about the error. */ public function errorCommand(string $message, array $info): void { @@ -141,8 +115,6 @@ public function errorCommand(string $message, array $info): void /** * Creates a model based on the given name and options. - * - * @return void */ private function makeModel(): void { @@ -150,124 +122,83 @@ private function makeModel(): void } /** - * Create an interface for the repository. - * - * @return void + * Executes the maker for creating an interface repository. */ private function makeInterfaceRepository(): void { - try { - $result = $this->makeInterfaceRepository->make($this->name, $this->options); - } catch (StubException|CreateStructureException $exception) { - $info = $exception->getInput(); - /** @var array{type: string, path: string} $info */ - $this->errorCommand($exception->getMessage(), $info); - return; - } - $this->infoCommand($result); + $this->executeMaker($this->makeInterfaceRepository); } /** - * Make a repository with the given name. - * - * @return void + * Executes the makeRepository method. */ private function makeRepository(): void { - try { - $result = $this->makeRepository->make($this->name, $this->options); - $this->makeRepository->binding($this->name); - } catch (StubException|CreateStructureException $exception) { - $info = $exception->getInput(); - /** @var array{type: string, path: string} $info */ - $this->errorCommand($exception->getMessage(), $info); - return; - } - $this->infoCommand($result); + $this->executeMaker($this->makeRepository); } /** - * Create an interface if the options flag hasInterface is true. + * Make interface service. + * * - * @return void + * If the options include a service, execute the maker for creating an interface services file. */ private function makeInterfaceService(): void { - if (!$this->options->hasService) { - return; + if ($this->options->hasService()) { + $this->executeMaker($this->makeInterfaceServices); } - try { - $result = $this->makeInterfaceServices->make($this->name, $this->options); - } catch (StubException|CreateStructureException $exception) { - $info = $exception->getInput(); - /** @var array{type: string, path: string} $info */ - $this->errorCommand($exception->getMessage(), $info); - return; - } - $this->infoCommand($result); } /** - * Makes a service. - * - * @return void + * Make a service. */ private function makeService(): void { - if (!$this->options->hasService) { - return; + if ($this->options->hasService()) { + $this->executeMaker($this->makeService); } - try { - $result = $this->makeService->make($this->name, $this->options); - $this->makeService->binding($this->name); - } catch (StubException|CreateStructureException $exception) { - $info = $exception->getInput(); - /** @var array{type: string, path: string} $info */ - $this->errorCommand($exception->getMessage(), $info); - return; - } - $this->infoCommand($result); } /** - * Generates a controller. - * - * @return void + * Makes a controller based on the given options. */ private function makeController(): void { - if (!$this->options->hasController) { - return; - } - try { - $result = $this->makeController->make($this->name, $this->options); - } catch (StubException|CreateStructureException $exception) { - $info = $exception->getInput(); - /** @var array{type: string, path: string} $info */ - $this->errorCommand($exception->getMessage(), $info); - return; + if ($this->options->hasController()) { + $this->executeMaker($this->makeController); } - $this->infoCommand($result); } /** - * Makes a request if the options haveRequest is set to true. - * - * @void + * Make a request. */ private function makeRequest(): void { - if (!$this->options->hasRequest) { - return; + if ($this->options->hasRequest()) { + $this->executeMaker($this->makeRequest); } + } + + /** + * Executes the Maker. + * + * This method executes a Maker by calling its `make` method with the given options. + * If the `bind` parameter is set to `true`, it also calls the Maker's `binding` method. + */ + private function executeMaker( + MakeRepository|MakeInterfaceRepository|MakeService|MakeInterfaceServices|MakeController|MakeRequest $maker, + ): void { try { - $result = $this->makeRequest->make($this->name, $this->options); + $result = $maker->make($this->name, $this->options); + if (in_array(get_class($maker), $this->hasBinding, true)) { + $maker->binding($this->name); + } + $this->infoCommand($result); } catch (StubException|CreateStructureException $exception) { $info = $exception->getInput(); /** @var array{type: string, path: string} $info */ $this->errorCommand($exception->getMessage(), $info); - return; } - $this->infoCommand($result); } } diff --git a/src/Handlers/Makers/MakeController.php b/src/Handlers/Makers/MakeController.php index 7d3d40f..e4fd562 100644 --- a/src/Handlers/Makers/MakeController.php +++ b/src/Handlers/Makers/MakeController.php @@ -1,5 +1,7 @@ defineReplace($name); + $directory = app_path("Http/Controllers/{$name}"); + $path = $this->getFilePath($directory, $name, $this->type); + + return $this->createFromClassStub( + $path, + $replace, + $this->type, + $options + ); + } /** * Define replace method. * - * This method is used to define and return an array of replace keys and values. + * This method is used to define and return an array of replace keys and + * values. * * @return array An array of replace keys and values. */ @@ -35,23 +58,4 @@ private function defineReplace(string $name): array 'ModelUri' => $this->namePluralSnakeCase($name), ]; } - - /** - * Create a repository file for a given name at the specified path. - * - * @param string $name The name of the repository. - * @param Options $options - * @return array{type: string, path: string} - * - * @throws StubException - * @throws CreateStructureException - */ - public function make(string $name, Options $options): array - { - $replace = $this->defineReplace($name); - $directory = app_path("Http/Controllers/$name"); - $path = $this->getFilePath($directory, $name, $this->type); - - return $this->createFromClassStub($path, $replace, $this->type, $options); - } } diff --git a/src/Handlers/Makers/MakeInterfaceRepository.php b/src/Handlers/Makers/MakeInterfaceRepository.php index 243ca57..68bfc09 100644 --- a/src/Handlers/Makers/MakeInterfaceRepository.php +++ b/src/Handlers/Makers/MakeInterfaceRepository.php @@ -1,5 +1,7 @@ An array of replace keys and values. - */ - private function defineReplace(string $name): array - { - return [ - 'DummyModel' => $name, - 'DummyClass' => 'I' . $name . 'Repository' - ]; - } - /** * Create a repository file for a given name at the specified path. * - * @param string $name The name of the repository. - * @param Options $options * @return array{type: string, path: string} * * @throws StubException @@ -47,9 +30,34 @@ private function defineReplace(string $name): array public function make(string $name, Options $options): array { $replace = $this->defineReplace($name); - $directory = app_path("Contracts/Repositories/$name"); - $path = $this->getFilePath($directory, 'I' . $name, 'Repository'); + $directory = app_path("Contracts/Repositories/{$name}"); + $path = $this->getFilePath( + $directory, + 'I' . $name, + 'Repository' + ); + + return $this->createFromClassStub( + $path, + $replace, + $this->type, + $options + ); + } - return $this->createFromClassStub($path, $replace, $this->type, $options); + /** + * Define replace method. + * + * This method is used to define and return an array of replace keys and + * values. + * + * @return array An array of replace keys and values. + */ + private function defineReplace(string $name): array + { + return [ + 'DummyModel' => $name, + 'DummyClass' => 'I' . $name . 'Repository', + ]; } } diff --git a/src/Handlers/Makers/MakeInterfaceServices.php b/src/Handlers/Makers/MakeInterfaceServices.php index f8ed661..08cb98f 100644 --- a/src/Handlers/Makers/MakeInterfaceServices.php +++ b/src/Handlers/Makers/MakeInterfaceServices.php @@ -1,5 +1,7 @@ An array of replace keys and values. - */ - private function defineReplace(string $name): array - { - return [ - 'DummyModel' => $name, - 'DummyClass' => 'I' . $name . 'Service' - ]; - } - /** * Create a repository file for a given name at the specified path. * - * @param string $name The name of the repository. - * @param Options $options * @return array{type: string, path: string} * * @throws StubException @@ -47,9 +30,34 @@ private function defineReplace(string $name): array public function make(string $name, Options $options): array { $replace = $this->defineReplace($name); - $directory = app_path("Contracts/Services/$name"); - $path = $this->getFilePath($directory, 'I' . $name, 'Service'); + $directory = app_path("Contracts/Services/{$name}"); + $path = $this->getFilePath( + $directory, + 'I' . $name, + 'Service' + ); + + return $this->createFromClassStub( + $path, + $replace, + $this->type, + $options + ); + } - return $this->createFromClassStub($path, $replace, $this->type, $options); + /** + * Define replace method. + * + * This method is used to define and return an array of replace keys and + * values. + * + * @return array An array of replace keys and values. + */ + private function defineReplace(string $name): array + { + return [ + 'DummyModel' => $name, + 'DummyClass' => 'I' . $name . 'Service', + ]; } } diff --git a/src/Handlers/Makers/MakeModel.php b/src/Handlers/Makers/MakeModel.php index d052453..307df80 100644 --- a/src/Handlers/Makers/MakeModel.php +++ b/src/Handlers/Makers/MakeModel.php @@ -1,5 +1,7 @@ call( 'make:model', [ 'name' => $name . '/' . $name, - '--migration' => $options->hasMigration, - '--seed' => $options->hasSeeder, - '--factory' => $options->hasFactory, - '--force' => $options->force + '--migration' => $options->hasMigration(), + '--seed' => $options->hasSeeder(), + '--factory' => $options->hasFactory(), + '--force' => $options->isForce(), ] ); } diff --git a/src/Handlers/Makers/MakeRepository.php b/src/Handlers/Makers/MakeRepository.php index 0e068b6..5712fde 100644 --- a/src/Handlers/Makers/MakeRepository.php +++ b/src/Handlers/Makers/MakeRepository.php @@ -1,5 +1,7 @@ An array of replace keys and values. - */ - private function defineReplace(string $name): array - { - return [ - 'DummyModel' => $name, - 'DummyClass' => $name . $this->type, - 'DummyInterface' => 'I' . $name . $this->type, - ]; - } - /** * Create a repository file for a given name at the specified path. * - * @param string $name The name of the repository - * @param Options $options The options for the repository * @return array{type: string, path: string} * * @throws StubException @@ -47,22 +32,48 @@ private function defineReplace(string $name): array public function make(string $name, Options $options): array { $replace = $this->defineReplace($name); - $directory = app_path("Repositories/$name"); + $directory = app_path("Repositories/{$name}"); $path = $this->getFilePath($directory, $name, $this->type); - return $this->createFromClassStub($path, $replace, $this->type, $options); + return $this->createFromClassStub( + $path, + $replace, + $this->type, + $options + ); } /** - * Bind a service implementation to its corresponding interface in the configuration file. - * - * @param string $name The name of the service. - * @return void + * Bind a service implementation to its corresponding interface in the + * configuration file. */ public function binding(string $name): void { - $service = $this->repositoryNameSpace . '\\' . $name . '\\' . $name . $this->type; - $interface = $this->interfaceNameSpace . '\\' . $name . '\\' . 'I' . $name . $this->type; - $this->updateConfigFile($this->nameSnakeCase($name) . '-repository', $interface, $service); + $pathService = "{$this->repositoryNameSpace}\\{$name}\\"; + $pathInterface = "{$this->interfaceNameSpace}\\{$name}\\"; + $service = "{$pathService}{$name}{$this->type}"; + $interface = "{$pathInterface}I{$name}{$this->type}"; + $this->updateConfigFile( + $this->nameSnakeCase($name) . '-repository', + $interface, + $service + ); + } + + /** + * Define replace method. + * + * This method is used to define and return an array of replace keys and + * values. + * + * @return array An array of replace keys and values. + */ + private function defineReplace(string $name): array + { + return [ + 'DummyModel' => $name, + 'DummyClass' => $name . $this->type, + 'DummyInterface' => 'I' . $name . $this->type, + ]; } } diff --git a/src/Handlers/Makers/MakeRequest.php b/src/Handlers/Makers/MakeRequest.php index b497fb6..160b17c 100644 --- a/src/Handlers/Makers/MakeRequest.php +++ b/src/Handlers/Makers/MakeRequest.php @@ -1,5 +1,7 @@ An array of replace keys and values. - */ - private function defineReplace(string $name): array - { - return [ - 'DummyModel' => $name, - 'DummyClass' => $name . $this->type - ]; - } - /** * Create a repository file for a given name at the specified path. * - * @param string $name The name of the repository. - * @param Options $options * @return array{type: string, path: string} * * @throws StubException @@ -47,9 +30,30 @@ private function defineReplace(string $name): array public function make(string $name, Options $options): array { $replace = $this->defineReplace($name); - $directory = app_path("Http/Requests/$name"); + $directory = app_path("Http/Requests/{$name}"); $path = $this->getFilePath($directory, $name, $this->type); - return $this->createFromClassStub($path, $replace, $this->type, $options); + return $this->createFromClassStub( + $path, + $replace, + $this->type, + $options + ); + } + + /** + * Define replace method. + * + * This method is used to define and return an array of replace keys and + * values. + * + * @return array An array of replace keys and values. + */ + private function defineReplace(string $name): array + { + return [ + 'DummyModel' => $name, + 'DummyClass' => $name . $this->type, + ]; } } diff --git a/src/Handlers/Makers/MakeService.php b/src/Handlers/Makers/MakeService.php index 8511b6c..b037f6a 100644 --- a/src/Handlers/Makers/MakeService.php +++ b/src/Handlers/Makers/MakeService.php @@ -1,5 +1,7 @@ An array of replace keys and values. - */ - private function defineReplace(string $name): array - { - return [ - 'DummyModel' => $name, - 'DummyClass' => $name . $this->type, - 'DummyRepository' => 'I' . $name . 'Repository', - 'DummyInterface' => 'I' . $name . $this->type, - ]; - } - /** * Create a repository file for a given name at the specified path. * - * @param string $name The name of the repository. - * @param Options $options * @return array{type: string, path: string} * * @throws StubException @@ -51,22 +32,49 @@ private function defineReplace(string $name): array public function make(string $name, Options $options): array { $replace = $this->defineReplace($name); - $directory = app_path("Services/$name"); + $directory = app_path("Services/{$name}"); $path = $this->getFilePath($directory, $name, $this->type); - return $this->createFromClassStub($path, $replace, $this->type, $options); + return $this->createFromClassStub( + $path, + $replace, + $this->type, + $options + ); } /** - * Bind a service implementation to its corresponding interface in the configuration file. - * - * @param string $name The name of the service. - * @return void + * Bind a service implementation to its corresponding interface in the + * configuration file. */ public function binding(string $name): void { - $service = $this->serviceNameSpace . '\\' . $name . '\\' . $name . $this->type; - $interface = $this->interfaceNameSpace . '\\' . $name . '\\' . 'I' . $name . $this->type; - $this->updateConfigFile($this->nameSnakeCase($name) . '-service', $interface, $service); + $pathService = "{$this->serviceNameSpace}\\{$name}\\"; + $pathInterface = "{$this->interfaceNameSpace}\\{$name}\\"; + $service = "{$pathService}{$name}{$this->type}"; + $interface = "{$pathInterface}I{$name}{$this->type}"; + $this->updateConfigFile( + $this->nameSnakeCase($name) . '-service', + $interface, + $service + ); + } + + /** + * Define replace method. + * + * This method is used to define and return an array of replace keys and + * values. + * + * @return array An array of replace keys and values. + */ + private function defineReplace(string $name): array + { + return [ + 'DummyModel' => $name, + 'DummyClass' => $name . $this->type, + 'DummyRepository' => 'I' . $name . 'Repository', + 'DummyInterface' => 'I' . $name . $this->type, + ]; } } diff --git a/src/Handlers/Makers/MakeStructure.php b/src/Handlers/Makers/MakeStructure.php index e56c285..769f529 100644 --- a/src/Handlers/Makers/MakeStructure.php +++ b/src/Handlers/Makers/MakeStructure.php @@ -1,22 +1,20 @@ $replacements - * @param string $type - * @param Options $options + * * @return array{type: string, path: string} + * * @throws StubException|CreateStructureException */ protected function createFromClassStub( @@ -55,37 +52,36 @@ protected function createFromClassStub( /** * Validate if the class exists. * - * @param string $classPath The file path of the class. - * @param string $type The type of the class (e.g., interface, service). - * @param Options $options The options for creating the class. - * @return void - * @throws CreateStructureException If the class already exists and force option is false. + * @throws CreateStructureException If the class already + * exists and force option is false. */ - protected function validateClassExists(string $classPath, string $type, Options $options): void - { - if ($this->file::exists($classPath) && !$options->force) { - throw new CreateStructureException('already exists', $type, $classPath); + protected function validateClassExists( + string $classPath, + string $type, + Options $options + ): void { + if ($this->file::exists($classPath) && !$options->isForce()) { + throw new CreateStructureException( + 'already exists', + $type, + $classPath + ); } } /** * Retrieves the path of the stub file based on the given type. - * - * @param string $type The type of the stub file. - * - * @return string The path of the stub file. */ protected function getStubPath(string $type): string { - return strval(realpath(__DIR__ . '/../../../stubs/' . $type . '.stub')); + return strval( + realpath(__DIR__ . '/../../../stubs/' . $type . '.stub') + ); } /** * Retrieves the content of a stub file based on the given type. * - * @param string $type The type of the stub. - * - * @return string The content of the stub file. * @throws StubException */ protected function getStubContent(string $type): string @@ -100,39 +96,41 @@ protected function getStubContent(string $type): string /** * Returns the file path for the given directory, name, and type. - * - * @param string $directory The directory where the file will be located. - * @param string $name The name of the file. - * @param string $type The type of the file. - * - * @return string The file path. */ - protected function getFilePath(string $directory, string $name, string $type): string - { + protected function getFilePath( + string $directory, + string $name, + string $type + ): string { if (!$this->file::exists($directory)) { - $this->file::makeDirectory($directory, 0755, true, true); + $this->file::makeDirectory( + $directory, + 0755, + true, + true + ); } return $directory . "/{$name}{$type}.php"; } /** - * Update the configuration file with the given interface and service classes. - * - * @param string $name The name of the binding. - * @param string $interfaceClass The fully qualified class name of the interface. - * @param string $serviceClass The fully qualified class name of the service. - * @return void + * Update the configuration file with the given + * interface and service classes. */ - protected function updateConfigFile(string $name, string $interfaceClass, string $serviceClass): void - { - $this->bindingServices->updateConfigFile($name, $interfaceClass, $serviceClass); + protected function updateConfigFile( + string $name, + string $interfaceClass, + string $serviceClass + ): void { + $this->bindingServices->updateConfigFile( + $name, + $interfaceClass, + $serviceClass + ); } /** * Convert the given name to snake case. - * - * @param string $name The name to be converted. - * @return string The converted name in snake case. */ protected function nameSnakeCase(string $name): string { @@ -141,9 +139,6 @@ protected function nameSnakeCase(string $name): string /** * Returns the plural form of the given name in snake case. - * - * @param string $name The name to convert to plural snake case. - * @return string The plural form of the given name in snake case. */ protected function namePluralSnakeCase(string $name): string { diff --git a/src/RepositoryCommandServiceProvider.php b/src/RepositoryCommandServiceProvider.php index 54edcd8..c1372e6 100644 --- a/src/RepositoryCommandServiceProvider.php +++ b/src/RepositoryCommandServiceProvider.php @@ -1,10 +1,12 @@ app instanceof LaravelApplication && $this->app->runningInConsole() && $this->app->isLocal()) { + if ( + $this->app instanceof LaravelApplication + && $this->app->runningInConsole() && $this->app->isLocal() + ) { $this->commands([ Handlers::class, ]); diff --git a/src/Trait/ArrayHandlerBindingTrait.php b/src/Trait/ArrayHandlerBindingTrait.php new file mode 100644 index 0000000..a3d5642 --- /dev/null +++ b/src/Trait/ArrayHandlerBindingTrait.php @@ -0,0 +1,118 @@ +>|string>|array $array + * The array to format. + */ + private function formatArray(array $array, int $indentLevel = 1): string + { + $indent = str_repeat(' ', $indentLevel); + $lines = $this->generateLines($array, $indentLevel, $indent); + + return implode(PHP_EOL, $lines); + } + + /** + * Format the configuration file content. + * + * @param array{ + * interfaces: array + * } $config + * The existing configuration array. + * @param array $newBindings + * The new bindings to be added. + */ + private function formatConfigFile(array $config, array $newBindings): string + { + $config['interfaces'] = array_merge( + $config['interfaces'], + $newBindings + ); + $configContent = $this->formatArray($config); + $eol = PHP_EOL; + + return ">|string> $array + * + * @return array + * */ + private function generateLines(array $array, int $indentLevel, string $indent): array + { + $lines = []; + foreach ($array as $key => $value) { + if (is_array($value)) { + /** @var array>|string>|array $value */ + $lines = $this->formatNestedArrayValue( + $lines, + $value, + $key, + $indent, + $indentLevel + ); + continue; + } + if ($this->isInterface($key)) { + $lines[] = $this->formatClassReference($key, $value, $indent); + continue; + } + $lines[] = "{$indent}'{$key}' => '{$value}',"; + } + return $lines; + } + + /** + * Format the nested array value. + * + * @param array $lines The lines of the formatted array. + * @param array>|string>|array $value + * The nested array value. + * + * @return array The formatted array lines. + */ + private function formatNestedArrayValue( + array $lines, + array $value, + string $key, + string $indent, + int $indentLevel + ): array { + $lines[] = "{$indent}'{$key}' => ["; + $lines[] = $this->formatArray($value, $indentLevel + 1); + $lines[] = "{$indent}],"; + return $lines; + } + + /** + * Format the class reference as a Laravel service declaration. + */ + private function formatClassReference(string $key, string $value, string $indent): string + { + return "{$indent}'{$key}' => {$value}::class,"; + } + + /** + * Check if the given key is an interface. + */ + private function isInterface(string $key): bool + { + return str_contains($key, 'interface') || + str_contains($key, 'implementation'); + } +} diff --git a/src/Trait/FailedValidationTrait.php b/src/Trait/FailedValidationTrait.php index d269a0f..d52637a 100644 --- a/src/Trait/FailedValidationTrait.php +++ b/src/Trait/FailedValidationTrait.php @@ -1,5 +1,7 @@ errors(); - $formattedErrors = []; foreach ($errors as $field => $message) { $formattedErrors[] = [ 'field' => $field, 'title' => 'Failed request validation', - "message" => 'Invalid data', - "detail" => $message + 'message' => 'Invalid data', + 'detail' => $message, ]; } throw new HttpResponseException( - response()->json(['errors' => $formattedErrors], Response::HTTP_UNPROCESSABLE_ENTITY) + response()->json( + ['errors' => $formattedErrors], + Response::HTTP_UNPROCESSABLE_ENTITY + ) ); } } diff --git a/src/Trait/OptionsTrait.php b/src/Trait/OptionsTrait.php new file mode 100644 index 0000000..0f6c629 --- /dev/null +++ b/src/Trait/OptionsTrait.php @@ -0,0 +1,31 @@ +|string $commandOption The command option to be evaluated + */ + private function evaluateOption(array|string $commandOption): bool + { + if (is_array($commandOption)) { + foreach ($commandOption as $value) { + if ($this->hasOption($value)) { + return boolval($this->option($value)); + } + } + return false; + } + return $this->hasOption($commandOption) && boolval($this->option($commandOption)); + } +} diff --git a/src/Trait/PopulatesOptionsTrait.php b/src/Trait/PopulatesOptionsTrait.php new file mode 100644 index 0000000..c73a84c --- /dev/null +++ b/src/Trait/PopulatesOptionsTrait.php @@ -0,0 +1,92 @@ +, + * hasMigration: array, + * hasFactory: array, + * hasService: array, + * hasController: array, + * hasRequest: array, + * force: string + * } Returns an array of options. + */ + private function getOptionsList(): array + { + return [ + 'hasSeeder' => ['seed', 'sd'], + 'hasMigration' => ['migration', 'm'], + 'hasFactory' => ['factory', 'f'], + 'hasService' => ['service', 's'], + 'hasController' => ['controller', 'c'], + 'hasRequest' => ['request', 'r'], + 'force' => 'force', + ]; + } + + /** + * Initializes the option values with false for each option in the provided options list. + * + * @param array{ + * hasSeeder: array, + * hasMigration: array, + * hasFactory: array, + * hasService: array, + * hasController: array, + * hasRequest: array, + * force: string + * } $optionsList The list of options. + * + * @return array The initialized option values. + */ + private function initializeOptionValues(array $optionsList): array + { + $optionValues = []; + $options = array_keys($optionsList); + foreach ($options as $option) { + $optionValues[$option] = false; + } + return $optionValues; + } + + /** + * Create a new Options object based on the given option values. + * + * @param array $optionValues An associative array containing the option values. + */ + private function createOptionsObject(array $optionValues): Options + { + return new Options( + $optionValues['hasMigration'], + $optionValues['hasFactory'], + $optionValues['hasController'], + $optionValues['hasRequest'], + $optionValues['hasService'], + $optionValues['hasSeeder'], + $optionValues['force'] + ); + } + + /** + * Checks if the "all" option is set and returns its boolean value. + */ + private function shouldForceAll(): bool + { + return $this->hasOption('all') && boolval($this->option('all')); + } +} diff --git a/stubs/Controller.stub b/stubs/Controller.stub index 03dd95f..5e07282 100644 --- a/stubs/Controller.stub +++ b/stubs/Controller.stub @@ -25,8 +25,6 @@ class DummyClass extends Controller /** * Display a listing of the resource. - * - * @return JsonResponse */ #[Get(uri: 'ModelUri', name: 'ModelUri.list')] public function list(): JsonResponse @@ -36,10 +34,6 @@ class DummyClass extends Controller /** * Show the form for creating a new resource. - * - * @param DummyModelRequest $request - * - * @return JsonResponse */ #[Post(uri: 'ModelUri', name: 'ModelUri.create')] public function create(DummyModelRequest $request): JsonResponse @@ -50,10 +44,6 @@ class DummyClass extends Controller /** * Display the specified resource. - * - * @param string $id - * - * @return JsonResponse */ #[Get(uri: 'ModelUri/{id}', name: 'ModelUri.read')] public function read(string $id): JsonResponse @@ -70,11 +60,6 @@ class DummyClass extends Controller /** * Update the specified resource in storage. - * - * @param DummyModelRequest $request - * @param string $id - * - * @return JsonResponse */ #[Put(uri: 'ModelUri/{id}', name: 'ModelUri.update')] public function update(DummyModelRequest $request, string $id): JsonResponse @@ -91,9 +76,6 @@ class DummyClass extends Controller /** * Remove the specified resource from storage. - * @param string $id - * - * @return JsonResponse */ #[Delete(uri: 'ModelUri/{id}', name: 'ModelUri.destroy')] public function destroy(string $id): JsonResponse diff --git a/stubs/InterfaceService.stub b/stubs/InterfaceService.stub index 8c53621..ec30e78 100644 --- a/stubs/InterfaceService.stub +++ b/stubs/InterfaceService.stub @@ -11,20 +11,14 @@ interface DummyClass { /** * Create a new DummyModel resource. - * - * @param DummyModelRequest $request The request object containing the data for creating a spec. - * - * @return EntityResourceTransformer Returns the newly created DummyModelResource if successful, or null if the spec creation failed. */ - public function create(DummyModelRequest $request): EntityResourceTransformer; + public function create( + DummyModelRequest $request + ): EntityResourceTransformer; /** * Read a DummyModel resource by ID. * - * @param string $id The ID of the spec resource to fetch. - * - * @return EntityResourceTransformer The spec resource, or null if not found. - * * @throws ModelNotFoundException */ public function read(string $id): EntityResourceTransformer; @@ -32,11 +26,6 @@ interface DummyClass /** * Updates a DummyModel resource. * - * @param string $id The ID of the spec resource to update. - * @param DummyModelRequest $request The request data for updating the spec. - * - * @return bool - * * @throws ModelNotFoundException */ public function update(string $id, DummyModelRequest $request): bool; @@ -44,20 +33,12 @@ interface DummyClass /** * Deletes a DummyModel object based on the provided ID. * - * @param string $id The ID of the DummyModel object to delete. - * - * @return bool True if the deletion was successful, false otherwise. - * * @throws ModelNotFoundException */ public function delete(string $id): bool; /** * List all DummyModel resources. - * - * @return JsonApiPaginationTransformer - * - * @throws ModelNotFoundException */ public function list(): JsonApiPaginationTransformer; } diff --git a/stubs/Repository.stub b/stubs/Repository.stub index c615aa1..24f3d68 100644 --- a/stubs/Repository.stub +++ b/stubs/Repository.stub @@ -25,8 +25,6 @@ class DummyClass implements DummyInterface /** * Class Constructor. - * - * @param DummyModel $model The model object to be injected. */ public function __construct( protected DummyModel $model @@ -38,8 +36,6 @@ class DummyClass implements DummyInterface * * @param array $entity * The object to be created. - * - * @return DummyModel The created object. */ public function create(array $entity): DummyModel { @@ -52,10 +48,6 @@ class DummyClass implements DummyInterface /** * Retrieves a record from the model by the given ID. * - * @param string $id The ID of the record to retrieve. - * - * @return DummyModel The retrieved record. - * * @throws ModelNotFoundException */ public function read(string $id): DummyModel @@ -69,11 +61,7 @@ class DummyClass implements DummyInterface /** * Updates the given record in the database. * - * @param DummyModel $entity The record to be updated. - * * @param array $dataEntity - * - * @return bool True if the record was successfully updated, false otherwise. */ public function update(Model $entity, array $dataEntity): bool { @@ -82,10 +70,6 @@ class DummyClass implements DummyInterface /** * Deletes a record from the database based on the given ID. - * - * @param DummyModel $entity - * - * @return bool True if the record is successfully deleted, false otherwise. */ public function delete(Model $entity): bool { @@ -93,13 +77,8 @@ class DummyClass implements DummyInterface } /** - * Lists records from the database based on the given conditions. - * @param QueryFilters $options - * - * An array of conditions to filter the records (default: []). - * - * @return LengthAwarePaginator An array of records that match the conditions. - */ + * Lists records from the database based on the given conditions. + */ public function list(QueryFilters $options): LengthAwarePaginator { $this->fields = $this->model->getFields(); diff --git a/stubs/Service.stub b/stubs/Service.stub index fb963c1..e8b967e 100644 --- a/stubs/Service.stub +++ b/stubs/Service.stub @@ -19,8 +19,6 @@ class DummyClass implements DummyInterface { /** * Class Constructor. - * - * @param DummyRepository $repository The model object to be injected. */ public function __construct( protected DummyRepository $repository @@ -29,23 +27,17 @@ class DummyClass implements DummyInterface /** * Create a new DummyModel resource. - * - * @param DummyModelRequest $request The request object containing the data for creating a DummyModel. - * - * @return EntityResourceTransformer Returns the newly created UserResource if successful, - * or null if the User creation failed. */ - public function create(DummyModelRequest $request): EntityResourceTransformer - { - return new EntityResourceTransformer($this->repository->create($request->all())); + public function create( + DummyModelRequest $request + ): EntityResourceTransformer { + return new EntityResourceTransformer( + $this->repository->create($request->all()) + ); } /** * Read a DummyModel resource by ID. - * - * @param string $id The ID of the DummyModel resource to fetch. - * - * @return EntityResourceTransformer The DummyModel resource, or null if not found. */ public function read(string $id): EntityResourceTransformer { @@ -54,23 +46,17 @@ class DummyClass implements DummyInterface /** * Updates a DummyModel resource. - * - * @param string $id The ID of the DummyModel resource to update. - * @param DummyModelRequest $request The request data for updating the DummyModel. - * - * @return bool */ public function update(string $id, DummyModelRequest $request): bool { - return $this->repository->update($this->repository->read($id), $request->all()); + return $this->repository->update( + $this->repository->read($id), + $request->all() + ); } /** * Deletes a DummyModel object based on the provided ID. - * - * @param string $id The ID of the DummyModel object to delete. - * - * @return bool True if the deletion was successful, false otherwise. */ public function delete(string $id): bool { @@ -79,12 +65,12 @@ class DummyClass implements DummyInterface /** * List all DummyModel resources. - * - * @return JsonApiPaginationTransformer */ public function list(): JsonApiPaginationTransformer { $options = new QueryFilters(); - return new JsonApiPaginationTransformer($this->repository->list($options)); + return new JsonApiPaginationTransformer( + $this->repository->list($options) + ); } } From bbe4dff8df39dafc2a99a18f759972c8f81cfef0 Mon Sep 17 00:00:00 2001 From: Oscar Cabrera Date: Sun, 28 Jul 2024 11:59:17 -0600 Subject: [PATCH 2/2] restore stub and fix phpstan --- src/Contracts/BindingInterface.php | 12 +++++++ src/Handlers/MainCommand.php | 35 ++---------------- src/Handlers/Makers/MakeRepository.php | 3 +- src/Handlers/Makers/MakeService.php | 3 +- src/Trait/MainCommandTrait.php | 49 ++++++++++++++++++++++++++ stubs/Controller.stub | 18 ++++++++++ stubs/InterfaceService.stub | 23 ++++++++++-- stubs/Repository.stub | 25 +++++++++++-- stubs/Service.stub | 22 ++++++++++++ 9 files changed, 151 insertions(+), 39 deletions(-) create mode 100644 src/Contracts/BindingInterface.php create mode 100644 src/Trait/MainCommandTrait.php diff --git a/src/Contracts/BindingInterface.php b/src/Contracts/BindingInterface.php new file mode 100644 index 0000000..ee80b17 --- /dev/null +++ b/src/Contracts/BindingInterface.php @@ -0,0 +1,12 @@ + - */ - private array $hasBinding = [ - MakeRepository::class, - MakeService::class, - ]; - /** * Constructor for the class. */ @@ -179,26 +172,4 @@ private function makeRequest(): void $this->executeMaker($this->makeRequest); } } - - /** - * Executes the Maker. - * - * This method executes a Maker by calling its `make` method with the given options. - * If the `bind` parameter is set to `true`, it also calls the Maker's `binding` method. - */ - private function executeMaker( - MakeRepository|MakeInterfaceRepository|MakeService|MakeInterfaceServices|MakeController|MakeRequest $maker, - ): void { - try { - $result = $maker->make($this->name, $this->options); - if (in_array(get_class($maker), $this->hasBinding, true)) { - $maker->binding($this->name); - } - $this->infoCommand($result); - } catch (StubException|CreateStructureException $exception) { - $info = $exception->getInput(); - /** @var array{type: string, path: string} $info */ - $this->errorCommand($exception->getMessage(), $info); - } - } } diff --git a/src/Handlers/Makers/MakeRepository.php b/src/Handlers/Makers/MakeRepository.php index 5712fde..d638590 100644 --- a/src/Handlers/Makers/MakeRepository.php +++ b/src/Handlers/Makers/MakeRepository.php @@ -5,6 +5,7 @@ namespace Oscabrera\ModelRepository\Handlers\Makers; use Oscabrera\ModelRepository\Classes\Options; +use Oscabrera\ModelRepository\Contracts\BindingInterface; use Oscabrera\ModelRepository\Exception\Command\CreateStructureException; use Oscabrera\ModelRepository\Exception\Command\StubException; @@ -15,7 +16,7 @@ * associated migration file * using the Laravel Artisan command 'make:model'. */ -class MakeRepository extends MakeStructure +class MakeRepository extends MakeStructure implements BindingInterface { private string $type = 'Repository'; private string $repositoryNameSpace = 'App\Repositories'; diff --git a/src/Handlers/Makers/MakeService.php b/src/Handlers/Makers/MakeService.php index b037f6a..a2b1664 100644 --- a/src/Handlers/Makers/MakeService.php +++ b/src/Handlers/Makers/MakeService.php @@ -5,6 +5,7 @@ namespace Oscabrera\ModelRepository\Handlers\Makers; use Oscabrera\ModelRepository\Classes\Options; +use Oscabrera\ModelRepository\Contracts\BindingInterface; use Oscabrera\ModelRepository\Exception\Command\CreateStructureException; use Oscabrera\ModelRepository\Exception\Command\StubException; @@ -15,7 +16,7 @@ * associated migration file * using the Laravel Artisan command 'make:model'. */ -class MakeService extends MakeStructure +class MakeService extends MakeStructure implements BindingInterface { private string $type = 'Service'; private string $serviceNameSpace = 'App\Services'; diff --git a/src/Trait/MainCommandTrait.php b/src/Trait/MainCommandTrait.php new file mode 100644 index 0000000..d7228ca --- /dev/null +++ b/src/Trait/MainCommandTrait.php @@ -0,0 +1,49 @@ + + */ + private array $hasBinding = [ + MakeRepository::class, + MakeService::class, + ]; + + /** + * Executes the Maker. + * + * This method executes a Maker by calling its `make` method with the given options. + * If the `bind` parameter is set to `true`, it also calls the Maker's `binding` method. + */ + private function executeMaker( + MakeRepository|MakeInterfaceRepository|MakeService|MakeInterfaceServices|MakeController|MakeRequest $maker, + ): void { + try { + $result = $maker->make($this->name, $this->options); + if ( + in_array($maker::class, $this->hasBinding, true) && + $maker instanceof BindingInterface + ) { + $maker->binding($this->name); + } + $this->infoCommand($result); + } catch (StubException|CreateStructureException $exception) { + $info = $exception->getInput(); + /** @var array{type: string, path: string} $info */ + $this->errorCommand($exception->getMessage(), $info); + } + } +} diff --git a/stubs/Controller.stub b/stubs/Controller.stub index 5e07282..03dd95f 100644 --- a/stubs/Controller.stub +++ b/stubs/Controller.stub @@ -25,6 +25,8 @@ class DummyClass extends Controller /** * Display a listing of the resource. + * + * @return JsonResponse */ #[Get(uri: 'ModelUri', name: 'ModelUri.list')] public function list(): JsonResponse @@ -34,6 +36,10 @@ class DummyClass extends Controller /** * Show the form for creating a new resource. + * + * @param DummyModelRequest $request + * + * @return JsonResponse */ #[Post(uri: 'ModelUri', name: 'ModelUri.create')] public function create(DummyModelRequest $request): JsonResponse @@ -44,6 +50,10 @@ class DummyClass extends Controller /** * Display the specified resource. + * + * @param string $id + * + * @return JsonResponse */ #[Get(uri: 'ModelUri/{id}', name: 'ModelUri.read')] public function read(string $id): JsonResponse @@ -60,6 +70,11 @@ class DummyClass extends Controller /** * Update the specified resource in storage. + * + * @param DummyModelRequest $request + * @param string $id + * + * @return JsonResponse */ #[Put(uri: 'ModelUri/{id}', name: 'ModelUri.update')] public function update(DummyModelRequest $request, string $id): JsonResponse @@ -76,6 +91,9 @@ class DummyClass extends Controller /** * Remove the specified resource from storage. + * @param string $id + * + * @return JsonResponse */ #[Delete(uri: 'ModelUri/{id}', name: 'ModelUri.destroy')] public function destroy(string $id): JsonResponse diff --git a/stubs/InterfaceService.stub b/stubs/InterfaceService.stub index ec30e78..b86eccf 100644 --- a/stubs/InterfaceService.stub +++ b/stubs/InterfaceService.stub @@ -11,14 +11,20 @@ interface DummyClass { /** * Create a new DummyModel resource. + * + * @param DummyModelRequest $request The request object containing the data for creating a spec. + * + * @return EntityResourceTransformer Returns the newly created DummyModelResource if successful, or null if the spec creation failed. */ - public function create( - DummyModelRequest $request - ): EntityResourceTransformer; + public function create(DummyModelRequest $request): EntityResourceTransformer; /** * Read a DummyModel resource by ID. * + * @param string $id The ID of the spec resource to fetch. + * + * @return EntityResourceTransformer The spec resource, or null if not found. + * * @throws ModelNotFoundException */ public function read(string $id): EntityResourceTransformer; @@ -26,6 +32,11 @@ interface DummyClass /** * Updates a DummyModel resource. * + * @param string $id The ID of the spec resource to update. + * @param DummyModelRequest $request The request data for updating the spec. + * + * @return bool + * * @throws ModelNotFoundException */ public function update(string $id, DummyModelRequest $request): bool; @@ -33,12 +44,18 @@ interface DummyClass /** * Deletes a DummyModel object based on the provided ID. * + * @param string $id The ID of the DummyModel object to delete. + * + * @return bool True if the deletion was successful, false otherwise. + * * @throws ModelNotFoundException */ public function delete(string $id): bool; /** * List all DummyModel resources. + * + * @return JsonApiPaginationTransformer */ public function list(): JsonApiPaginationTransformer; } diff --git a/stubs/Repository.stub b/stubs/Repository.stub index 24f3d68..016e231 100644 --- a/stubs/Repository.stub +++ b/stubs/Repository.stub @@ -25,6 +25,8 @@ class DummyClass implements DummyInterface /** * Class Constructor. + * + * @param DummyModel $model The model object to be injected. */ public function __construct( protected DummyModel $model @@ -36,6 +38,8 @@ class DummyClass implements DummyInterface * * @param array $entity * The object to be created. + * + * @return DummyModel The created object. */ public function create(array $entity): DummyModel { @@ -48,6 +52,10 @@ class DummyClass implements DummyInterface /** * Retrieves a record from the model by the given ID. * + * @param string $id The ID of the record to retrieve. + * + * @return DummyModel The retrieved record. + * * @throws ModelNotFoundException */ public function read(string $id): DummyModel @@ -61,7 +69,11 @@ class DummyClass implements DummyInterface /** * Updates the given record in the database. * + * @param DummyModel $entity The record to be updated. + * * @param array $dataEntity + * + * @return bool True if the record was successfully updated, false otherwise. */ public function update(Model $entity, array $dataEntity): bool { @@ -70,6 +82,10 @@ class DummyClass implements DummyInterface /** * Deletes a record from the database based on the given ID. + * + * @param DummyModel $entity + * + * @return bool True if the record is successfully deleted, false otherwise. */ public function delete(Model $entity): bool { @@ -77,8 +93,13 @@ class DummyClass implements DummyInterface } /** - * Lists records from the database based on the given conditions. - */ + * Lists records from the database based on the given conditions. + * @param QueryFilters $options + * + * An array of conditions to filter the records (default: []). + * + * @return LengthAwarePaginator An array of records that match the conditions. + */ public function list(QueryFilters $options): LengthAwarePaginator { $this->fields = $this->model->getFields(); diff --git a/stubs/Service.stub b/stubs/Service.stub index e8b967e..6d193bd 100644 --- a/stubs/Service.stub +++ b/stubs/Service.stub @@ -19,6 +19,8 @@ class DummyClass implements DummyInterface { /** * Class Constructor. + * + * @param DummyRepository $repository The model object to be injected. */ public function __construct( protected DummyRepository $repository @@ -27,6 +29,11 @@ class DummyClass implements DummyInterface /** * Create a new DummyModel resource. + * + * @param DummyModelRequest $request The request object containing the data for creating a DummyModel. + * + * @return EntityResourceTransformer Returns the newly created UserResource if successful, + * or null if the User creation failed. */ public function create( DummyModelRequest $request @@ -38,6 +45,10 @@ class DummyClass implements DummyInterface /** * Read a DummyModel resource by ID. + * + * @param string $id The ID of the DummyModel resource to fetch. + * + * @return EntityResourceTransformer The DummyModel resource, or null if not found. */ public function read(string $id): EntityResourceTransformer { @@ -46,6 +57,11 @@ class DummyClass implements DummyInterface /** * Updates a DummyModel resource. + * + * @param string $id The ID of the DummyModel resource to update. + * @param DummyModelRequest $request The request data for updating the DummyModel. + * + * @return bool */ public function update(string $id, DummyModelRequest $request): bool { @@ -57,6 +73,10 @@ class DummyClass implements DummyInterface /** * Deletes a DummyModel object based on the provided ID. + * + * @param string $id The ID of the DummyModel object to delete. + * + * @return bool True if the deletion was successful, false otherwise. */ public function delete(string $id): bool { @@ -65,6 +85,8 @@ class DummyClass implements DummyInterface /** * List all DummyModel resources. + * + * @return JsonApiPaginationTransformer */ public function list(): JsonApiPaginationTransformer {