diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index dc17d9f..934c7ff 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,34 +10,15 @@ on: pull_request: branches: [ main ] -# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains a single job called "build" build: runs-on: ubuntu-latest strategy: fail-fast: true matrix: - php: [7.0.21, 7.1, 7.2, 7.3, 7.4, 8.0] + php: [8.0, 8.1] stability: [prefer-lowest, prefer-stable] - laravel: [5.5, 6.x, 7.x, 8.x] - exclude: - - laravel: 5.5 - php: 8.0 - - laravel: 6.x - php: 7.0.21 - - laravel: 6.x - php: 7.1 - - laravel: 7.x - php: 7.0.21 - - laravel: 7.x - php: 7.1 - - laravel: 8.x - php: 7.0.21 - - laravel: 8.x - php: 7.1 - - laravel: 8.x - php: 7.2 + laravel: [9.x] name: L${{ matrix.laravel }} - PHP ${{ matrix.php }} - ${{ matrix.stability }} @@ -48,7 +29,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd tools: composer:v2 coverage: none @@ -71,3 +51,30 @@ jobs: cp $GITHUB_WORKSPACE/bin/test-commands.sh laravel-${{ matrix.laravel }} cd laravel-${{ matrix.laravel }} ./test-commands.sh + + code_quality: + runs-on: ubuntu-latest + + name: Code Quality + + steps: + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + tools: composer:v2 + coverage: none + + - name: Install Dependencies + run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + + - name: Run Pint + run: ./vendor/bin/pint --test -v --ansi + + - name: Run PHPStan + run: ./vendor/bin/phpstan analyse --memory-limit=2G + + - name: Run Pest + run: ./vendor/bin/pest diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 096f2d5..36bbbc8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ Lucid Architecture's GitHub issue trackers are not intended to provide help or s ## Core Development Discussion -You may propose new features or improvements of existing Lucid Architecture behaviour in the [Lucid Discussins](https://github.com/lucidarch/lucid/discussions). +You may propose new features or improvements of existing Lucid Architecture behaviour in the [Lucid Discussions](https://github.com/lucidarch/lucid/discussions). If you propose a new feature, please be willing to implement at least some of the code that would be needed to complete the feature, or collaborate on active ideation in the meantime. Informal discussion regarding bugs, new features, and implementation of existing features takes place in the `#internals` channel of the [Lucid Slack workspace](https://lucid-slack.herokuapp.com/). diff --git a/bin/test-commands.sh b/bin/test-commands.sh index 3c3fbae..5fbc856 100755 --- a/bin/test-commands.sh +++ b/bin/test-commands.sh @@ -27,7 +27,6 @@ fi examine "app/Providers" examine "app/Providers/RouteServiceProvider.php" examine "resources" -examine "resources/lang" examine "resources/views" examine "resources/views/welcome.blade.php" lint "resources/views/welcome.blade.php" @@ -147,6 +146,7 @@ lint "tests/Unit/Services/Harbour/Operations/TwistOperationTest.php" ## --- TEARDOWN --- ./vendor/bin/lucid delete:feature trade +./vendor/bin/lucid delete:feature finance/wallet/pay ./vendor/bin/lucid delete:job submitTradeRequest shipping ./vendor/bin/lucid delete:job sail boat ./vendor/bin/lucid delete:model bridge @@ -156,6 +156,7 @@ lint "tests/Unit/Services/Harbour/Operations/TwistOperationTest.php" rm app/Http/Controllers/TradeController.php ./vendor/bin/lucid delete:feature trade harbour +./vendor/bin/lucid delete:feature port/yacht/park harbour ./vendor/bin/lucid delete:operation spin harbour ./vendor/bin/lucid delete:operation twist harbour rm app/Services/Harbour/Http/Controllers/TradeController.php diff --git a/composer.json b/composer.json index 3a61c22..62fa2c5 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ } ], "require": { + "php": ">=8.0", "ext-dom": "*", "mockery/mockery": "*", "symfony/console": "*", @@ -25,13 +26,22 @@ "symfony/finder": "*", "symfony/process": "*" }, + "require-dev": { + "laravel/pint": "^1.4", + "nunomaduro/larastan": "^2.0", + "orchestra/testbench": "^8.0", + "pestphp/pest": "^1.22" + }, "autoload": { "psr-4": { "Lucid\\": "src/" } }, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "pestphp/pest-plugin": true + } }, "minimum-stability": "dev", "prefer-stable": true diff --git a/lucid b/lucid index 25a6456..bf009f0 100755 --- a/lucid +++ b/lucid @@ -1,6 +1,8 @@ #!/usr/bin/env php run(); diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..2c1e976 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,24 @@ +includes: + - ./vendor/nunomaduro/larastan/extension.neon + +parameters: + + paths: + - src + + # Level 0 is the lowest, 8 is the highest + level: 5 + + checkMissingIterableValueType: false + reportUnmatchedIgnoredErrors: true + treatPhpDocTypesAsCertain: false + polluteScopeWithLoopInitialAssignments: false + polluteScopeWithAlwaysIterableForeach: false + checkTooWideReturnTypesInProtectedAndPublicMethods: true + checkUninitializedProperties: true + + parallel: + processTimeout: 300.00 + + ignoreErrors: + - '/Call to an undefined method Mockery\\ExpectationInterface|Mockery\\HigherOrderMessage\:\:once\(\)/' diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..ec8702d --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,17 @@ + + + + + ./tests + + + + + ./src + + + diff --git a/src/Bus/Marshal.php b/src/Bus/Marshal.php index 6c6ebdd..edac9e1 100644 --- a/src/Bus/Marshal.php +++ b/src/Bus/Marshal.php @@ -2,25 +2,23 @@ namespace Lucid\Bus; -use Exception; use ArrayAccess; +use Exception; +use Illuminate\Http\Request; use ReflectionParameter; trait Marshal { /** * Marshal a command from the given array accessible object. - * - * @param string $command - * @param \ArrayAccess $source - * @param array $extras - * - * @return mixed */ - protected function marshal($command, ArrayAccess $source, array $extras = []) - { + protected function marshal( + string $command, + iterable|Request $source, + array $extras = [] + ): mixed { $parameters = []; - + foreach ($source as $name => $parameter) { $parameters[$name] = $parameter; } @@ -33,17 +31,14 @@ protected function marshal($command, ArrayAccess $source, array $extras = []) /** * Get a parameter value for a marshaled command. * - * @param string $command - * @param \ArrayAccess $source - * @param \ReflectionParameter $parameter - * @param array $extras - * - * @return mixed * @throws Exception */ - protected function getParameterValueForCommand($command, ArrayAccess $source, - ReflectionParameter $parameter, array $extras = []) - { + protected function getParameterValueForCommand( + string $command, + ArrayAccess $source, + ReflectionParameter $parameter, + array $extras = [] + ): mixed { if (array_key_exists($parameter->name, $extras)) { return $extras[$parameter->name]; } diff --git a/src/Bus/ServesFeatures.php b/src/Bus/ServesFeatures.php index 9c0c1e4..9bde520 100644 --- a/src/Bus/ServesFeatures.php +++ b/src/Bus/ServesFeatures.php @@ -2,8 +2,8 @@ namespace Lucid\Bus; -use Illuminate\Support\Collection; use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Support\Collection; use Lucid\Events\FeatureStarted; trait ServesFeatures @@ -13,16 +13,11 @@ trait ServesFeatures /** * Serve the given feature with the given arguments. - * - * @param string $feature - * @param array $arguments - * - * @return mixed */ - public function serve($feature, $arguments = []) + public function serve(string $feature, array $arguments = []): mixed { event(new FeatureStarted($feature, $arguments)); - return $this->dispatch($this->marshal($feature, new Collection(), $arguments)); + return $this->dispatchSync($this->marshal($feature, new Collection(), $arguments)); } } diff --git a/src/Bus/UnitDispatcher.php b/src/Bus/UnitDispatcher.php index a7b422e..6e137e3 100644 --- a/src/Bus/UnitDispatcher.php +++ b/src/Bus/UnitDispatcher.php @@ -3,17 +3,17 @@ namespace Lucid\Bus; use App; +use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Http\Request; +use Illuminate\Support\Collection; +use Lucid\Events\JobStarted; +use Lucid\Events\OperationStarted; use Lucid\Testing\UnitMock; use Lucid\Testing\UnitMockRegistry; -use ReflectionClass; use Lucid\Units\Job; -use ReflectionException; use Lucid\Units\Operation; -use Illuminate\Http\Request; -use Lucid\Events\JobStarted; -use Illuminate\Support\Collection; -use Lucid\Events\OperationStarted; -use Illuminate\Foundation\Bus\DispatchesJobs; +use ReflectionClass; +use ReflectionException; trait UnitDispatcher { @@ -25,24 +25,21 @@ trait UnitDispatcher * laravel function dispatchFromArray. * When the $arguments is an instance of Request * it will call dispatchFrom instead. - * - * @param mixed $unit - * @param array|\Illuminate\Http\Request $arguments - * @param array $extra - * - * @return mixed */ - public function run($unit, $arguments = [], $extra = []) - { - if (is_object($unit) && !App::runningUnitTests()) { - $result = $this->dispatch($unit); + public function run( + mixed $unit, + array|Request $arguments = [], + array $extra = [] + ): mixed { + if (is_object($unit) && ! App::runningUnitTests()) { + $result = $this->dispatchSync($unit); } elseif ($arguments instanceof Request) { - $result = $this->dispatch($this->marshal($unit, $arguments, $extra)); + $result = $this->dispatchSync($this->marshal($unit, $arguments, $extra)); } else { - if (!is_object($unit)) { + if (! is_object($unit)) { $unit = $this->marshal($unit, new Collection(), $arguments); - // don't dispatch unit when in tests and have a mock for it. + // don't dispatch unit when in tests and have a mock for it. } elseif (App::runningUnitTests() && app(UnitMockRegistry::class)->has(get_class($unit))) { /** @var UnitMock $mock */ $mock = app(UnitMockRegistry::class)->get(get_class($unit)); @@ -58,7 +55,7 @@ public function run($unit, $arguments = [], $extra = []) ); } - $result = $this->dispatch($unit); + $result = $this->dispatchSync($unit); } if ($unit instanceof Operation) { @@ -75,15 +72,13 @@ public function run($unit, $arguments = [], $extra = []) /** * Run the given unit in the given queue. * - * @param string $unit - * @param array $arguments - * @param string|null $queue - * - * @return mixed * @throws ReflectionException */ - public function runInQueue($unit, array $arguments = [], $queue = 'default') - { + public function runInQueue( + string $unit, + array $arguments = [], + ?string $queue = 'default' + ): mixed { // instantiate and queue the unit $reflection = new ReflectionClass($unit); $instance = $reflection->newInstanceArgs($arguments); diff --git a/src/Console/Command.php b/src/Console/Command.php deleted file mode 100644 index 704f072..0000000 --- a/src/Console/Command.php +++ /dev/null @@ -1,180 +0,0 @@ -setName($this->name) - ->setDescription($this->description); - - foreach ($this->getArguments() as $arguments) { - call_user_func_array([$this, 'addArgument'], $arguments); - } - - foreach ($this->getOptions() as $options) { - call_user_func_array([$this, 'addOption'], $options); - } - } - - /** - * Default implementation to get the arguments of this command. - * - * @return array - */ - public function getArguments() - { - return []; - } - - /** - * Default implementation to get the options of this command. - * - * @return array - */ - public function getOptions() - { - return []; - } - - /** - * Execute the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - */ - public function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - - return (int) $this->handle(); - } - - /** - * Get an argument from the input. - * - * @param string $key - * - * @return string - */ - public function argument($key) - { - return $this->input->getArgument($key); - } - - /** - * Get an option from the input. - * - * @param string $key - * - * @return string - */ - public function option($key) - { - return $this->input->getOption($key); - } - - /** - * Write a string as information output. - * - * @param string $string - */ - public function info($string) - { - $this->output->writeln("$string"); - } - - /** - * Write a string as comment output. - * - * @param string $string - * @return void - */ - public function comment($string) - { - $this->output->writeln("$string"); - } - - /** - * Write a string as error output. - * - * @param string $string - * @return void - */ - public function error($string) - { - $this->output->writeln("$string"); - } - - /** - * Format input to textual table. - * - * @param array $headers - * @param \Illuminate\Contracts\Support\Arrayable|array $rows - * @param string $style - * @return void - */ - public function table(array $headers, $rows, $style = 'default') - { - $table = new Table($this->output); - - if ($rows instanceof Arrayable) { - $rows = $rows->toArray(); - } - - $table->setHeaders($headers)->setRows($rows)->setStyle($style)->render(); - } - - /** - * Ask the user the given question. - * - * @param string $question - * - * @return string - */ - public function ask($question, $default = false) - { - $question = ''.$question.' '; - - $confirmation = new ConfirmationQuestion($question, false); - - return $this->getHelperSet()->get('question')->ask($this->input, $this->output, $confirmation); - } - - /** - * Ask the user the given secret question. - * - * @param string $question - * - * @return string - */ - public function secret($question) - { - $question = ''.$question.' '; - - return $this->getHelperSet()->get('dialog')->askHiddenResponse($this->output, $question, false); - } -} diff --git a/src/Console/Commands/ChangeSourceNamespaceCommand.php b/src/Console/Commands/ChangeSourceNamespaceCommand.php index 7fa15a8..79a2c76 100644 --- a/src/Console/Commands/ChangeSourceNamespaceCommand.php +++ b/src/Console/Commands/ChangeSourceNamespaceCommand.php @@ -2,46 +2,32 @@ namespace Lucid\Console\Commands; -use Lucid\Finder; -use Lucid\Console\Command; -use Illuminate\Support\Composer; +use Exception; +use Illuminate\Console\Command; use Illuminate\Filesystem\Filesystem; -use Symfony\Component\Console\Input\InputArgument; +use Illuminate\Support\Composer; +use Lucid\Finder; use Symfony\Component\Finder\Finder as SymfonyFinder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -class ChangeSourceNamespaceCommand extends SymfonyCommand +class ChangeSourceNamespaceCommand extends Command { use Finder; - use Command; - /** - * The console command name. - * - * @var string - */ - protected $name = 'src:name'; + protected $signature = 'src:name + {name : The source directory namespace.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Set the source directory namespace.'; /** * The Composer class instance. - * - * @var \Illuminate\Support\Composer */ - protected $composer; + protected Composer $composer; /** * The filesystem instance. - * - * @var \Illuminate\Filesystem\Filesystem */ - protected $files; + protected Filesystem $files; /** * Create a new key generator command. @@ -69,15 +55,17 @@ public function handle() $this->info('Lucid source directory namespace set!'); $this->composer->dumpAutoloads(); - } catch (\Exception $e) { + } catch (Exception $e) { $this->error($e->getMessage()); } } /** * Set the namespace on the files in the app directory. + * + * @throws Exception */ - protected function setAppDirectoryNamespace() + protected function setAppDirectoryNamespace(): void { $files = SymfonyFinder::create() ->in(base_path()) @@ -93,9 +81,9 @@ protected function setAppDirectoryNamespace() /** * Replace the App namespace at the given path. * - * @param string $path + * @throws Exception */ - protected function replaceNamespace($path) + protected function replaceNamespace(string $path): void { $search = [ 'namespace '.$this->findRootNamespace().';', @@ -112,8 +100,10 @@ protected function replaceNamespace($path) /** * Set the PSR-4 namespace in the Composer file. + * + * @throws Exception */ - protected function setComposerNamespace() + protected function setComposerNamespace(): void { $this->replaceIn( $this->getComposerPath(), str_replace('\\', '\\\\', $this->findRootNamespace()).'\\\\', str_replace('\\', '\\\\', $this->argument('name')).'\\\\' @@ -122,8 +112,10 @@ protected function setComposerNamespace() /** * Set the namespace in the appropriate configuration files. + * + * @throws Exception */ - protected function setAppConfigNamespaces() + protected function setAppConfigNamespaces(): void { $search = [ $this->findRootNamespace().'\\Providers', @@ -142,27 +134,14 @@ protected function setAppConfigNamespaces() /** * Replace the given string in the given file. - * - * @param string $path - * @param string|array $search - * @param string|array $replace */ - protected function replaceIn($path, $search, $replace) - { + protected function replaceIn( + string $path, + string|array $search, + string|array $replace + ): void { if ($this->files->exists($path)) { $this->files->put($path, str_replace($search, $replace, $this->files->get($path))); } } - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['name', InputArgument::REQUIRED, 'The source directory namespace.'], - ]; - } } diff --git a/src/Console/Commands/ControllerMakeCommand.php b/src/Console/Commands/ControllerMakeCommand.php index 690639d..40235e1 100644 --- a/src/Console/Commands/ControllerMakeCommand.php +++ b/src/Console/Commands/ControllerMakeCommand.php @@ -2,117 +2,36 @@ namespace Lucid\Console\Commands; -use Lucid\Finder; -use Lucid\Console\Command; -use Lucid\Filesystem; -use Lucid\Str; -use Symfony\Component\Console\Input\InputOption; +use Illuminate\Console\Command; use Lucid\Generators\ControllerGenerator; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -class ControllerMakeCommand extends SymfonyCommand +class ControllerMakeCommand extends Command { - use Finder; - use Command; - use Filesystem; + protected $signature = 'make:controller + {controller : The controller\'s name.} + {service? : The service in which the controller should be generated.} + {--resource : Generate a resource controller class.} + '; - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:controller'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a new resource Controller class in a service'; - /** - * The type of class being generated. - * - * @var string - */ - protected $type = 'Controller'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - $generator = new ControllerGenerator(); - - $service = $this->argument('service'); - $name = $this->argument('controller'); - try { - $controller = $generator->generate($name, $service, $this->option('resource')); - - $this->info('Controller class created successfully.'. - "\n". - "\n". - 'Find it at '.$controller.''."\n" + $controller = (new ControllerGenerator()) + ->generate( + $this->argument('controller'), + $this->argument('service'), + $this->option('resource') + ); + + $this->info( + 'Controller class created successfully.' + ."\n\n" + ."Find it at $controller\n" ); - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['controller', InputArgument::REQUIRED, 'The controller\'s name.'], - ['service', InputArgument::OPTIONAL, 'The service in which the controller should be generated.'], - ]; - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions() - { - return [ - ['resource', null, InputOption::VALUE_NONE, 'Generate a resource controller class.'], - ]; - } - - /** - * Parse the feature name. - * remove the Controller.php suffix if found - * we're adding it ourselves. - * - * @param string $name - * - * @return string - */ - protected function parseName($name) - { - return Str::studly(preg_replace('/Controller(\.php)?$/', '', $name).'Controller'); - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - if ($this->option('plain')) { - return __DIR__ . '/../Generators/stubs/controller.plain.stub'; - } - - return __DIR__ . '/../Generators/stubs/controller.resource.stub'; - } } diff --git a/src/Console/Commands/FeatureDeleteCommand.php b/src/Console/Commands/FeatureDeleteCommand.php index 1df854e..666f325 100644 --- a/src/Console/Commands/FeatureDeleteCommand.php +++ b/src/Console/Commands/FeatureDeleteCommand.php @@ -2,97 +2,48 @@ namespace Lucid\Console\Commands; -use Lucid\Str; -use Lucid\Finder; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Lucid\Finder; +use Lucid\Str; -class FeatureDeleteCommand extends SymfonyCommand +class FeatureDeleteCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The console command name. - * - * @var string - */ - protected $name = 'delete:feature'; + protected $signature = 'delete:feature + {feature : The feature\'s name.} + {service? : The service in which the feature should be deleted.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Delete an existing Feature in a service'; - /** - * The type of class being deleted. - * - * @var string - */ - protected $type = 'Feature'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - try { - $service = Str::service($this->argument('service')); - $title = $this->parseName($this->argument('feature')); + $service = Str::service($this->argument('service')); + $title = Str::feature($this->argument('feature')); - if (!$this->exists($feature = $this->findFeaturePath($service, $title))) { - $this->error('Feature class '.$title.' cannot be found.'); + try { + // Delete feature + if (! $this->exists($feature = $this->findFeaturePath($service, $title))) { + $this->error("Feature class $title cannot be found."); } else { $this->delete($feature); - $this->info('Feature class '.$title.' deleted successfully.'); + $this->info("Feature class $title deleted successfully."); } - } catch (Exception $e) { - $this->error($e->getMessage()); - } - } - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['feature', InputArgument::REQUIRED, 'The feature\'s name.'], - ['service', InputArgument::OPTIONAL, 'The service from which the feature should be deleted.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - return __DIR__ . '/../Generators/stubs/feature.stub'; - } + // Delete feature tests + $testTitle = $title.'Test'; + if (! $this->exists($test = $this->findFeatureTestPath($service, $testTitle))) { + $this->error("Feature test class $testTitle cannot be found."); + } else { + $this->delete($test); - /** - * Parse the feature name. - * remove the Feature.php suffix if found - * we're adding it ourselves. - * - * @param string $name - * - * @return string - */ - protected function parseName($name) - { - return Str::feature($name); + $this->info("Feature test class $testTitle deleted successfully."); + } + } catch (\Exception $e) { + $this->error($e->getMessage()); + } } } diff --git a/src/Console/Commands/FeatureDescribeCommand.php b/src/Console/Commands/FeatureDescribeCommand.php deleted file mode 100644 index 93c511c..0000000 --- a/src/Console/Commands/FeatureDescribeCommand.php +++ /dev/null @@ -1,68 +0,0 @@ -findFeature($this->argument('feature'))) { - $parser = new Parser(); - $jobs = $parser->parseFeatureJobs($feature); - - $features = []; - foreach ($jobs as $index => $job) { - $features[$feature->title][] = [$index+1, $job->title, $job->domain->name, $job->relativePath]; - } - - foreach ($features as $feature => $jobs) { - $this->comment("\n$feature\n"); - $this->table(['', 'Job', 'Domain', 'Path'], $jobs); - } - - return true; - } - - throw new InvalidArgumentException('Feature with name "'.$this->argument('feature').'" not found.'); - } - - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['feature', InputArgument::REQUIRED, 'The feature name to list the jobs of.'], - ]; - } - } diff --git a/src/Console/Commands/FeatureMakeCommand.php b/src/Console/Commands/FeatureMakeCommand.php index c4c6d4d..5ab98d2 100644 --- a/src/Console/Commands/FeatureMakeCommand.php +++ b/src/Console/Commands/FeatureMakeCommand.php @@ -2,101 +2,39 @@ namespace Lucid\Console\Commands; -use Lucid\Str; -use Lucid\Finder; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; +use Lucid\Finder; use Lucid\Generators\FeatureGenerator; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Lucid\Str; -class FeatureMakeCommand extends SymfonyCommand +class FeatureMakeCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:feature'; + protected $signature = 'make:feature + {feature : The feature\'s name.} + {service? : The service in which the feature should be implemented.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a new Feature in a service'; - /** - * The type of class being generated. - * - * @var string - */ - protected $type = 'Feature'; - - /** - * Execute the console command. - * - * @return bool|null - * @throws \Exception - */ - public function handle() + public function handle(): void { try { - $service = Str::studly($this->argument('service')); - $title = $this->parseName($this->argument('feature')); - - $generator = new FeatureGenerator(); - $feature = $generator->generate($title, $service); + $feature = (new FeatureGenerator()) + ->generate( + Str::studly($this->argument('feature')), + Str::studly($this->argument('service')) + ); $this->info( - 'Feature class '.$feature->title.' created successfully.'. - "\n". - "\n". - 'Find it at '.$feature->relativePath.''."\n" + "Feature class $feature->title created successfully." + ."\n\n" + ."Find it at $feature->relativePath\n" ); - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['feature', InputArgument::REQUIRED, 'The feature\'s name.'], - ['service', InputArgument::OPTIONAL, 'The service in which the feature should be implemented.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - return __DIR__ . '/../Generators/stubs/feature.stub'; - } - - /** - * Parse the feature name. - * remove the Feature.php suffix if found - * we're adding it ourselves. - * - * @param string $name - * - * @return string - */ - protected function parseName($name) - { - return Str::feature($name); - } } diff --git a/src/Console/Commands/FeaturesListCommand.php b/src/Console/Commands/FeaturesListCommand.php index 0315c61..6c4c0f1 100644 --- a/src/Console/Commands/FeaturesListCommand.php +++ b/src/Console/Commands/FeaturesListCommand.php @@ -2,55 +2,39 @@ namespace Lucid\Console\Commands; +use Illuminate\Console\Command; +use Lucid\Entities\Feature; use Lucid\Finder; -use Lucid\Console\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -class FeaturesListCommand extends SymfonyCommand +class FeaturesListCommand extends Command { use Finder; - use Command; - - /** - * The console command name. - * - * @var string - */ - protected $name = 'list:features'; - - /** - * The console command description. - * - * @var string - */ + + protected $signature = 'list:features + {service? : The service to list the features of.} + '; + protected $description = 'List the features.'; - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - foreach ($this->listFeatures($this->argument('service')) as $service => $features) { - $this->comment("\n$service\n"); - $features = array_map(function($feature) { - return [$feature->title, $feature->service->name, $feature->file, $feature->relativePath]; - }, $features->all()); - $this->table(['Feature', 'Service', 'File', 'Path'], $features); + try { + $featuresList = $this->listFeatures($this->argument('service')); + } catch (\Exception $e) { + $this->error($e->getMessage()); + + return; } - } - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['service', InputArgument::OPTIONAL, 'The service to list the features of.'], - ]; + foreach ($featuresList as $service => $features) { + $this->comment("\n$service\n"); + + $this->table( + ['Feature', 'Service', 'File', 'Path'], + array_map(function (Feature $feature) { + return [$feature->title, $feature->service->name, $feature->file, $feature->relativePath]; + }, $features->all()) + ); + } } } diff --git a/src/Console/Commands/GeneratorCommand.php b/src/Console/Commands/GeneratorCommand.php deleted file mode 100644 index 1cbfee4..0000000 --- a/src/Console/Commands/GeneratorCommand.php +++ /dev/null @@ -1,13 +0,0 @@ -generator = $generator; - } -} diff --git a/src/Console/Commands/InitCommandTrait.php b/src/Console/Commands/InitCommandTrait.php index 9ebca33..6ebcaea 100644 --- a/src/Console/Commands/InitCommandTrait.php +++ b/src/Console/Commands/InitCommandTrait.php @@ -6,7 +6,7 @@ trait InitCommandTrait { - private function welcome($service = null) + private function welcome($service = null): void { $service = Str::service($service); @@ -21,7 +21,7 @@ private function welcome($service = null) if ($service) { $this->info("will generate app/Services/$service/Features/LoginUserFeature.php"); } else { - $this->info("will generate app/Features/LoginUserFeature.php"); + $this->info('will generate app/Features/LoginUserFeature.php'); } $this->info(''); @@ -53,7 +53,7 @@ private function welcome($service = null) $this->info(''); - $this->info('For more details, help yourself with the docs at https://docs.lucidarch.dev'); + $this->info('For more details, help yourself with the docs at https://docs.lucidarch.dev'); $this->info(''); $this->info('Remember to enjoy the journey.'); $this->info('Cheers!'); diff --git a/src/Console/Commands/InitMicroCommand.php b/src/Console/Commands/InitMicroCommand.php index 8841056..be63a8b 100644 --- a/src/Console/Commands/InitMicroCommand.php +++ b/src/Console/Commands/InitMicroCommand.php @@ -2,51 +2,27 @@ namespace Lucid\Console\Commands; -use Lucid\Finder; -use Lucid\Filesystem; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Generators\MicroGenerator; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -class InitMicroCommand extends SymfonyCommand +class InitMicroCommand extends Command { - use Finder; - use Command; - use Filesystem; use InitCommandTrait; - /** - * The console command name. - * - * @var string - */ - protected $name = 'init:micro'; - - /** - * The console command description. - * - * @var string - */ + protected $signature = 'init:micro'; + protected $description = 'Initialize Lucid Micro in current project.'; - /** - * Execute the console command. - * - * @return int - */ - public function handle() + public function handle(): void { $version = app()->version(); $this->info("Initializing Lucid Micro for Laravel $version\n"); - $generator = new MicroGenerator(); - $paths = $generator->generate(); + $paths = (new MicroGenerator())->generate(); - $this->comment("Created directories:"); - $this->comment(join("\n", $paths)); + $this->comment('Created directories:'); + $this->comment(implode("\n", $paths)); $this->welcome(); - - return 0; } } diff --git a/src/Console/Commands/InitMonolithCommand.php b/src/Console/Commands/InitMonolithCommand.php index da2fbc1..95f84b2 100644 --- a/src/Console/Commands/InitMonolithCommand.php +++ b/src/Console/Commands/InitMonolithCommand.php @@ -2,59 +2,20 @@ namespace Lucid\Console\Commands; -use Lucid\Str; -use Lucid\Finder; -use Lucid\Filesystem; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Generators\MonolithGenerator; -use Illuminate\Support\Composer; -use Symfony\Component\Console\Input\ArrayInput; -use Illuminate\Filesystem\Filesystem as IlluminateFilesystem; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -class InitMonolithCommand extends SymfonyCommand +class InitMonolithCommand extends Command { - use Finder; - use Command; - use Filesystem; use InitCommandTrait; - /** - * The console command name. - * - * @var string - */ - protected $name = 'init:monolith'; + protected $signature = 'init:monolith + {service? : Your first service.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Initialize Lucid Monolith in current project.'; - /** - * The Composer class instance. - * - * @var Composer - */ - protected $composer; - - /** - * The filesystem instance. - * - * @var Filesystem - */ - protected $files; - - /** - * Execute the console command. - * - * @return int - */ - public function handle() + public function handle(): void { $version = app()->version(); $this->info("Initializing Lucid Monolith for Laravel $version\n"); @@ -63,42 +24,14 @@ public function handle() $directories = (new MonolithGenerator())->generate(); $this->comment('Created directories:'); - $this->comment(join("\n", $directories)); + $this->comment(implode("\n", $directories)); // create service if ($service) { - $this->getApplication() - ->find('make:service') - ->run(new ArrayInput(['name' => $service]), $this->output); - + $this->call('make:service', ['name' => $service]); $this->ask('Once done, press Enter/Return to continue...'); } $this->welcome($service); - - return 0; - } - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['service', InputArgument::OPTIONAL, 'Your first service.'], - ]; - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions() - { - return [ - ]; } } diff --git a/src/Console/Commands/JobDeleteCommand.php b/src/Console/Commands/JobDeleteCommand.php index 93a9848..60aa2f0 100644 --- a/src/Console/Commands/JobDeleteCommand.php +++ b/src/Console/Commands/JobDeleteCommand.php @@ -2,53 +2,31 @@ namespace Lucid\Console\Commands; -use Lucid\Str; -use Lucid\Finder; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Lucid\Finder; +use Lucid\Str; -class JobDeleteCommand extends SymfonyCommand +class JobDeleteCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The console command name. - * - * @var string - */ - protected $name = 'delete:job'; + protected $signature = 'delete:job + {job : The job\'s name.} + {domain : The domain from which the job will be deleted.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Delete an existing Job in a domain'; - /** - * The type of class being deleted. - * - * @var string - */ - protected $type = 'Job'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { try { $domain = Str::studly($this->argument('domain')); - $title = $this->parseName($this->argument('job')); + $title = Str::job($this->argument('job')); - if (!$this->exists($job = $this->findJobPath($domain, $title))) { - $this->error('Job class '.$title.' cannot be found.'); + // Delete job + if (! $this->exists($job = $this->findJobPath($domain, $title))) { + $this->error("Job class $title cannot be found."); } else { $this->delete($job); @@ -56,42 +34,20 @@ public function handle() $this->delete($this->findDomainPath($domain)); } - $this->info('Job class '.$title.' deleted successfully.'); + $this->info("Job class $title deleted successfully."); } - } catch (Exception $e) { - $this->error($e->getMessage()); - } - } - public function getArguments() - { - return [ - ['job', InputArgument::REQUIRED, 'The job\'s name.'], - ['domain', InputArgument::REQUIRED, 'The domain from which the job will be deleted.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/job.stub'; - } + // Delete job tests + $testTitle = $title.'Test'; + if (! $this->exists($job = $this->findJobTestPath($domain, $testTitle))) { + $this->error("Job test class $testTitle cannot be found."); + } else { + $this->delete($job); - /** - * Parse the job name. - * remove the Job.php suffix if found - * we're adding it ourselves. - * - * @param string $name - * - * @return string - */ - protected function parseName($name) - { - return Str::job($name); + $this->info("Job test class $testTitle deleted successfully."); + } + } catch (\Exception $e) { + $this->error($e->getMessage()); + } } } diff --git a/src/Console/Commands/JobMakeCommand.php b/src/Console/Commands/JobMakeCommand.php index 89cc88f..86ed014 100644 --- a/src/Console/Commands/JobMakeCommand.php +++ b/src/Console/Commands/JobMakeCommand.php @@ -2,104 +2,37 @@ namespace Lucid\Console\Commands; -use Lucid\Console\Command; -use Lucid\Filesystem; -use Lucid\Finder; +use Illuminate\Console\Command; use Lucid\Generators\JobGenerator; use Lucid\Str; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -class JobMakeCommand extends SymfonyCommand +class JobMakeCommand extends Command { - use Finder; - use Command; - use Filesystem; + protected $signature = 'make:job + {job : The job\'s name.} + {domain : The domain to be responsible for the job.} + {--Q|queue : Whether a job is queueable or not.} + '; - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:job {--Q|queue}'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a new Job in a domain'; - /** - * The type of class being generated. - * - * @var string - */ - protected $type = 'Job'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - $generator = new JobGenerator(); - - $domain = Str::studly($this->argument('domain')); - $title = $this->parseName($this->argument('job')); - $isQueueable = $this->option('queue'); try { - $job = $generator->generate($title, $domain, $isQueueable); + $job = (new JobGenerator()) + ->generate( + Str::job($this->argument('job')), + Str::studly($this->argument('domain')), + $this->option('queue') + ); $this->info( - 'Job class '.$title.' created successfully.'. - "\n". - "\n". - 'Find it at '.$job->relativePath.''."\n" + "Job class $job->title created successfully." + ."\n\n" + ."Find it at $job->relativePath\n" ); - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - public function getArguments() - { - return [ - ['job', InputArgument::REQUIRED, 'The job\'s name.'], - ['domain', InputArgument::REQUIRED, 'The domain to be responsible for the job.'], - ]; - } - - public function getOptions() - { - return [ - ['queue', 'Q', InputOption::VALUE_NONE, 'Whether a job is queueable or not.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/job.stub'; - } - - /** - * Parse the job name. - * remove the Job.php suffix if found - * we're adding it ourselves. - * - * @param string $name - * - * @return string - */ - protected function parseName($name) - { - return Str::job($name); - } } diff --git a/src/Console/Commands/MigrationMakeCommand.php b/src/Console/Commands/MigrationMakeCommand.php index 03f317d..b78b901 100644 --- a/src/Console/Commands/MigrationMakeCommand.php +++ b/src/Console/Commands/MigrationMakeCommand.php @@ -2,58 +2,31 @@ namespace Lucid\Console\Commands; -use Lucid\Str; -use Illuminate\Support\Facades\Artisan; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Finder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; +use Lucid\Str; -class MigrationMakeCommand extends SymfonyCommand +class MigrationMakeCommand extends Command { use Finder; - use Command; - - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:migration'; - - /** - * The console command description. - * - * @var string - */ - protected $description = 'Create a new Migration class in a service'; - /** - * Execute the console command. - */ - public function handle() - { - $service = $this->argument('service'); - $migration = $this->argument('migration'); + protected $signature = 'make:migration + {migration : The migration\'s name.} + {service? : The service in which the migration should be generated.} + '; - $path = $this->findMigrationPath(Str::service($service)); + protected $description = 'Create a new Migration class in a service'; - $output = shell_exec('php artisan make:migration '.$migration.' --path='.$path); + public function handle(): void + { + $path = $this + ->findMigrationPath(Str::service($this->argument('service'))); - $this->info($output); - $this->info("\n".'Find it at '.$path.''."\n"); - } + $this->call('make:migration', [ + 'name' => $this->argument('migration'), + '--path' => $path, + ]); - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['migration', InputArgument::REQUIRED, 'The migration\'s name.'], - ['service', InputArgument::OPTIONAL, 'The service in which the migration should be generated.'], - ]; + $this->info("\n Find it at $path \n"); } } diff --git a/src/Console/Commands/ModelDeleteCommand.php b/src/Console/Commands/ModelDeleteCommand.php index 6c53b41..1f2028a 100644 --- a/src/Console/Commands/ModelDeleteCommand.php +++ b/src/Console/Commands/ModelDeleteCommand.php @@ -3,91 +3,35 @@ namespace Lucid\Console\Commands; use Exception; -use Lucid\Str; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; use Lucid\Finder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; +use Lucid\Str; -class ModelDeleteCommand extends SymfonyCommand +class ModelDeleteCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The console command name. - * - * @var string - */ - protected $name = 'delete:model'; + protected $signature = 'delete:model + {model : The Model\'s name.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Delete an existing Eloquent Model.'; - /** - * The type of class being generated - * @var string - */ - protected $type = 'Model'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { try { - $model = $this->parseModelName($this->argument('model')); + $model = Str::model($this->argument('model')); - if ( ! $this->exists($path = $this->findModelPath($model))) { - $this->error('Model class ' . $model . ' cannot be found.'); + if (! $this->exists($path = $this->findModelPath($model))) { + $this->error("Model class $model cannot be found."); } else { $this->delete($path); - $this->info('Model class ' . $model . ' deleted successfully.'); + $this->info("Model class $model deleted successfully."); } } catch (Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - public function getArguments() - { - return [ - ['model', InputArgument::REQUIRED, 'The Model\'s name.'] - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/model.stub'; - } - - /** - * Parse the model name. - * - * @param string $name - * @return string - */ - public function parseModelName($name) - { - return Str::model($name); - } } diff --git a/src/Console/Commands/ModelMakeCommand.php b/src/Console/Commands/ModelMakeCommand.php index 463b26d..51995d6 100644 --- a/src/Console/Commands/ModelMakeCommand.php +++ b/src/Console/Commands/ModelMakeCommand.php @@ -2,83 +2,30 @@ namespace Lucid\Console\Commands; -use Exception; +use Illuminate\Console\Command; use Lucid\Generators\ModelGenerator; -use Lucid\Console\Command; -use Lucid\Filesystem; -use Lucid\Finder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; -class ModelMakeCommand extends SymfonyCommand +class ModelMakeCommand extends Command { - use Finder; - use Command; - use Filesystem; + protected $signature = 'make:model + {model : The Model\'s name.} + '; - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:model'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a new Eloquent Model.'; - /** - * The type of class being generated - * @var string - */ - protected $type = 'Model'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - $generator = new ModelGenerator(); - - $name = $this->argument('model'); - try { - $model = $generator->generate($name); + $model = (new ModelGenerator()) + ->generate($this->argument('model')); - $this->info('Model class created successfully.' . - "\n" . - "\n" . - 'Find it at ' . $model->relativePath . '' . "\n" + $this->info( + 'Model class created successfully.' + ."\n\n" + ."Find it at $model->relativePath\n" ); - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - public function getArguments() - { - return [ - ['model', InputArgument::REQUIRED, 'The Model\'s name.'] - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/model.stub'; - } } diff --git a/src/Console/Commands/NewCommand.php b/src/Console/Commands/NewCommand.php deleted file mode 100644 index 15ea301..0000000 --- a/src/Console/Commands/NewCommand.php +++ /dev/null @@ -1,84 +0,0 @@ -setName('new') - ->setDescription('Create a new Lucid-architected project') - ->addArgument('name', InputArgument::OPTIONAL) - ->addOption('laravel', null, InputOption::VALUE_NONE, 'Specify the Laravel version you wish to install'); - } - - /** - * Execute the command. - * - * @param InputInterface $input - * @param OutputInterface $output - */ - public function execute(InputInterface $input, OutputInterface $output) - { - $this->verifyApplicationDoesntExist( - $directory = ($input->getArgument('name')) ? getcwd().'/'.$input->getArgument('name') : getcwd(), - $output - ); - - $output->writeln('Crafting Lucid application...'); - - /* - * @TODO: Get Lucid based on the Laravel version. - */ - $process = new Process($this->findComposer().' create-project laravel/laravel '.$directory); - - if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { - $process->setTty(true); - } - - $process->run(function ($type, $line) use ($output) { - $output->write($line); - }); - - $output->writeln('Application ready! Make your dream a reality.'); - } - - /** - * Verify that the application does not already exist. - * - * @param string $directory - */ - protected function verifyApplicationDoesntExist($directory, OutputInterface $output) - { - if ((is_dir($directory) || is_file($directory)) && $directory != getcwd()) { - throw new RuntimeException('Application already exists!'); - } - } - - /** - * Get the composer command for the environment. - * - * @return string - */ - protected function findComposer() - { - $composer = 'composer'; - - if (file_exists(getcwd().'/composer.phar')) { - $composer = '"'.PHP_BINARY.'" composer.phar'; - } - - return $composer; - } -} diff --git a/src/Console/Commands/OperationDeleteCommand.php b/src/Console/Commands/OperationDeleteCommand.php index 22cd63d..93c0d4e 100644 --- a/src/Console/Commands/OperationDeleteCommand.php +++ b/src/Console/Commands/OperationDeleteCommand.php @@ -2,97 +2,48 @@ namespace Lucid\Console\Commands; -use Lucid\Str; -use Lucid\Finder; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Lucid\Finder; +use Lucid\Str; -class OperationDeleteCommand extends SymfonyCommand +class OperationDeleteCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The console command name. - * - * @var string - */ - protected $name = 'delete:operation'; + protected $signature = 'delete:operation + {operation : The operation\'s name.} + {service? : The service from which the operation should be deleted.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Delete an existing Operation in a service'; - /** - * The type of class being deleted. - * - * @var string - */ - protected $type = 'Operation'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { + $service = Str::service($this->argument('service')); + $title = Str::operation($this->argument('operation')); + try { - $service = Str::service($this->argument('service')); - $title = $this->parseName($this->argument('operation')); + // Delete operation + if (! $this->exists($operation = $this->findOperationPath($service, $title))) { + $this->error("Operation class $title cannot be found."); + } else { + $this->delete($operation); + + $this->info("Operation class $title deleted successfully."); + } - if (!$this->exists($operation = $this->findOperationPath($service, $title))) { - $this->error('Operation class '.$title.' cannot be found.'); + // Delete operation tests + $testTitle = $title.'Test'; + if (! $this->exists($operation = $this->findOperationTestPath($service, $testTitle))) { + $this->error("Operation test class $testTitle cannot be found."); } else { $this->delete($operation); - $this->info('Operation class '.$title.' deleted successfully.'); + $this->info("Operation test class $testTitle deleted successfully."); } - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['operation', InputArgument::REQUIRED, 'The operation\'s name.'], - ['service', InputArgument::OPTIONAL, 'The service from which the operation should be deleted.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - return __DIR__ . '/../Generators/stubs/operation.stub'; - } - - /** - * Parse the operation name. - * remove the Operation.php suffix if found - * we're adding it ourselves. - * - * @param string $name - * - * @return string - */ - protected function parseName($name) - { - return Str::operation($name); - } } diff --git a/src/Console/Commands/OperationMakeCommand.php b/src/Console/Commands/OperationMakeCommand.php index afd06af..4e03ba5 100644 --- a/src/Console/Commands/OperationMakeCommand.php +++ b/src/Console/Commands/OperationMakeCommand.php @@ -2,105 +2,37 @@ namespace Lucid\Console\Commands; -use Lucid\Console\Command; -use Lucid\Filesystem; -use Lucid\Finder; +use Illuminate\Console\Command; use Lucid\Generators\OperationGenerator; use Lucid\Str; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -class OperationMakeCommand extends SymfonyCommand +class OperationMakeCommand extends Command { - use Finder; - use Command; - use Filesystem; + protected $signature = 'make:operation + {operation : The operation\'s name.} + {service? : The service in which the operation should be implemented.} + {--Q|queue : Whether an operation is queueable or not.} + '; - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:operation {--Q|queue}'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a new Operation in a domain'; - /** - * The type of class being generated. - * - * @var string - */ - protected $type = 'Operation'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - $generator = new OperationGenerator(); - - $service = Str::studly($this->argument('service')); - $title = $this->parseName($this->argument('operation')); - $isQueueable = $this->option('queue'); try { - $operation = $generator->generate($title, $service, $isQueueable); + $operation = (new OperationGenerator()) + ->generate( + Str::operation($this->argument('operation')), + Str::studly($this->argument('service')), + $this->option('queue') + ); $this->info( - 'Operation class '.$title.' created successfully.'. - "\n". - "\n". - 'Find it at '.$operation->relativePath.''."\n" + "Operation class $operation->title created successfully." + ."\n\n" + ."Find it at $operation->relativePath\n" ); - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - public function getArguments() - { - return [ - ['operation', InputArgument::REQUIRED, 'The operation\'s name.'], - ['service', InputArgument::OPTIONAL, 'The service in which the operation should be implemented.'], - ['jobs', InputArgument::IS_ARRAY, 'A list of Jobs Operation calls'] - ]; - } - - public function getOptions() - { - return [ - ['queue', 'Q', InputOption::VALUE_NONE, 'Whether a operation is queueable or not.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/operation.stub'; - } - - /** - * Parse the operation name. - * remove the Operation.php suffix if found - * we're adding it ourselves. - * - * @param string $name - * - * @return string - */ - protected function parseName($name) - { - return Str::operation($name); - } } diff --git a/src/Console/Commands/PolicyDeleteCommand.php b/src/Console/Commands/PolicyDeleteCommand.php index 15fae79..f2cd528 100644 --- a/src/Console/Commands/PolicyDeleteCommand.php +++ b/src/Console/Commands/PolicyDeleteCommand.php @@ -2,92 +2,35 @@ namespace Lucid\Console\Commands; -use Exception; -use Lucid\Str; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; use Lucid\Finder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; +use Lucid\Str; -class PolicyDeleteCommand extends SymfonyCommand +class PolicyDeleteCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The console command name. - * - * @var string - */ - protected $name = 'delete:policy'; + protected $signature = 'delete:policy + {policy : The Policy\'s name.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Delete an existing Policy.'; - /** - * The type of class being generated - * @var string - */ - protected $type = 'Policy'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { try { - $policy = $this->parsePolicyName($this->argument('policy')); + $policy = Str::policy($this->argument('policy')); - if ( ! $this->exists($path = $this->findPolicyPath($policy))) { - $this->error('Policy class ' . $policy . ' cannot be found.'); + if (! $this->exists($path = $this->findPolicyPath($policy))) { + $this->error("Policy class $policy cannot be found."); } else { $this->delete($path); - $this->info('Policy class ' . $policy . ' deleted successfully.'); + $this->info("Policy class $policy deleted successfully."); } - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - public function getArguments() - { - return [ - ['policy', InputArgument::REQUIRED, 'The Policy\'s name.'] - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/policy.stub'; - } - - /** - * Parse the model name. - * - * @param string $name - * @return string - */ - public function parsePolicyName($name) - { - return Str::policy($name); - } } diff --git a/src/Console/Commands/PolicyMakeCommand.php b/src/Console/Commands/PolicyMakeCommand.php index f9a2e6b..f434099 100644 --- a/src/Console/Commands/PolicyMakeCommand.php +++ b/src/Console/Commands/PolicyMakeCommand.php @@ -2,83 +2,30 @@ namespace Lucid\Console\Commands; -use Exception; +use Illuminate\Console\Command; use Lucid\Generators\PolicyGenerator; -use Lucid\Console\Command; -use Lucid\Filesystem; -use Lucid\Finder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; -class PolicyMakeCommand extends SymfonyCommand +class PolicyMakeCommand extends Command { - use Finder; - use Command; - use Filesystem; + protected $signature = 'make:policy + {policy : The Policy\'s name.} + '; - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:policy'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a Policy.'; - /** - * The type of class being generated - * @var string - */ - protected $type = 'Policy'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - $generator = new PolicyGenerator(); - - $name = $this->argument('policy'); - try { - $policy = $generator->generate($name); + $policy = (new PolicyGenerator()) + ->generate($this->argument('policy')); - $this->info('Policy class created successfully.' . - "\n" . - "\n" . - 'Find it at ' . $policy->relativePath . '' . "\n" + $this->info( + 'Policy class created successfully.' + ."\n\n" + ."Find it at $policy->relativePath\n" ); - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - public function getArguments() - { - return [ - ['policy', InputArgument::REQUIRED, 'The Policy\'s name.'] - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/policy.stub'; - } } diff --git a/src/Console/Commands/RequestDeleteCommand.php b/src/Console/Commands/RequestDeleteCommand.php index 4790f4c..6207016 100644 --- a/src/Console/Commands/RequestDeleteCommand.php +++ b/src/Console/Commands/RequestDeleteCommand.php @@ -2,94 +2,37 @@ namespace Lucid\Console\Commands; -use Exception; -use Lucid\Str; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; use Lucid\Finder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; +use Lucid\Str; -class RequestDeleteCommand extends SymfonyCommand +class RequestDeleteCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The console command name. - * - * @var string - */ - protected $name = 'delete:request'; + protected $signature = 'delete:request + {request : The Request\'s name.} + {service : The Service\'s name.} + '; - /** - * The console command description. - * - * @var string - */ protected $description = 'Delete an existing Request.'; - /** - * The type of class being generated - * @var string - */ - protected $type = 'Request'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { try { - $request = $this->parseRequestName($this->argument('request')); + $request = Str::request($this->argument('request')); $service = Str::service($this->argument('service')); - if ( ! $this->exists($path = $this->findRequestPath($service, $request))) { - $this->error('Request class ' . $request . ' cannot be found.'); + if (! $this->exists($path = $this->findRequestPath($service, $request))) { + $this->error("Request class $request cannot be found."); } else { $this->delete($path); - $this->info('Request class ' . $request . ' deleted successfully.'); + $this->info("Request class $request deleted successfully."); } - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - public function getArguments() - { - return [ - ['request', InputArgument::REQUIRED, 'The Request\'s name.'], - ['service', InputArgument::REQUIRED, 'The Service\'s name.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/request.stub'; - } - - /** - * Parse the model name. - * - * @param string $name - * @return string - */ - public function parseRequestName($name) - { - return Str::request($name); - } } diff --git a/src/Console/Commands/RequestMakeCommand.php b/src/Console/Commands/RequestMakeCommand.php index 6dd8d06..bd5eee9 100644 --- a/src/Console/Commands/RequestMakeCommand.php +++ b/src/Console/Commands/RequestMakeCommand.php @@ -2,85 +2,34 @@ namespace Lucid\Console\Commands; -use Exception; +use Illuminate\Console\Command; use Lucid\Generators\RequestGenerator; -use Lucid\Console\Command; -use Lucid\Filesystem; -use Lucid\Finder; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -use Symfony\Component\Console\Input\InputArgument; -class RequestMakeCommand extends SymfonyCommand +class RequestMakeCommand extends Command { - use Finder; - use Command; - use Filesystem; + protected $signature = 'make:request + {name : The name of the class.} + {domain : The Domain in which this request should be generated.} + '; - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:request'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a Request in a domain.'; - /** - * The type of class being generated - * @var string - */ - protected $type = 'Request'; - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { - $generator = new RequestGenerator(); - - $name = $this->argument('name'); - $service = $this->argument('domain'); - try { - $request = $generator->generate($name, $service); - - $this->info('Request class created successfully.' . - "\n" . - "\n" . - 'Find it at ' . $request->relativePath . '' . "\n" + $request = (new RequestGenerator()) + ->generate( + $this->argument('name'), + $this->argument('domain') + ); + + $this->info( + 'Request class created successfully.' + ."\n\n" + ."Find it at $request->relativePath\n" ); - } catch (Exception $e) { + } catch (\Exception $e) { $this->error($e->getMessage()); } } - - /** - * Get the console command arguments. - * - * @return array - */ - public function getArguments() - { - return [ - ['name', InputArgument::REQUIRED, 'The name of the class.'], - ['domain', InputArgument::REQUIRED, 'The Domain in which this request should be generated.'], - ]; - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - public function getStub() - { - return __DIR__ . '/../Generators/stubs/request.stub'; - } } diff --git a/src/Console/Commands/ServiceDeleteCommand.php b/src/Console/Commands/ServiceDeleteCommand.php index 84ee8b7..a02320c 100644 --- a/src/Console/Commands/ServiceDeleteCommand.php +++ b/src/Console/Commands/ServiceDeleteCommand.php @@ -2,89 +2,47 @@ namespace Lucid\Console\Commands; -use Lucid\Str; -use Lucid\Finder; -use Lucid\Console\Command; +use Illuminate\Console\Command; use Lucid\Filesystem; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Lucid\Finder; +use Lucid\Str; -class ServiceDeleteCommand extends SymfonyCommand +class ServiceDeleteCommand extends Command { - use Finder; - use Command; - use Filesystem; + use Filesystem, Finder; - /** - * The base namespace for this command. - * - * @var string - */ - private $namespace; + protected $signature = 'delete:service + {name : The service name.} + '; - /** - * The Services path. - * - * @var string - */ - private $path; - - /** - * The console command name. - * - * @var string - */ - protected $name = 'delete:service'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Delete an existing Service'; - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - return __DIR__ . '/../Generators/stubs/service.stub'; - } - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { if ($this->isMicroservice()) { - return $this->error('This functionality is disabled in a Microservice'); + $this->error('This functionality is disabled in a Microservice'); + + return; } + $name = Str::service($this->argument('name')); + try { - $name = Str::service($this->argument('name')); + if (! $this->exists($service = $this->findServicePath($name))) { + $this->error("Service $name cannot be found."); - if (!$this->exists($service = $this->findServicePath($name))) { - return $this->error('Service '.$name.' cannot be found.'); + return; } $this->delete($service); - $this->info('Service '.$name.' deleted successfully.'."\n"); + $this->info("Service $name deleted successfully \n"); $this->info('Please remove your registered service providers, if any.'); } catch (\Exception $e) { - dd($e->getMessage(), $e->getFile(), $e->getLine()); + $this->error($e->getMessage()); + $this->error($e->getFile()); + $this->error((string) $e->getLine()); } } - - public function getArguments() - { - return [ - ['name', InputArgument::REQUIRED, 'The service name.'], - ]; - } } diff --git a/src/Console/Commands/ServiceMakeCommand.php b/src/Console/Commands/ServiceMakeCommand.php index f9a1a2d..6e5d335 100644 --- a/src/Console/Commands/ServiceMakeCommand.php +++ b/src/Console/Commands/ServiceMakeCommand.php @@ -2,91 +2,39 @@ namespace Lucid\Console\Commands; +use Illuminate\Console\Command; use Lucid\Finder; -use Lucid\Console\Command; -use Lucid\Filesystem; use Lucid\Generators\ServiceGenerator; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -class ServiceMakeCommand extends SymfonyCommand +class ServiceMakeCommand extends Command { use Finder; - use Command; - use Filesystem; - /** - * The base namespace for this command. - * - * @var string - */ - private $namespace; + protected $signature = 'make:service + {name : The service name.} + '; - /** - * The Services path. - * - * @var string - */ - private $path; - - /** - * The console command name. - * - * @var string - */ - protected $name = 'make:service'; - - /** - * The console command description. - * - * @var string - */ protected $description = 'Create a new Service'; - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - return __DIR__ . '/../Generators/stubs/service.stub'; - } - - /** - * Execute the console command. - * - * @return bool|null - */ - public function handle() + public function handle(): void { try { - $name = $this->argument('name'); + $service = (new ServiceGenerator()) + ->generate($this->argument('name')); - $generator = new ServiceGenerator(); - $service = $generator->generate($name); + $this->info("Service $service->name created successfully.\n"); - $this->info('Service '.$service->name.' created successfully.'."\n"); - - $rootNamespace = $this->findRootNamespace(); $serviceNamespace = $this->findServiceNamespace($service->name); $serviceProvider = $serviceNamespace.'\\Providers\\'.$service->name.'ServiceProvider'; - $this->info('Activate it by adding '. - ''.$serviceProvider.'::class '. - "\nto 'providers' in config/app.php". - "\n" + $this->info( + 'Activate it by adding ' + ."$serviceProvider::class" + ."\nto 'providers' in config/app.php\n" ); } catch (\Exception $e) { $this->error($e->getMessage()."\n".$e->getFile().' at '.$e->getLine()); } } - - public function getArguments() - { - return [ - ['name', InputArgument::REQUIRED, 'The service name.'], - ]; - } } diff --git a/src/Console/Commands/ServicesListCommand.php b/src/Console/Commands/ServicesListCommand.php index 1d0d0b9..e4615bd 100644 --- a/src/Console/Commands/ServicesListCommand.php +++ b/src/Console/Commands/ServicesListCommand.php @@ -2,35 +2,27 @@ namespace Lucid\Console\Commands; +use Illuminate\Console\Command; +use Lucid\Entities\Service; use Lucid\Finder; -use Lucid\Console\Command; -use Symfony\Component\Console\Command\Command as SymfonyCommand; -class ServicesListCommand extends SymfonyCommand +class ServicesListCommand extends Command { use Finder; - use Command; - /** - * The console command name. - * - * @var string - */ - protected $name = 'list:services'; + protected $signature = 'list:services'; - /** - * The console command description. - * - * @var string - */ protected $description = 'List the services in this project.'; - public function handle() + public function handle(): void { $services = $this->listServices()->all(); - $this->table(['Service', 'Slug', 'Path'], array_map(function($service) { - return [$service->name, $service->slug, $service->relativePath]; - }, $services)); + $this->table( + ['Service', 'Slug', 'Path'], + array_map(function (Service $service) { + return [$service->name, $service->slug, $service->relativePath]; + }, $services) + ); } } diff --git a/src/Domains/Http/Jobs/RespondWithJsonErrorJob.php b/src/Domains/Http/Jobs/RespondWithJsonErrorJob.php index 507441f..476ee6c 100644 --- a/src/Domains/Http/Jobs/RespondWithJsonErrorJob.php +++ b/src/Domains/Http/Jobs/RespondWithJsonErrorJob.php @@ -2,11 +2,19 @@ namespace Lucid\Domains\Http\Jobs; -use Lucid\Units\Job; use Illuminate\Routing\ResponseFactory; +use Lucid\Units\Job; class RespondWithJsonErrorJob extends Job { + protected array $content; + + protected int $status; + + protected array $headers; + + protected int $options; + public function __construct($message = 'An error occurred', $code = 400, $status = 400, $headers = [], $options = 0) { $this->content = [ diff --git a/src/Domains/Http/Jobs/RespondWithJsonJob.php b/src/Domains/Http/Jobs/RespondWithJsonJob.php index f00c0f6..80a69f3 100644 --- a/src/Domains/Http/Jobs/RespondWithJsonJob.php +++ b/src/Domains/Http/Jobs/RespondWithJsonJob.php @@ -2,15 +2,18 @@ namespace Lucid\Domains\Http\Jobs; -use Lucid\Units\Job; use Illuminate\Routing\ResponseFactory; +use Lucid\Units\Job; class RespondWithJsonJob extends Job { - protected $status; - protected $content; - protected $headers; - protected $options; + protected mixed $content; + + protected int $status; + + protected array $headers; + + protected int $options; public function __construct($content, $status = 200, array $headers = [], $options = 0) { diff --git a/src/Domains/Http/Jobs/RespondWithViewJob.php b/src/Domains/Http/Jobs/RespondWithViewJob.php index 8dbcffb..6440e5e 100644 --- a/src/Domains/Http/Jobs/RespondWithViewJob.php +++ b/src/Domains/Http/Jobs/RespondWithViewJob.php @@ -2,15 +2,18 @@ namespace Lucid\Domains\Http\Jobs; -use Lucid\Units\Job; use Illuminate\Routing\ResponseFactory; +use Lucid\Units\Job; class RespondWithViewJob extends Job { - protected $status; - protected $data; - protected $headers; - protected $template; + protected array|string $template; + + protected array $data; + + protected int $status; + + protected array $headers; public function __construct($template, $data = [], $status = 200, array $headers = []) { diff --git a/src/Entities/Domain.php b/src/Entities/Domain.php index 06c1088..35605a1 100644 --- a/src/Entities/Domain.php +++ b/src/Entities/Domain.php @@ -2,12 +2,23 @@ namespace Lucid\Entities; -use Illuminate\Support\Str; +use Lucid\Str; +/** + * @property-read string $name + * @property-read string $slug + * @property-read string $namespace + * @property-read string $realPath + * @property-read string $relativePath + */ class Domain extends Entity { - public function __construct($name, $namespace, $path, $relativePath) - { + public function __construct( + string $name, + string $namespace, + string $path, + string $relativePath + ) { $this->setAttributes([ 'name' => $name, 'slug' => Str::studly($name), diff --git a/src/Entities/Entity.php b/src/Entities/Entity.php index 87d4b74..58c1c45 100644 --- a/src/Entities/Entity.php +++ b/src/Entities/Entity.php @@ -4,51 +4,35 @@ use Illuminate\Contracts\Support\Arrayable; -/** - * @property-read string title - * @property-read string className - * @property-read string service - * @property-read string file - * @property-read string realPath - * @property-read string relativePath - * @property-read string content - */ class Entity implements Arrayable { - protected $attributes = []; + protected array $attributes = []; /** * Get the array representation of this instance. - * - * @return array */ - public function toArray() + public function toArray(): array { return $this->attributes; } /** * Set the attributes for this component. - * - * @param array $attributes */ - protected function setAttributes(array $attributes) + protected function setAttributes(array $attributes): void { $this->attributes = $attributes; } /** * Get an attribute's value if found. - * - * @param string $key - * - * @return mixed */ - public function __get($key) + public function __get(string $key): mixed { if (isset($this->attributes[$key])) { return $this->attributes[$key]; } - } + return null; + } } diff --git a/src/Entities/Feature.php b/src/Entities/Feature.php index 2f06c5b..764a17d 100644 --- a/src/Entities/Feature.php +++ b/src/Entities/Feature.php @@ -2,15 +2,28 @@ namespace Lucid\Entities; +/** + * @property-read string $title + * @property-read string $className + * @property-read Service $service + * @property-read string $file + * @property-read string $realPath + * @property-read string $relativePath + * @property-read string $content + */ class Feature extends Entity { - public function __construct($title, $file, $realPath, $relativePath, Service $service = null, $content = '') - { - $className = str_replace(' ', '', $title).'Feature'; - + public function __construct( + string $title, + string $file, + string $realPath, + string $relativePath, + ?Service $service = null, + string $content = '' + ) { $this->setAttributes([ 'title' => $title, - 'className' => $className, + 'className' => str_replace(' ', '', $title).'Feature', 'service' => $service, 'file' => $file, 'realPath' => $realPath, @@ -18,17 +31,4 @@ public function __construct($title, $file, $realPath, $relativePath, Service $se 'content' => $content, ]); } - - // public function toArray() - // { - // $attributes = parent::toArray(); - // - // // real path not needed - // unset($attributes['realPath']); - // - // // map the service object to its name - // $attributes['service'] = $attributes['service']->name; - // - // return $attributes; - // } } diff --git a/src/Entities/Job.php b/src/Entities/Job.php index 121b7b2..f7e8ccb 100644 --- a/src/Entities/Job.php +++ b/src/Entities/Job.php @@ -2,14 +2,30 @@ namespace Lucid\Entities; +/** + * @property-read string $title + * @property-read string $className + * @property-read string $namespace + * @property-read string $file + * @property-read string $realPath + * @property-read string $relativePath + * @property-read string $domain + * @property-read string $content + */ class Job extends Entity { - public function __construct($title, $namespace, $file, $path, $relativePath, Domain $domain = null, $content = '') - { - $className = str_replace(' ', '', $title).'Job'; + public function __construct( + string $title, + string $namespace, + string $file, + string $path, + string $relativePath, + ?Domain $domain = null, + string $content = '' + ) { $this->setAttributes([ 'title' => $title, - 'className' => $className, + 'className' => str_replace(' ', '', $title).'Job', 'namespace' => $namespace, 'file' => $file, 'realPath' => $path, @@ -19,7 +35,7 @@ public function __construct($title, $namespace, $file, $path, $relativePath, Dom ]); } - public function toArray() + public function toArray(): array { $attributes = parent::toArray(); diff --git a/src/Entities/Model.php b/src/Entities/Model.php index 9cf42eb..c647dc5 100644 --- a/src/Entities/Model.php +++ b/src/Entities/Model.php @@ -2,10 +2,24 @@ namespace Lucid\Entities; +/** + * @property-read string $model + * @property-read string $namespace + * @property-read string $file + * @property-read string $path + * @property-read string $relativePath + * @property-read string $content + */ class Model extends Entity { - public function __construct($title, $namespace, $file, $path, $relativePath, $content) - { + public function __construct( + string $title, + string $namespace, + string $file, + string $path, + string $relativePath, + string $content + ) { $this->setAttributes([ 'model' => $title, 'namespace' => $namespace, diff --git a/src/Entities/Operation.php b/src/Entities/Operation.php index 8820d12..10ce5a8 100644 --- a/src/Entities/Operation.php +++ b/src/Entities/Operation.php @@ -2,15 +2,28 @@ namespace Lucid\Entities; +/** + * @property-read string $title + * @property-read string $className + * @property-read string $service + * @property-read string $file + * @property-read string $realPath + * @property-read string $relativePath + * @property-read string $content + */ class Operation extends Entity { - public function __construct($title, $file, $realPath, $relativePath, Service $service = null, $content = '') - { - $className = str_replace(' ', '', $title).'Operation'; - + public function __construct( + string $title, + string $file, + string $realPath, + string $relativePath, + ?Service $service = null, + string $content = '' + ) { $this->setAttributes([ 'title' => $title, - 'className' => $className, + 'className' => str_replace(' ', '', $title).'Operation', 'service' => $service, 'file' => $file, 'realPath' => $realPath, diff --git a/src/Entities/Policy.php b/src/Entities/Policy.php index 08690a7..4fc2a08 100644 --- a/src/Entities/Policy.php +++ b/src/Entities/Policy.php @@ -2,10 +2,24 @@ namespace Lucid\Entities; +/** + * @property-read string $policy + * @property-read string $namespace + * @property-read string $file + * @property-read string $path + * @property-read string $relativePath + * @property-read string $content + */ class Policy extends Entity { - public function __construct($title, $namespace, $file, $path, $relativePath, $content) - { + public function __construct( + string $title, + string $namespace, + string $file, + string $path, + string $relativePath, + string $content + ) { $this->setAttributes([ 'policy' => $title, 'namespace' => $namespace, diff --git a/src/Entities/Request.php b/src/Entities/Request.php index 66965b7..8abeec7 100644 --- a/src/Entities/Request.php +++ b/src/Entities/Request.php @@ -1,12 +1,27 @@ setAttributes([ 'request' => $title, 'domain' => $domain, diff --git a/src/Entities/Service.php b/src/Entities/Service.php index e45ddd7..dea7fa9 100644 --- a/src/Entities/Service.php +++ b/src/Entities/Service.php @@ -4,9 +4,15 @@ use Lucid\Str; +/** + * @property-read string $name + * @property-read string $slug + * @property-read string $realPath + * @property-read string $relativePath + */ class Service extends Entity { - public function __construct($name, $realPath, $relativePath) + public function __construct(string $name, string $realPath, string $relativePath) { $this->setAttributes([ 'name' => $name, @@ -15,13 +21,4 @@ public function __construct($name, $realPath, $relativePath) 'relativePath' => $relativePath, ]); } - - // public function toArray() - // { - // $attributes = parent::toArray(); - // - // unset($attributes['realPath']); - // - // return $attributes; - // } } diff --git a/src/Events/FeatureStarted.php b/src/Events/FeatureStarted.php index e51e86b..9be34fe 100644 --- a/src/Events/FeatureStarted.php +++ b/src/Events/FeatureStarted.php @@ -4,22 +4,11 @@ class FeatureStarted { - /** - * @var string - */ - public $name; + public string $name; - /** - * @var array - */ - public $arguments; + public array $arguments; - /** - * FeatureStarted constructor. - * @param string $name - * @param array $arguments - */ - public function __construct($name, array $arguments = []) + public function __construct(string $name, array $arguments = []) { $this->name = $name; $this->arguments = $arguments; diff --git a/src/Events/JobStarted.php b/src/Events/JobStarted.php index faa3e09..2828d37 100644 --- a/src/Events/JobStarted.php +++ b/src/Events/JobStarted.php @@ -4,22 +4,11 @@ class JobStarted { - /** - * @var string - */ - public $name; + public string $name; - /** - * @var array - */ - public $arguments; + public array $arguments; - /** - * JobStarted constructor. - * @param string $name - * @param array $arguments - */ - public function __construct($name, array $arguments = []) + public function __construct(string $name, array $arguments = []) { $this->name = $name; $this->arguments = $arguments; diff --git a/src/Events/OperationStarted.php b/src/Events/OperationStarted.php index 0c82c85..064cd2a 100644 --- a/src/Events/OperationStarted.php +++ b/src/Events/OperationStarted.php @@ -4,22 +4,11 @@ class OperationStarted { - /** - * @var string - */ - public $name; + public string $name; - /** - * @var array - */ - public $arguments; + public array $arguments; - /** - * OperationStarted constructor. - * @param string $name - * @param array $arguments - */ - public function __construct($name, array $arguments = []) + public function __construct(string $name, array $arguments = []) { $this->name = $name; $this->arguments = $arguments; diff --git a/src/Exceptions/InvalidInputException.php b/src/Exceptions/InvalidInputException.php index b5ad038..f6118ba 100644 --- a/src/Exceptions/InvalidInputException.php +++ b/src/Exceptions/InvalidInputException.php @@ -11,8 +11,11 @@ */ class InvalidInputException extends Exception { - public function __construct($message = '', $code = 0, Exception $previous = null) - { + public function __construct( + mixed $message = '', + int $code = 0, + Exception $previous = null + ) { if ($message instanceof IlluminateValidator) { $message = $message->messages()->all(); } diff --git a/src/Filesystem.php b/src/Filesystem.php index fb71830..41a80f9 100644 --- a/src/Filesystem.php +++ b/src/Filesystem.php @@ -8,26 +8,20 @@ trait Filesystem { /** * Determine if a file or directory exists. - * - * @param string $path - * - * @return bool */ - public function exists($path) + public function exists(string $path): bool { return file_exists($path); } /** * Create a file at the given path with the given contents. - * - * @param string $path - * @param string $contents - * - * @return bool */ - public function createFile($path, $contents = '', $lock = false) - { + public function createFile( + string $path, + string $contents = '', + bool $lock = false + ): bool { $this->createDirectory(dirname($path)); return file_put_contents($path, $contents, $lock ? LOCK_EX : 0); @@ -35,16 +29,13 @@ public function createFile($path, $contents = '', $lock = false) /** * Create a directory. - * - * @param string $path - * @param int $mode - * @param bool $recursive - * @param bool $force - * - * @return bool */ - public function createDirectory($path, $mode = 0755, $recursive = true, $force = true) - { + public function createDirectory( + string $path, + int $mode = 0755, + bool $recursive = true, + bool $force = true + ): bool { if ($force) { return @mkdir($path, $mode, $recursive); } @@ -54,19 +45,18 @@ public function createDirectory($path, $mode = 0755, $recursive = true, $force = /** * Delete an existing file or directory at the given path. - * - * @param string $path - * - * @return bool */ - public function delete($path) + public function delete(string $path): void { $filesystem = new SymfonyFilesystem(); $filesystem->remove($path); } - public function rename($path, $name) + /** + * Rename file at specified path. + */ + public function rename(string $path, string $name): void { $filesystem = new SymfonyFilesystem(); diff --git a/src/Finder.php b/src/Finder.php index cdd33a0..58103b6 100644 --- a/src/Finder.php +++ b/src/Finder.php @@ -3,127 +3,49 @@ namespace Lucid; use Exception; -use InvalidArgumentException; use Illuminate\Support\Collection; -use Lucid\Entities\Feature; -use Lucid\Entities\Service; +use InvalidArgumentException; use Lucid\Entities\Domain; +use Lucid\Entities\Feature; use Lucid\Entities\Job; +use Lucid\Entities\Service; use Symfony\Component\Finder\Finder as SymfonyFinder; -if (!defined('DS')) { +if (! defined('DS')) { define('DS', DIRECTORY_SEPARATOR); } trait Finder { - public function fuzzyFind($query) - { - $finder = new SymfonyFinder(); - - $files = $finder->in($this->findServicesRootPath().'/*/Features') // features - ->in($this->findDomainsRootPath().'/*/Jobs') // jobs - ->name('*.php') - ->files(); - - $matches = [ - 'jobs' => [], - 'features' => [], - ]; - - foreach ($files as $file) { - $base = $file->getBaseName(); - $name = str_replace(['.php', ' '], '', $base); - - $query = str_replace(' ', '', trim($query)); - - similar_text($query, mb_strtolower($name), $percent); - - if ($percent > 35) { - if (strpos($base, 'Feature.php')) { - $matches['features'][] = [$this->findFeature($name)->toArray(), $percent]; - } elseif (strpos($base, 'Job.php')) { - $matches['jobs'][] = [$this->findJob($name)->toArray(), $percent]; - } - } - } - - // sort the results by their similarity percentage - $this->sortFuzzyResults($matches['jobs']); - $this->sortFuzzyResults($matches['features']); - - $matches['features'] = $this->mapFuzzyResults($matches['features']); - $matches['jobs'] = array_map(function ($result) { - return $result[0]; - }, $matches['jobs']); - - return $matches; - } - - /** - * Sort the fuzzy-find results. - * - * @param array &$results - * - * @return bool - */ - private function sortFuzzyResults(&$results) - { - return usort($results, function ($resultLeft, $resultRight) { - return $resultLeft[1] < $resultRight[1]; - }); - } - - /** - * Map the fuzzy-find results into the data - * that should be returned. - * - * @param array $results - * - * @return array - */ - private function mapFuzzyResults($results) - { - return array_map(function ($result) { - return $result[0]; - }, $results); - } - /** * Get the source directory name. - * - * @return string */ - public function getSourceDirectoryName() + public function getSourceDirectoryName(): string { return 'app'; } /** * Determines whether this is a lucid microservice installation. - * - * @return bool */ - public function isMicroservice() + public function isMicroservice(): bool { - return !file_exists(base_path().DS.$this->getSourceDirectoryName().DS.'Services'); + return ! file_exists(base_path().DS.$this->getSourceDirectoryName().DS.'Services'); } /** * Get the namespace used for the application. * - * @return string - * * @throws Exception */ - public function findNamespace(string $dir) + public function findNamespace(string $dir): string { // read composer.json file contents to determine the namespace - $composer = json_decode(file_get_contents(base_path(). DS .'composer.json'), true); + $composer = json_decode(file_get_contents(base_path().DS.'composer.json'), true); // see which one refers to the "src/" directory foreach ($composer['autoload']['psr-4'] as $namespace => $directory) { - $directory = str_replace(['/', '\\'], DS, $directory); + $directory = str_replace(['/', '\\'], DS, $directory ?? ''); if ($directory === $dir.DS) { return trim($namespace, '\\'); } @@ -132,32 +54,18 @@ public function findNamespace(string $dir) throw new Exception('App namespace not set in composer.json'); } - public function findRootNamespace() - { - return $this->findNamespace($this->getSourceDirectoryName()); - } - - public function findAppNamespace() - { - return $this->findNamespace('app'); - } - /** - * Find the namespace of the foundation. - * - * @return string + * @throws Exception */ - public function findFoundationNamespace() + public function findRootNamespace(): string { - return 'Lucid\Foundation'; + return $this->findNamespace($this->getSourceDirectoryName()); } /** * Find the namespace of a unit. - * - * @return string */ - public function findUnitNamespace() + public function findUnitNamespace(): string { return 'Lucid\Units'; } @@ -165,121 +73,91 @@ public function findUnitNamespace() /** * Find the namespace for the given service name. * - * @param string $service - * - * @return string * @throws Exception */ - public function findServiceNamespace($service = null) + public function findServiceNamespace(?string $service = null): string { $root = $this->findRootNamespace(); - return (!$service) ? $root : "$root\\Services\\$service"; + return (! $service) ? $root : "$root\\Services\\$service"; } /** - * get the root of the source directory. - * - * @return string + * Get the root of the source directory. */ - public function findSourceRoot() + public function getSourceRoot(): string { return app_path(); } /** * Find the root path of all the services. - * - * @return string */ - public function findServicesRootPath() + public function findServicesRootPath(): string { - return $this->findSourceRoot(). DS .'Services'; + return $this->getSourceRoot().DS.'Services'; } /** * Find the path to the directory of the given service name. * In the case of a microservice service installation this will be app path. - * - * @param string $service - * - * @return string */ - public function findServicePath($service) + public function findServicePath(?string $service): string { - return (!$service) ? app_path() : $this->findServicesRootPath(). DS . $service; + return (! $service) + ? $this->getSourceRoot() + : $this->findServicesRootPath().DS.$service; } /** * Find the path to the directory of the given service name. * In the case of a microservice service installation this will be app path. - * - * @param string $service - * - * @return string */ - public function findMigrationPath($service) + public function findMigrationPath(?string $service): string { - return (!$service) ? - 'database/migrations' : - $this->relativeFromReal($this->findServicesRootPath(). DS . $service . "/database/migrations"); + return (! $service) + ? 'database/migrations' + : $this->relativeFromReal($this->findServicesRootPath().DS.$service.'/database/migrations'); } /** * Find the features root path in the given service. - * - * @param string $service - * - * @return string */ - public function findFeaturesRootPath($service) + public function findFeaturesRootPath(?string $service): string { - return $this->findServicePath($service). DS . 'Features'; + return $this->findServicePath($service).DS.'Features'; } /** * Find the file path for the given feature. - * - * @param string $service - * @param string $feature - * - * @return string */ - public function findFeaturePath($service, $feature) + public function findFeaturePath(string $service, string $feature): string { - return $this->findFeaturesRootPath($service). DS . "$feature.php"; + return $this->findFeaturesRootPath($service).DS."$feature.php"; } /** * Find the test file path for the given feature. - * - * @param string $service - * @param string $feature - * - * @return string */ - public function findFeatureTestPath($service, $test) + public function findFeatureTestPath(?string $service, string $test): string { $root = $this->findFeatureTestsRootPath(); if ($service) { - $root .= DS . 'Services'. DS . $service; + $root .= DS.'Services'.DS.$service; } - return join(DS, [$root, "$test.php"]); + return implode(DS, [$root, "$test.php"]); } /** * Find the namespace for features in the given service. * - * @param string $service - * - * @return string * @throws Exception */ - public function findFeatureNamespace($service, $feature) + public function findFeatureNamespace(?string $service, string $feature): string { - $dirs = join('\\', explode(DS, dirname($feature))); + $dirs = implode('\\', explode(DS, dirname($feature))); $base = $this->findServiceNamespace($service).'\\Features'; @@ -293,12 +171,8 @@ public function findFeatureNamespace($service, $feature) /** * Find the namespace for features tests in the given service. - * - * @param string $service - * - * @return string */ - public function findFeatureTestNamespace($service = null) + public function findFeatureTestNamespace(?string $service = null): string { $namespace = $this->findFeatureTestsRootNamespace(); @@ -311,57 +185,40 @@ public function findFeatureTestNamespace($service = null) /** * Find the operations root path in the given service. - * - * @param string $service - * - * @return string */ - public function findOperationsRootPath($service) + public function findOperationsRootPath(?string $service): string { - return $this->findServicePath($service). DS . 'Operations'; + return $this->findServicePath($service).DS.'Operations'; } /** * Find the file path for the given operation. - * - * @param string $service - * @param string $operation - * - * @return string */ - public function findOperationPath($service, $operation) + public function findOperationPath(?string $service, string $operation): string { - return $this->findOperationsRootPath($service). DS . "$operation.php"; + return $this->findOperationsRootPath($service).DS."$operation.php"; } /** * Find the test file path for the given operation. - * - * @param string $service - * @param string $operation - * - * @return string */ - public function findOperationTestPath($service, $test) + public function findOperationTestPath(?string $service, string $test): string { $root = $this->findUnitTestsRootPath(); if ($service) { - $root .= DS . 'Services'. DS . $service; + $root .= DS.'Services'.DS.$service; } - return join(DS, [$root, 'Operations', "$test.php"]); + return implode(DS, [$root, 'Operations', "$test.php"]); } /** * Find the namespace for operations in the given service. * - * @param string $service - * - * @return string * @throws Exception */ - public function findOperationNamespace($service) + public function findOperationNamespace(?string $service): string { return $this->findServiceNamespace($service).'\\Operations'; } @@ -369,12 +226,9 @@ public function findOperationNamespace($service) /** * Find the namespace for operations tests in the given service. * - * @param string $service - * - * @return string * @throws Exception */ - public function findOperationTestNamespace($service = null) + public function findOperationTestNamespace(?string $service = null): string { $namespace = $this->findUnitTestsRootNamespace(); @@ -382,37 +236,31 @@ public function findOperationTestNamespace($service = null) $namespace .= "\\Services\\$service"; } - return $namespace . '\\Operations'; + return $namespace.'\\Operations'; } /** * Find the root path of domains. - * - * @return string */ - public function findDomainsRootPath() + public function findDomainsRootPath(): string { - return $this->findSourceRoot(). DS .'Domains'; + return $this->getSourceRoot().DS.'Domains'; } /** * Find the path for the given domain. - * - * @param string $domain - * - * @return string */ - public function findDomainPath($domain) + public function findDomainPath(string $domain): string { - return $this->findDomainsRootPath(). DS . $domain; + return $this->findDomainsRootPath().DS.$domain; } /** * Get the list of domains. * - * @return Collection; + * @throws Exception */ - public function listDomains() + public function listDomains(): Collection { $finder = new SymfonyFinder(); $directories = $finder @@ -441,11 +289,9 @@ public function listDomains() * List the jobs per domain, * optionally provide a domain name to list its jobs. * - * @param string $domainName - * - * @return Collection + * @throws Exception */ - public function listJobs($domainName = null) + public function listJobs(?string $domainName = null): Collection { $domains = ($domainName) ? [$this->findDomain(Str::domain($domainName))] : $this->listDomains(); @@ -456,9 +302,10 @@ public function listJobs($domainName = null) $finder = new SymfonyFinder(); $files = $finder ->name('*Job.php') - ->in($path. DS .'Jobs') + ->in($path.DS.'Jobs') ->files(); + /** @phpstan-ignore-next-line */ $jobs[$domain->name] = new Collection(); foreach ($files as $file) { @@ -473,6 +320,7 @@ public function listJobs($domainName = null) file_get_contents($file->getRealPath()) ); + /** @phpstan-ignore-next-line */ $jobs[$domain->name]->push($job); } } @@ -482,13 +330,8 @@ public function listJobs($domainName = null) /** * Find the path for the given job name. - * - * @param string$domain - * @param string$job - * - * @return string */ - public function findJobPath($domain, $job) + public function findJobPath(string $domain, string $job): string { return $this->findDomainPath($domain).DS.'Jobs'.DS.$job.'.php'; } @@ -496,12 +339,9 @@ public function findJobPath($domain, $job) /** * Find the namespace for the given domain. * - * @param string $domain - * - * @return string * @throws Exception */ - public function findDomainNamespace($domain) + public function findDomainNamespace(string $domain): string { return $this->findRootNamespace().'\\Domains\\'.$domain; } @@ -509,12 +349,9 @@ public function findDomainNamespace($domain) /** * Find the namespace for the given domain's Jobs. * - * @param string $domain - * - * @return string * @throws Exception */ - public function findDomainJobsNamespace($domain) + public function findDomainJobsNamespace(string $domain): string { return $this->findDomainNamespace($domain).'\Jobs'; } @@ -522,72 +359,51 @@ public function findDomainJobsNamespace($domain) /** * Find the namespace for the given domain's Jobs. * - * @param string $domain - * - * @return string * @throws Exception */ - public function findDomainJobsTestsNamespace($domain) + public function findDomainJobsTestsNamespace(string $domain): string { - return $this->findUnitTestsRootNamespace() . "\\Domains\\$domain\\Jobs"; + return $this->findUnitTestsRootNamespace()."\\Domains\\$domain\\Jobs"; } /** * Get the path to the tests of the given domain. - * - * @param string $domain - * - * @return string */ - public function findDomainTestsPath($domain) + public function findDomainTestsPath(string $domain): string { - return $this->findUnitTestsRootPath() . DS . 'Domains' . DS . $domain; + return $this->findUnitTestsRootPath().DS.'Domains'.DS.$domain; } /** * Find the test path for the given job. - * - * @param string $domain - * @param string $jobTest - * - * @return string */ - public function findJobTestPath($domain, $jobTest) + public function findJobTestPath(string $domain, string $jobTest): string { - return $this->findDomainTestsPath($domain) . DS . 'Jobs' . DS . "$jobTest.php"; + return $this->findDomainTestsPath($domain).DS.'Jobs'.DS."$jobTest.php"; } /** * Find the path for the give controller class. - * - * @param string $service - * @param string $controller - * - * @return string */ - public function findControllerPath($service, $controller) + public function findControllerPath(?string $service, string $controller): string { - return $this->findServicePath($service).DS.join(DS, ['Http', 'Controllers', "$controller.php"]); + return $this->findServicePath($service).DS.implode(DS, ['Http', 'Controllers', "$controller.php"]); } /** * Find the namespace of controllers in the given service. * - * @param string $service - * - * @return string + * @throws Exception */ - public function findControllerNamespace($service) + public function findControllerNamespace(?string $service): string { return $this->findServiceNamespace($service).'\\Http\\Controllers'; } /** * Get the list of services. - * - * @return Collection */ - public function listServices() + public function listServices(): Collection { $services = new Collection(); @@ -606,40 +422,31 @@ public function listServices() /** * Find the service for the given service name. * - * @param string $service - * - * @return Service * @throws Exception */ - public function findService($service) + public function findService(string $service): Service { $finder = new SymfonyFinder(); $dirs = $finder->name($service)->in($this->findServicesRootPath())->directories(); - if ($dirs->count() < 1) { - throw new Exception('Service "'.$service.'" could not be found.'); - } foreach ($dirs as $dir) { $path = $dir->getRealPath(); - return new Service(Str::service($service), $path, $this->relativeFromReal($path)); + return new Service(Str::service($service), $path, $this->relativeFromReal($path)); } + + throw new Exception('Service "'.$service.'" could not be found.'); } /** * Find the domain for the given domain name. * - * @param string $domain - * - * @return Domain + * @throws Exception */ - public function findDomain($domain) + public function findDomain(string $domain): Domain { $finder = new SymfonyFinder(); $dirs = $finder->name($domain)->in($this->findDomainsRootPath())->directories(); - if ($dirs->count() < 1) { - throw new Exception('Domain "'.$domain.'" could not be found.'); - } foreach ($dirs as $dir) { $path = $dir->getRealPath(); @@ -651,16 +458,16 @@ public function findDomain($domain) $this->relativeFromReal($path) ); } + + throw new Exception('Domain "'.$domain.'" could not be found.'); } /** * Find the feature for the given feature name. * - * @param string $name - * - * @return Feature + * @throws Exception */ - public function findFeature($name) + public function findFeature(string $name): Feature { $name = Str::feature($name); $fileName = "$name.php"; @@ -682,16 +489,16 @@ public function findFeature($name) $content ); } + + throw new Exception('Feature "'.$name.'" could not be found.'); } /** * Find the feature for the given feature name. * - * @param string $name - * - * @return Job + * @throws Exception */ - public function findJob($name) + public function findJob(string $name): Job { $name = Str::job($name); $fileName = "$name.php"; @@ -714,23 +521,23 @@ public function findJob($name) $content ); } + + throw new Exception('Job "'.$name.'" could not be found.'); } /** * Get the list of features, * optionally withing a specified service. * - * @param string $serviceName - * - * @return array of Feature + * @return array * * @throws Exception */ - public function listFeatures($serviceName = '') + public function listFeatures(?string $serviceName = ''): array { $services = $this->listServices(); - if (!empty($serviceName)) { + if (! empty($serviceName)) { $services = $services->filter(function ($service) use ($serviceName) { return $service->name === $serviceName || $service->slug === $serviceName; }); @@ -766,70 +573,50 @@ public function listFeatures($serviceName = '') /** * Get the path to the passed model. - * - * @param string $model - * - * @return string */ - public function findModelPath($model) + public function findModelPath(string $model): string { - return $this->getSourceDirectoryName(). DS .'Data'. DS . 'Models' . DS . "$model.php"; + return $this->getSourceDirectoryName().DS.'Data'.DS.'Models'.DS."$model.php"; } /** * Get the path to the policies directory. - * - * @return string */ - public function findPoliciesPath() + public function findPoliciesPath(): string { return $this->getSourceDirectoryName().DS.'Policies'; } /** * Get the path to the passed policy. - * - * @param string $policy - * - * @return string */ - public function findPolicyPath($policy) + public function findPolicyPath(string $policy): string { return $this->findPoliciesPath().DS.$policy.'.php'; } /** * Get the path to the request directory of a specific service. - * - * @param string $domain - * - * @return string */ - public function findRequestsPath($domain) + public function findRequestsPath(string $domain): string { - return $this->findDomainPath($domain). DS . 'Requests'; + return $this->findDomainPath($domain).DS.'Requests'; } /** * Get the path to a specific request. - * - * @param string $domain - * @param string $request - * - * @return string */ - public function findRequestPath($domain, $request) + public function findRequestPath(string $domain, string $request): string { - return $this->findRequestsPath($domain) . DS . $request.'.php'; + return $this->findRequestsPath($domain).DS.$request.'.php'; } /** * Get the namespace for the Models. * - * @return string * @throws Exception */ - public function findModelNamespace() + public function findModelNamespace(): string { return $this->findRootNamespace().'\\Data\\Models'; } @@ -837,10 +624,9 @@ public function findModelNamespace() /** * Get the namespace for Policies. * - * @return mixed * @throws Exception */ - public function findPolicyNamespace() + public function findPolicyNamespace(): string { return $this->findRootNamespace().'\\Policies'; } @@ -848,27 +634,19 @@ public function findPolicyNamespace() /** * Get the requests namespace for the service passed in. * - * @param string $domain - * - * @return string * @throws Exception */ - public function findRequestsNamespace($domain) + public function findRequestsNamespace(string $domain): string { return $this->findDomainNamespace($domain).'\\Requests'; } /** * Get the relative version of the given real path. - * - * @param string $path - * @param string $needle - * - * @return string */ - protected function relativeFromReal($path, $needle = '') + protected function relativeFromReal(string $path, string $needle = ''): string { - if (!$needle) { + if ($needle === '') { $needle = $this->getSourceDirectoryName().DS; } @@ -877,57 +655,48 @@ protected function relativeFromReal($path, $needle = '') /** * Get the path to the Composer.json file. - * - * @return string */ - protected function getComposerPath() + protected function getComposerPath(): string { return app()->basePath().DS.'composer.json'; } /** * Get the path to the given configuration file. - * - * @param string $name - * - * @return string */ - protected function getConfigPath($name) + protected function getConfigPath(string $name): string { - return app()['path.config']. DS ."$name.php"; + return app()['path.config'].DS."$name.php"; } /** * Get the root path to unit tests directory. - * - * @return string */ - protected function findUnitTestsRootPath() + protected function findUnitTestsRootPath(): string { - return base_path(). DS . 'tests' . DS . 'Unit'; + return base_path().DS.'tests'.DS.'Unit'; } /** * Get the root path to feature tests directory. - * - * @return string */ - protected function findFeatureTestsRootPath() + protected function findFeatureTestsRootPath(): string { - return base_path(). DS . 'tests' . DS . 'Feature'; + return base_path().DS.'tests'.DS.'Feature'; } /** * Get the root namespace for unit tests - * - * @return string */ - protected function findUnitTestsRootNamespace() + protected function findUnitTestsRootNamespace(): string { return 'Tests\\Unit'; } - protected function findFeatureTestsRootNamespace() + /** + * Get the root namespace for feature tests + */ + protected function findFeatureTestsRootNamespace(): string { return 'Tests\\Feature'; } diff --git a/src/Generators/ControllerGenerator.php b/src/Generators/ControllerGenerator.php index 83f9ccd..03b8f83 100644 --- a/src/Generators/ControllerGenerator.php +++ b/src/Generators/ControllerGenerator.php @@ -7,8 +7,14 @@ class ControllerGenerator extends Generator { - public function generate($name, $service, $resource = false) - { + /** + * @throws Exception + */ + public function generate( + string $name, + ?string $service, + bool $resource = false + ): string { $name = Str::controller($name); $service = Str::service($service); @@ -16,18 +22,16 @@ public function generate($name, $service, $resource = false) if ($this->exists($path)) { throw new Exception('Controller already exists!'); - - return false; } $namespace = $this->findControllerNamespace($service); $content = file_get_contents($this->getStub($resource)); $content = str_replace( - ['{{controller}}', '{{namespace}}', '{{unit_namespace}}'], - [$name, $namespace, $this->findUnitNamespace()], - $content - ); + ['{{controller}}', '{{namespace}}', '{{unit_namespace}}'], + [$name, $namespace, $this->findUnitNamespace()], + $content ?: '' + ); $this->createFile($path, $content); @@ -37,15 +41,14 @@ public function generate($name, $service, $resource = false) /** * Get the stub file for the generator. * - * @param $resource Determines whether to return the resource controller - * @return string + * $resource - Determines whether to return the resource controller */ - protected function getStub($resource) + protected function getStub(bool $resource): string { if ($resource) { - return __DIR__ . '/stubs/controller.resource.stub'; + return __DIR__.'/stubs/controller.resource.stub'; } - return __DIR__ . '/stubs/controller.plain.stub'; + return __DIR__.'/stubs/controller.plain.stub'; } } diff --git a/src/Generators/DirectoriesGeneratorTrait.php b/src/Generators/DirectoriesGeneratorTrait.php index 4db72e4..9b5538d 100644 --- a/src/Generators/DirectoriesGeneratorTrait.php +++ b/src/Generators/DirectoriesGeneratorTrait.php @@ -10,10 +10,7 @@ */ trait DirectoriesGeneratorTrait { - /** - * @return array - */ - private function generateDirectories() + private function generateDirectories(): array { $root = base_path(); diff --git a/src/Generators/FeatureGenerator.php b/src/Generators/FeatureGenerator.php index 0b72352..e875de2 100644 --- a/src/Generators/FeatureGenerator.php +++ b/src/Generators/FeatureGenerator.php @@ -3,12 +3,15 @@ namespace Lucid\Generators; use Exception; -use Lucid\Str; use Lucid\Entities\Feature; +use Lucid\Str; class FeatureGenerator extends Generator { - public function generate($feature, $service, array $jobs = []) + /** + * @throws Exception + */ + public function generate(string $feature, ?string $service, array $jobs = []): Feature { $feature = Str::feature($feature); $service = Str::service($service); @@ -18,8 +21,6 @@ public function generate($feature, $service, array $jobs = []) if ($this->exists($path)) { throw new Exception('Feature already exists!'); - - return false; } $namespace = $this->findFeatureNamespace($service, $feature); @@ -42,7 +43,7 @@ public function generate($feature, $service, array $jobs = []) $content = str_replace( ['{{feature}}', '{{namespace}}', '{{unit_namespace}}', '{{use_jobs}}', '{{run_jobs}}'], [$classname, $namespace, $this->findUnitNamespace(), $useJobs, $runJobs], - $content + $content ?: '' ); $this->createFile($path, $content); @@ -60,7 +61,7 @@ public function generate($feature, $service, array $jobs = []) ); } - private function classname($feature) + private function classname(string $feature): string { $parts = explode(DS, $feature); @@ -70,46 +71,41 @@ private function classname($feature) /** * Generate the test file. * - * @param string $feature - * @param string $service + * @throws Exception */ - private function generateTestFile($feature, $service) + private function generateTestFile(string $feature, ?string $service) { - $content = file_get_contents($this->getTestStub()); + $content = file_get_contents($this->getTestStub()); - $namespace = $this->findFeatureTestNamespace($service); - $featureClass = $this->classname($feature); - $featureNamespace = $this->findFeatureNamespace($service, $feature)."\\".$featureClass; + $namespace = $this->findFeatureTestNamespace($service); + $featureClass = $this->classname($feature); + $featureNamespace = $this->findFeatureNamespace($service, $feature).'\\'.$featureClass; $testClass = $featureClass.'Test'; - $content = str_replace( - ['{{namespace}}', '{{testclass}}', '{{feature}}', '{{feature_namespace}}'], - [$namespace, $testClass, Str::snake(str_replace(DS, '', $feature)), $featureNamespace], - $content - ); + $content = str_replace( + ['{{namespace}}', '{{testclass}}', '{{feature}}', '{{feature_namespace}}'], + [$namespace, $testClass, Str::snake(str_replace(DS, '', $feature)), $featureNamespace], + $content ?: '' + ); - $path = $this->findFeatureTestPath($service, $feature.'Test'); + $path = $this->findFeatureTestPath($service, $feature.'Test'); - $this->createFile($path, $content); + $this->createFile($path, $content); } /** * Get the stub file for the generator. - * - * @return string */ - protected function getStub() + protected function getStub(): string { - return __DIR__ . '/stubs/feature.stub'; + return __DIR__.'/stubs/feature.stub'; } /** * Get the test stub file for the generator. - * - * @return string */ - private function getTestStub() + private function getTestStub(): string { - return __DIR__ . '/stubs/feature-test.stub'; + return __DIR__.'/stubs/feature-test.stub'; } } diff --git a/src/Generators/Generator.php b/src/Generators/Generator.php index 74d37b6..8882fee 100644 --- a/src/Generators/Generator.php +++ b/src/Generators/Generator.php @@ -2,28 +2,11 @@ namespace Lucid\Generators; -use Lucid\Finder; use Lucid\Filesystem; +use Lucid\Finder; class Generator { use Finder; use Filesystem; - - /** - * The current Laravel framework version - * as defined in Foundation\Application::VERSION - * - * @param bool $majorOnly determines whether the needed version is only the major one - * @return string - */ - public function laravelVersion($majorOnly = true) - { - $version = app()->version(); - if ($majorOnly) { - $version = explode('.', $version)[0]; - } - - return $version; - } } diff --git a/src/Generators/JobGenerator.php b/src/Generators/JobGenerator.php index bf5f177..8b5a91f 100644 --- a/src/Generators/JobGenerator.php +++ b/src/Generators/JobGenerator.php @@ -3,12 +3,15 @@ namespace Lucid\Generators; use Exception; -use Lucid\Str; use Lucid\Entities\Job; +use Lucid\Str; class JobGenerator extends Generator { - public function generate($job, $domain, $isQueueable = false) + /** + * @throws Exception + */ + public function generate(string $job, string $domain, bool $isQueueable = false): Job { $job = Str::job($job); $domain = Str::domain($domain); @@ -28,7 +31,7 @@ public function generate($job, $domain, $isQueueable = false) $content = str_replace( ['{{job}}', '{{namespace}}', '{{unit_namespace}}'], [$job, $namespace, $this->findUnitNamespace()], - $content + $content ?: '' ); $this->createFile($path, $content); @@ -49,10 +52,9 @@ public function generate($job, $domain, $isQueueable = false) /** * Generate test file. * - * @param string $job - * @param string $domain + * @throws Exception */ - private function generateTestFile($job, $domain) + private function generateTestFile(string $job, string $domain): void { $content = file_get_contents($this->getTestStub()); @@ -63,7 +65,7 @@ private function generateTestFile($job, $domain) $content = str_replace( ['{{namespace}}', '{{testclass}}', '{{job}}', '{{job_namespace}}'], [$namespace, $testClass, Str::snake($job), $jobNamespace], - $content + $content ?: '' ); $path = $this->findJobTestPath($domain, $testClass); @@ -73,10 +75,8 @@ private function generateTestFile($job, $domain) /** * Create domain directory. - * - * @param string $domain */ - private function createDomainDirectory($domain) + private function createDomainDirectory(string $domain) { $this->createDirectory($this->findDomainPath($domain).'/Jobs'); $this->createDirectory($this->findDomainTestsPath($domain).'/Jobs'); @@ -84,27 +84,21 @@ private function createDomainDirectory($domain) /** * Get the stub file for the generator. - * - * @return string */ - public function getStub($isQueueable = false) + public function getStub(bool $isQueueable = false): string { - $stubName; if ($isQueueable) { - $stubName = '/stubs/job-queueable.stub'; + return __DIR__.'/stubs/job-queueable.stub'; } else { - $stubName = '/stubs/job.stub'; + return __DIR__.'/stubs/job.stub'; } - return __DIR__.$stubName; } /** * Get the test stub file for the generator. - * - * @return string */ - public function getTestStub() + public function getTestStub(): string { - return __DIR__ . '/stubs/job-test.stub'; + return __DIR__.'/stubs/job-test.stub'; } } diff --git a/src/Generators/MicroGenerator.php b/src/Generators/MicroGenerator.php index 16adf73..ea8623a 100644 --- a/src/Generators/MicroGenerator.php +++ b/src/Generators/MicroGenerator.php @@ -2,8 +2,8 @@ namespace Lucid\Generators; -use DOMXPath; use DOMDocument; +use DOMXPath; use Lucid\Generators\Generator as GeneratorAlias; class MicroGenerator extends GeneratorAlias @@ -12,10 +12,8 @@ class MicroGenerator extends GeneratorAlias /** * The directories to be created. - * - * @var array */ - private $directories = [ + private array $directories = [ 'app' => [ 'Data', 'Domains', @@ -26,19 +24,18 @@ class MicroGenerator extends GeneratorAlias 'tests' => [ 'Domains', 'Operations', - ] + ], ]; /** * Generate initial directory structure. - * - * @return array */ - public function generate() + public function generate(): array { - $created = $this->generateDirectories(); - - $created = array_merge($created, $this->generateCustomDirectories()); + $created = array_merge( + $this->generateDirectories(), + $this->generateCustomDirectories() + ); $this->updatePHPUnitXML(); @@ -76,7 +73,7 @@ private function updatePHPUnitXML() } } - private function testsuites() + private function testsuites(): string { return << @@ -90,25 +87,21 @@ private function testsuites() \t XMLSUITE; - } - /** - * @return array - */ - private function generateCustomDirectories() + private function generateCustomDirectories(): array { $root = base_path(); - $created = []; - // rename or create tests/Features directory if ($this->exists("$root/tests/Feature")) { - $this->rename("$root/tests/Feature", "$root/tests/Features"); - } else { + $this->delete("$root/tests/Feature"); + } + + if (! $this->exists("$root/tests/Features")) { $this->createDirectory("$root/tests/Features"); $created[] = 'tests/Features'; } - return $created; + return $created ?? []; } } diff --git a/src/Generators/ModelGenerator.php b/src/Generators/ModelGenerator.php index 30a9aa6..fc4040c 100644 --- a/src/Generators/ModelGenerator.php +++ b/src/Generators/ModelGenerator.php @@ -3,27 +3,23 @@ namespace Lucid\Generators; use Exception; -use Lucid\Str; use Lucid\Entities\Model; +use Lucid\Str; class ModelGenerator extends Generator { /** * Generate the file. * - * @param $name - * @return Model|bool * @throws Exception */ - public function generate($name) + public function generate(string $name): Model { $model = Str::model($name); $path = $this->findModelPath($model); if ($this->exists($path)) { throw new Exception('Model already exists'); - - return false; } $namespace = $this->findModelNamespace(); @@ -32,7 +28,7 @@ public function generate($name) $content = str_replace( ['{{model}}', '{{namespace}}', '{{unit_namespace}}'], [$model, $namespace, $this->findUnitNamespace()], - $content + $content ?: '' ); $this->createFile($path, $content); @@ -49,15 +45,9 @@ public function generate($name) /** * Get the stub file for the generator. - * - * @return string */ - public function getStub() + public function getStub(): string { - if ($this->laravelVersion() > 7) { - return __DIR__ . '/../Generators/stubs/model-8.stub'; - } - - return __DIR__ . '/../Generators/stubs/model.stub'; + return __DIR__.'/../Generators/stubs/model-8.stub'; } } diff --git a/src/Generators/MonolithGenerator.php b/src/Generators/MonolithGenerator.php index 4f94d2b..d6c7358 100644 --- a/src/Generators/MonolithGenerator.php +++ b/src/Generators/MonolithGenerator.php @@ -6,7 +6,7 @@ class MonolithGenerator extends Generator { use DirectoriesGeneratorTrait; - private $directories = [ + private array $directories = [ 'app' => [ 'Data', 'Domains', @@ -14,10 +14,10 @@ class MonolithGenerator extends Generator 'Foundation', 'Policies', 'Data/Models', - ] + ], ]; - public function generate() + public function generate(): array { return $this->generateDirectories(); } diff --git a/src/Generators/OperationGenerator.php b/src/Generators/OperationGenerator.php index 5ced465..b6c3086 100644 --- a/src/Generators/OperationGenerator.php +++ b/src/Generators/OperationGenerator.php @@ -3,13 +3,20 @@ namespace Lucid\Generators; use Exception; -use Lucid\Str; use Lucid\Entities\Operation; +use Lucid\Str; class OperationGenerator extends Generator { - public function generate($operation, $service, $isQueueable = false, array $jobs = []) - { + /** + * @throws Exception + */ + public function generate( + string $operation, + ?string $service, + bool $isQueueable = false, + array $jobs = [] + ): Operation { $operation = Str::operation($operation); $service = Str::service($service); @@ -17,20 +24,18 @@ public function generate($operation, $service, $isQueueable = false, array $jobs if ($this->exists($path)) { throw new Exception('Operation already exists!'); - - return false; } $namespace = $this->findOperationNamespace($service); $content = file_get_contents($this->getStub($isQueueable)); - list($useJobs, $runJobs) = self::getUsesAndRunners($jobs); + [$useJobs, $runJobs] = self::getUsesAndRunners($jobs); $content = str_replace( ['{{operation}}', '{{namespace}}', '{{unit_namespace}}', '{{use_jobs}}', '{{run_jobs}}'], [$operation, $namespace, $this->findUnitNamespace(), $useJobs, $runJobs], - $content + $content ?: '' ); $this->createFile($path, $content); @@ -51,10 +56,9 @@ public function generate($operation, $service, $isQueueable = false, array $jobs /** * Generate the test file. * - * @param string $operation - * @param string $service + * @throws Exception */ - private function generateTestFile($operation, $service) + private function generateTestFile(string $operation, ?string $service): void { $content = file_get_contents($this->getTestStub()); @@ -65,7 +69,7 @@ private function generateTestFile($operation, $service) $content = str_replace( ['{{namespace}}', '{{testclass}}', '{{operation}}', '{{operation_namespace}}'], [$namespace, $testClass, Str::snake($operation), $operationNamespace], - $content + $content ?: '' ); $path = $this->findOperationTestPath($service, $testClass); @@ -75,59 +79,48 @@ private function generateTestFile($operation, $service) /** * Get the stub file for the generator. - * - * @return string */ - protected function getStub($isQueueable = false) + protected function getStub(bool $isQueueable = false): string { - $stubName; if ($isQueueable) { - $stubName = '/stubs/operation-queueable.stub'; + return __DIR__.'/stubs/operation-queueable.stub'; } else { - $stubName = '/stubs/operation.stub'; + return __DIR__.'/stubs/operation.stub'; } - return __DIR__.$stubName; } /** * Get the test stub file for the generator. - * - * @return string */ - private function getTestStub() + private function getTestStub(): string { - return __DIR__ . '/stubs/operation-test.stub'; + return __DIR__.'/stubs/operation-test.stub'; } /** * Get de use to import the right class * Get de job run command - * @param $job - * @return array */ - static private function getUseAndJobRunCommand($job) + private static function getUseAndJobRunCommand(string $job): array { - $str = str_replace_last('\\','#', $job); + $str = Str::replaceLast('\\', '#', $job); $explode = explode('#', $str); $use = 'use '.$explode[0].'\\'.$explode['1'].";\n"; $runJobs = "\t\t".'$this->run('.$explode['1'].'::class);'; - return array($use, $runJobs); + return [$use, $runJobs]; } /** * Returns all users and all $this->run() generated - * @param $jobs - * @return array */ - static private function getUsesAndRunners($jobs) + private static function getUsesAndRunners(array $jobs): array { $useJobs = ''; $runJobs = ''; foreach ($jobs as $index => $job) { - - list($useLine, $runLine) = self::getUseAndJobRunCommand($job); + [$useLine, $runLine] = self::getUseAndJobRunCommand($job); $useJobs .= $useLine; $runJobs .= $runLine; // only add carriage returns when it's not the last job @@ -135,8 +128,7 @@ static private function getUsesAndRunners($jobs) $runJobs .= "\n\n"; } } - return array($useJobs, $runJobs); - } - + return [$useJobs, $runJobs]; + } } diff --git a/src/Generators/PolicyGenerator.php b/src/Generators/PolicyGenerator.php index 743fc32..ded26fe 100644 --- a/src/Generators/PolicyGenerator.php +++ b/src/Generators/PolicyGenerator.php @@ -1,30 +1,25 @@ findPolicyPath($policy); if ($this->exists($path)) { throw new Exception('Policy already exists'); - - return false; } $this->createPolicyDirectory(); @@ -35,7 +30,7 @@ public function generate($name) $content = str_replace( ['{{policy}}', '{{namespace}}'], [$policy, $namespace], - $content + $content ?: '' ); $this->createFile($path, $content); @@ -53,18 +48,16 @@ public function generate($name) /** * Create Policies directory. */ - public function createPolicyDirectory() + public function createPolicyDirectory(): void { $this->createDirectory($this->findPoliciesPath()); } /** * Get the stub file for the generator. - * - * @return string */ - public function getStub() + public function getStub(): string { - return __DIR__ . '/../Generators/stubs/policy.stub'; + return __DIR__.'/../Generators/stubs/policy.stub'; } } diff --git a/src/Generators/RequestGenerator.php b/src/Generators/RequestGenerator.php index 3355a17..5811d28 100644 --- a/src/Generators/RequestGenerator.php +++ b/src/Generators/RequestGenerator.php @@ -1,24 +1,19 @@ createFile($path, $content); @@ -53,11 +48,9 @@ public function generate($name, $domain) /** * Get the stub file for the generator. - * - * @return string */ - public function getStub() + public function getStub(): string { - return __DIR__ . '/../Generators/stubs/request.stub'; + return __DIR__.'/../Generators/stubs/request.stub'; } } diff --git a/src/Generators/ServiceGenerator.php b/src/Generators/ServiceGenerator.php index e0c6597..6be8f36 100644 --- a/src/Generators/ServiceGenerator.php +++ b/src/Generators/ServiceGenerator.php @@ -8,12 +8,7 @@ class ServiceGenerator extends Generator { - /** - * The directories to be created under the service directory. - * - * @var array - */ - protected $directories = [ + protected array $directories = [ 'Console/', 'database/', 'database/factories/', @@ -34,7 +29,12 @@ class ServiceGenerator extends Generator 'Tests/Operations/', ]; - public function generate($name) + /** + * Add the corresponding service provider for the created service. + * + * @throws Exception + */ + public function generate(string $name): Service { $name = Str::service($name); $slug = Str::snake($name); @@ -42,8 +42,6 @@ public function generate($name) if ($this->exists($path)) { throw new Exception('Service already exists!'); - - return false; } // create service directory @@ -61,7 +59,6 @@ public function generate($name) return new Service( $name, - $slug, $path, $this->relativeFromReal($path) ); @@ -69,12 +66,8 @@ public function generate($name) /** * Create the default directories at the given service path. - * - * @param string $path - * - * @return void */ - public function createServiceDirectories($path) + public function createServiceDirectories(string $path): void { foreach ($this->directories as $directory) { $this->createDirectory($path.'/'.$directory); @@ -85,13 +78,13 @@ public function createServiceDirectories($path) /** * Add the corresponding service provider for the created service. * - * @param string $name - * @param string $path - * - * @return bool + * @throws Exception */ - public function addServiceProviders($name, $slug, $path) - { + public function addServiceProviders( + string $name, + string $slug, + string $path + ): void { $namespace = $this->findServiceNamespace($name).'\\Providers'; $this->createRegistrationServiceProvider($name, $path, $slug, $namespace); @@ -103,15 +96,14 @@ public function addServiceProviders($name, $slug, $path) /** * Create the service provider that registers broadcast channels. - * - * @param $name - * @param $path - * @param $slug - * @param $namespace */ - public function createBroadcastServiceProvider($name, $path, $slug, $namespace) - { - $content = file_get_contents(__DIR__ . "/stubs/broadcastserviceprovider.stub"); + public function createBroadcastServiceProvider( + string $name, + string $path, + string $slug, + string $namespace + ): void { + $content = file_get_contents(__DIR__.'/stubs/broadcastserviceprovider.stub'); $content = str_replace( ['{{name}}', '{{slug}}', '{{namespace}}'], [$name, $slug, $namespace], @@ -123,18 +115,14 @@ public function createBroadcastServiceProvider($name, $path, $slug, $namespace) /** * Create the service provider that registers this service. - * - * @param string $name - * @param string $path */ - public function createRegistrationServiceProvider($name, $path, $slug, $namespace) - { - $stub = 'serviceprovider.stub'; - if ((int) $this->laravelVersion() > 7) { - $stub = 'serviceprovider-8.stub'; - } - - $content = file_get_contents(__DIR__ . "/stubs/$stub"); + public function createRegistrationServiceProvider( + string $name, + string $path, + string $slug, + string $namespace + ): void { + $content = file_get_contents(__DIR__.'/stubs/serviceprovider.stub'); $content = str_replace( ['{{name}}', '{{slug}}', '{{namespace}}'], [$name, $slug, $namespace], @@ -147,18 +135,19 @@ public function createRegistrationServiceProvider($name, $path, $slug, $namespac /** * Create the routes service provider file. * - * @param string $name - * @param string $path - * @param string $slug - * @param string $namespace + * @throws Exception */ - public function createRouteServiceProvider($name, $path, $slug, $namespace) - { + public function createRouteServiceProvider( + string $name, + string $path, + string $slug, + string $namespace + ): void { $serviceNamespace = $this->findServiceNamespace($name); $controllers = $serviceNamespace.'\Http\Controllers'; $foundation = $this->findUnitNamespace(); - $content = file_get_contents(__DIR__ . '/stubs/routeserviceprovider.stub'); + $content = file_get_contents(__DIR__.'/stubs/routeserviceprovider.stub'); $content = str_replace( ['{{name}}', '{{namespace}}', '{{controllers_namespace}}', '{{unit_namespace}}'], [$name, $namespace, $controllers, $foundation], @@ -168,57 +157,51 @@ public function createRouteServiceProvider($name, $path, $slug, $namespace) $this->createFile($path.'/Providers/RouteServiceProvider.php', $content); } - /** + /** * Add the routes files. * - * @param string $name - * @param string $slug - * @param string $path + * @throws Exception */ - public function addRoutesFiles($name, $slug, $path) + public function addRoutesFiles(string $name, string $slug, string $path): void { - $controllers = 'src/Services/' . $name . '/Http/Controllers'; + $controllers = 'src/Services/'.$name.'/Http/Controllers'; - $api = file_get_contents(__DIR__ . '/stubs/routes-api.stub'); + $api = file_get_contents(__DIR__.'/stubs/routes-api.stub'); $api = str_replace(['{{slug}}', '{{controllers_path}}'], [$slug, $controllers], $api); - $web = file_get_contents(__DIR__ . '/stubs/routes-web.stub'); + $web = file_get_contents(__DIR__.'/stubs/routes-web.stub'); $web = str_replace(['{{slug}}', '{{controllers_path}}'], [$slug, $controllers], $web); - $channels = file_get_contents(__DIR__ . '/stubs/routes-channels.stub'); + $channels = file_get_contents(__DIR__.'/stubs/routes-channels.stub'); $channels = str_replace(['{{namespace}}'], [$this->findServiceNamespace($name)], $channels); - $console = file_get_contents(__DIR__ . '/stubs/routes-console.stub'); + $console = file_get_contents(__DIR__.'/stubs/routes-console.stub'); - $this->createFile($path . '/routes/api.php', $api); - $this->createFile($path . '/routes/web.php', $web); - $this->createFile($path . '/routes/channels.php', $channels); - $this->createFile($path . '/routes/console.php', $console); + $this->createFile($path.'/routes/api.php', $api); + $this->createFile($path.'/routes/web.php', $web); + $this->createFile($path.'/routes/channels.php', $channels); + $this->createFile($path.'/routes/console.php', $console); unset($api, $web, $channels, $console); - $this->delete($path . '/routes/.gitkeep'); + $this->delete($path.'/routes/.gitkeep'); } /** * Add the welcome view file. - * - * @param string $path */ - public function addWelcomeViewFile($path) + public function addWelcomeViewFile(string $path): void { $this->createFile( $path.'/resources/views/welcome.blade.php', - file_get_contents(__DIR__ . '/stubs/welcome.blade.stub') + file_get_contents(__DIR__.'/stubs/welcome.blade.stub') ); } /** * Get the stub file for the generator. - * - * @return string */ - protected function getStub() + protected function getStub(): string { return __DIR__.'/stubs/service.stub'; } diff --git a/src/Generators/stubs/model-8.stub b/src/Generators/stubs/model-8.stub deleted file mode 100644 index 60731d3..0000000 --- a/src/Generators/stubs/model-8.stub +++ /dev/null @@ -1,11 +0,0 @@ - */ public function rules() { diff --git a/src/Generators/stubs/serviceprovider-8.stub b/src/Generators/stubs/serviceprovider-8.stub deleted file mode 100644 index 30b01b5..0000000 --- a/src/Generators/stubs/serviceprovider-8.stub +++ /dev/null @@ -1,59 +0,0 @@ -loadMigrationsFrom([ - realpath(__DIR__ . '/../database/migrations') - ]); - } - - /** - * Register the {{name}} service provider. - * - * @return void - */ - public function register() - { - $this->app->register(RouteServiceProvider::class); - $this->app->register(BroadcastServiceProvider::class); - - $this->registerResources(); - } - - /** - * Register the {{name}} service resource namespaces. - * - * @return void - */ - protected function registerResources() - { - // Translation must be registered ahead of adding lang namespaces - $this->app->register(TranslationServiceProvider::class); - - Lang::addNamespace('{{slug}}', realpath(__DIR__.'/../resources/lang')); - - View::addNamespace('{{slug}}', base_path('resources/views/vendor/{{slug}}')); - View::addNamespace('{{slug}}', realpath(__DIR__.'/../resources/views')); - } -} diff --git a/src/Generators/stubs/serviceprovider.stub b/src/Generators/stubs/serviceprovider.stub index b42a3ab..30b01b5 100644 --- a/src/Generators/stubs/serviceprovider.stub +++ b/src/Generators/stubs/serviceprovider.stub @@ -2,13 +2,10 @@ namespace {{namespace}}; -use Lang; -use View; +use Illuminate\Support\Facades\Lang; +use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; -use {{namespace}}\RouteServiceProvider; -use {{namespace}}\BroadcastServiceProvider; use Illuminate\Translation\TranslationServiceProvider; -use Illuminate\Database\Eloquent\Factory as EloquentFactory; class {{name}}ServiceProvider extends ServiceProvider { @@ -29,9 +26,6 @@ class {{name}}ServiceProvider extends ServiceProvider $this->loadMigrationsFrom([ realpath(__DIR__ . '/../database/migrations') ]); - - $this->app->make(EloquentFactory::class) - ->load(realpath(__DIR__ . '/../database/factories')); } /** diff --git a/src/Parser.php b/src/Parser.php index ad5531e..9ffe8ff 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -1,28 +1,25 @@ realPath); @@ -31,7 +28,7 @@ public function parseFeatureJobs(Feature $feature) $jobs = []; foreach ($body as $line) { $job = $this->parseJobInLine($line, $contents); - if (!empty($job)) { + if ($job !== null) { $jobs[] = $job; } } @@ -39,7 +36,7 @@ public function parseFeatureJobs(Feature $feature) return $jobs; } - public function parseFunctionBody($contents, $function) + public function parseFunctionBody($contents, $function): string { // $pattern = "/function\s$function\([a-zA-Z0-9_\$\s,]+\)?". // match "function handle(...)" // '[\n\s]?[\t\s]*'. // regardless of the indentation preceding the { @@ -51,7 +48,7 @@ public function parseFunctionBody($contents, $function) // '('. # (1 start) // '{'. # opening brace // '('. # (2 start) - /* '(?>'.*/ # atomic grouping (for its non-capturing purpose only) + /* '(?>'.*/ // atomic grouping (for its non-capturing purpose only) // '" [^"]*+ "'. # double quoted strings // '| \' [^\']*+ \''. # single quoted strings // '| // .* $'. # a comment block starting with // @@ -68,7 +65,6 @@ public function parseFunctionBody($contents, $function) // '}'. # closing brace // ')~'; # (1 end) - preg_match($pattern, $contents, $match); return $match[1]; @@ -77,12 +73,9 @@ public function parseFunctionBody($contents, $function) /** * Parses the job class out of the given line of code. * - * @param string $line - * @param string $contents - * - * @return string + * @throws \Exception */ - public function parseJobInLine($line, $contents) + public function parseJobInLine(string $line, string $contents): ?Job { $line = trim($line); // match the line that potentially has the job, @@ -91,13 +84,15 @@ public function parseJobInLine($line, $contents) // we won't do anything if no job has been matched. if (empty($match)) { - return ''; + return null; } $match = $match[1]; // prepare for parsing $match = $this->filterJobMatch($match); + $name = $namespace = ''; + /* * determine syntax style and afterwards detect how the job * class name was put into the "run" method as a parameter. @@ -117,19 +112,19 @@ public function parseJobInLine($line, $contents) * Instantiation with an imported class using a `use` statement * passing parameters to the construction of the instance. * - new ImportedClass - * Instantiation without parameters nor parantheses. + * Instantiation without parameters nor parentheses. */ switch ($this->jobSyntaxStyle($match)) { case self::SYNTAX_STRING: - list($name, $namespace) = $this->parseStringJobSyntax($match, $contents); + [$name, $namespace] = $this->parseStringJobSyntax($match, $contents); break; case self::SYNTAX_KEYWORD: - list($name, $namespace) = $this->parseKeywordJobSyntax($match, $contents); + [$name, $namespace] = $this->parseKeywordJobSyntax($match, $contents); break; case self::SYNTAX_INSTANTIATION: - list($name, $namespace) = $this->parseInitJobSyntax($match, $contents); + [$name, $namespace] = $this->parseInitJobSyntax($match, $contents); break; } @@ -144,7 +139,7 @@ public function parseJobInLine($line, $contents) $path = $this->findJobPath($domainName, $name); - $job = new Job( + return new Job( $name, $namespace, basename($path), @@ -152,38 +147,28 @@ public function parseJobInLine($line, $contents) $this->relativeFromReal($path), $domain ); - - return $job; } /** * Parse the given job class written in the string syntax: 'Some\Domain\Job' - * - * @param string $match - * @param string $contents - * - * @return string */ - private function parseStringJobSyntax($match, $contents) + private function parseStringJobSyntax(string $match, string $contents): array { $slash = strrpos($match, '\\'); if ($slash !== false) { - $name = str_replace('\\', '', substr($match, $slash)); + $name = str_replace('\\', '', Str::substr($match, $slash)); $namespace = '\\'.preg_replace('/^\\\/', '', $match); + + return [$name, $namespace]; } - return [$name, $namespace]; + return ['', '']; } /** * Parse the given job class written in the ::class keyword syntax: SomeJob::class - * - * @param string $match - * @param string $contents - * - * @return string */ - private function parseKeywordJobSyntax($match, $contents) + private function parseKeywordJobSyntax(string $match, string $contents): array { // is it of the form \Full\Name\Space::class? // (using full namespace in-line) @@ -193,7 +178,7 @@ private function parseKeywordJobSyntax($match, $contents) if ($slash !== false) { $namespace = str_replace('::class', '', $match); // remove the ::class and the \ prefix - $name = str_replace(['\\', '::class'], '', substr($namespace, $slash)); + $name = str_replace(['\\', '::class'], '', Str::substr($namespace, $slash)); } else { // nope it's just Space::class, we will figure // out the namespace from a "use" statement. @@ -208,13 +193,8 @@ private function parseKeywordJobSyntax($match, $contents) /** * Parse the given job class written in the ini syntax: new SomeJob() - * - * @param string $match - * @param string $contents - * - * @return string */ - private function parseInitJobSyntax($match, $contents) + private function parseInitJobSyntax(string $match, string $contents): array { // remove the 'new ' from the beginning. $match = str_replace('new ', '', $match); @@ -230,9 +210,9 @@ private function parseInitJobSyntax($match, $contents) if ($slash !== false) { $namespace = $name; // prefix with a \ if not found. - $name = str_replace('\\', '', substr($namespace, $slash)); + $name = str_replace('\\', '', Str::substr($namespace, $slash)); } else { - // we don't have the full namespace so we will figure it out + // we don't have the full namespace, so we will figure it out // from the 'use' statements that we have in the file. preg_match("/use\s(.*$name)/", $contents, $namespace); $namespace = '\\'.preg_replace('/^\\\/', '', $namespace[1]); @@ -243,34 +223,18 @@ private function parseInitJobSyntax($match, $contents) /** * Get the domain for the given job's namespace. - * - * @param string $namespace - * - * @return string */ - private function domainForJob($namespace) + private function domainForJob(string $namespace): string { preg_match('/Domains\\\([^\\\]*)\\\Jobs/', $namespace, $domain); - return (!empty($domain)) ? $domain[1] : ''; + return (! empty($domain)) ? $domain[1] : ''; } - // if (strpos($match, '::class') !== false) { - // - // } elseif(strpos($match, 'new ') !== false) { - // - // } else { - // - // } - /** * Filter the matched line in preparation for parsing. - * - * @param string $match The matched job line. - * - * @return string */ - private function filterJobMatch($match) + private function filterJobMatch(string $match): string { // we don't want any quotes return str_replace(['"', "'"], '', $match); @@ -283,16 +247,12 @@ private function filterJobMatch($match) * - Using the 'TheJob::class' keyword * - Using instantiation: new TheJob(...) * - Using a string with the full namespace: '\Domain\TheJob' - * - * @param string $match - * - * @return string */ - private function jobSyntaxStyle($match) + private function jobSyntaxStyle(string $match): string { - if (strpos($match, '::class') !== false) { + if (str_contains($match, '::class')) { $style = self::SYNTAX_KEYWORD; - } elseif(strpos($match, 'new ') !== false) { + } elseif (str_contains($match, 'new ')) { $style = self::SYNTAX_INSTANTIATION; } else { $style = self::SYNTAX_STRING; diff --git a/src/Providers/RouteServiceProvider.php b/src/Providers/RouteServiceProvider.php index 3c20c8c..93ac738 100644 --- a/src/Providers/RouteServiceProvider.php +++ b/src/Providers/RouteServiceProvider.php @@ -2,29 +2,26 @@ namespace Lucid\Providers; -use Illuminate\Routing\Router; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as BaseServiceProvider; +use Illuminate\Routing\Router; abstract class RouteServiceProvider extends BaseServiceProvider { /** * Read the routes from the "api.php" and "web.php" files of this Service - * - * @param Router $router */ abstract public function map(Router $router); - /** - * @param $router - * @param $namespace - * @param $pathApi - * @param $pathWeb - */ - public function loadRoutesFiles($router, $namespace, $pathApi = null, $pathWeb = null) - { + public function loadRoutesFiles( + Router $router, + string $namespace, + ?string $pathApi = null, + ?string $pathWeb = null + ): void { if (is_string($pathApi) && is_file($pathApi)) { $this->mapApiRoutes($router, $namespace, $pathApi); } + if (is_string($pathWeb) && is_file($pathWeb)) { $this->mapWebRoutes($router, $namespace, $pathWeb); } @@ -34,20 +31,17 @@ public function loadRoutesFiles($router, $namespace, $pathApi = null, $pathWeb = * Define the "api" routes for the application. * * These routes are typically stateless. - * - * @param $router - * @param $namespace - * @param $path - * @param $prefix - * - * @return void */ - protected function mapApiRoutes($router, $namespace, $path, $prefix='api') - { + protected function mapApiRoutes( + Router $router, + string $namespace, + string $path, + string $prefix = 'api' + ): void { $router->group([ 'middleware' => 'api', - 'namespace' => $namespace, - 'prefix' => $prefix // to allow the delete or change of api prefix + 'namespace' => $namespace, + 'prefix' => $prefix, // to allow to delete or change of api prefix ], function ($router) use ($path) { require $path; }); @@ -57,18 +51,15 @@ protected function mapApiRoutes($router, $namespace, $path, $prefix='api') * Define the "web" routes for the application. * * These routes all receive session state, CSRF protection, etc. - * - * @param $router - * @param $namespace - * @param $path - * - * @return void */ - protected function mapWebRoutes($router, $namespace, $path) - { + protected function mapWebRoutes( + Router $router, + string $namespace, + string $path + ): void { $router->group([ 'middleware' => 'web', - 'namespace' => $namespace + 'namespace' => $namespace, ], function ($router) use ($path) { require $path; }); diff --git a/src/Str.php b/src/Str.php index 5cdc2bf..d119f31 100644 --- a/src/Str.php +++ b/src/Str.php @@ -4,43 +4,60 @@ use Illuminate\Support\Str as LaravelStr; +if (! defined('DS')) { + define('DS', DIRECTORY_SEPARATOR); +} + class Str { /** * Convert a value to studly caps case. - * - * @param string $value - * @return string */ - public static function studly($value) + public static function studly(?string $value): string { - return LaravelStr::studly($value); + return LaravelStr::studly($value ?? ''); } /** * Convert a string to snake case. - * - * @param string $value - * @param string $delimiter - * @return string */ - public static function snake($value, $delimiter = '_') + public static function snake(string $value, string $delimiter = '_'): string { return LaravelStr::snake($value, $delimiter); } + /** + * Replace last occurrence of string inside another string with specified string + */ + public static function replaceLast( + string $search, + string $replace, + string $subject + ): string { + return LaravelStr::replaceLast($search, $replace, $subject); + } + + public static function substr( + string $string, + int $offset + ): string { + /** @var false|string $substr */ + $substr = substr($string, $offset); + + if ($substr === false) { + return ''; + } + + return $substr; + } + /** * Determine the real name of the given name, * excluding the given pattern. - * i.e. the name: "CreateArticleFeature.php" with pattern '/Feature.php' + * i.e. the name: "CreateArticleFeature.php" with pattern '/Feature.php/' * will result in "Create Article". - * - * @param string $name - * @param string $pattern - * - * @return string */ - public static function realName($name, $pattern = '//') + public static function realName(string $name, string $pattern = '//'): string { $name = preg_replace($pattern, '', $name); @@ -50,36 +67,30 @@ public static function realName($name, $pattern = '//') /** * Get the given name formatted as a feature. * - * i.e. "Create Post Feature", "CreatePostFeature.php", "createPost", "createe" + * i.e. "Create Post Feature", "CreatePostFeature.php", "createPost", "create" * and many other forms will be transformed to "CreatePostFeature" which is * the standard feature class name. - * - * @param string $name - * - * @return string */ - public static function feature($name) + public static function feature(?string $name): string { - $parts = array_map(function($part) { return self::studly($part); }, explode("/", $name)); - $feature = self::studly(preg_replace('/Feature(\.php)?$/', '', array_pop($parts)).'Feature'); + $parts = array_map(function ($part) { + return self::studly($part); + }, explode('/', $name ?? '')); + $feature = self::studly(preg_replace('/Feature(\.php)?$/', '', array_pop($parts)).'Feature'); $parts[] = $feature; - return join(DS, $parts); + return implode(DS, $parts); } /** * Get the given name formatted as a job. * - * i.e. "Create Post Feature", "CreatePostJob.php", "createPost", + * i.e. "Create Post", "CreatePostJob.php", "createPost", * and many other forms will be transformed to "CreatePostJob" which is * the standard job class name. - * - * @param string $name - * - * @return string */ - public static function job($name) + public static function job(string $name): string { return self::studly(preg_replace('/Job(\.php)?$/', '', $name).'Job'); } @@ -90,12 +101,8 @@ public static function job($name) * i.e. "Create Post Operation", "CreatePostOperation.php", "createPost", * and many other forms will be transformed to "CreatePostOperation" which is * the standard operation class name. - * - * @param string $name - * - * @return string */ - public static function operation($name) + public static function operation(string $name): string { return self::studly(preg_replace('/Operation(\.php)?$/', '', $name).'Operation'); } @@ -104,36 +111,24 @@ public static function operation($name) * Get the given name formatted as a domain. * * Domain names are just CamelCase - * - * @param string $name - * - * @return string */ - public static function domain($name) + public static function domain(string $name): string { return self::studly($name); } /** * Get the given name formatted as a service name. - * - * @param string $name - * - * @return string */ - public static function service($name) + public static function service(?string $name): string { - return self::studly($name); + return self::studly($name ?? ''); } /** * Get the given name formatted as a controller name. - * - * @param string $name - * - * @return string */ - public static function controller($name) + public static function controller(string $name): string { return self::studly(preg_replace('/Controller(\.php)?$/', '', $name).'Controller'); } @@ -142,34 +137,24 @@ public static function controller($name) * Get the given name formatted as a model. * * Model names are just CamelCase - * - * @param string $name - * - * @return string */ - public static function model($name) + public static function model(string $name): string { return self::studly($name); } /** * Get the given name formatted as a policy. - * - * @param $name - * @return string */ - public static function policy($name) + public static function policy(string $name): string { - return self::studly(preg_replace('/Policy(\.php)?$/', '', $name) . 'Policy'); + return self::studly(preg_replace('/Policy(\.php)?$/', '', $name).'Policy'); } /** * Get the given name formatted as a request. - * - * @param $name - * @return string */ - public static function request($name) + public static function request(string $name): string { return self::studly($name); } diff --git a/src/Testing/MockMe.php b/src/Testing/MockMe.php index c28460e..43632d6 100644 --- a/src/Testing/MockMe.php +++ b/src/Testing/MockMe.php @@ -2,8 +2,6 @@ namespace Lucid\Testing; -use Mockery\Mock; - trait MockMe { public static function mock(array $constructorExpectations = []): UnitMock diff --git a/src/Testing/UnitMock.php b/src/Testing/UnitMock.php index f80ba18..e720a17 100644 --- a/src/Testing/UnitMock.php +++ b/src/Testing/UnitMock.php @@ -13,36 +13,18 @@ class UnitMock { use Marshal; - /** - * @var string $unit - */ - private $unit; + private string $unit; - /** - * @var array $constructorExpectations - */ - private $constructorExpectations; + private array $constructorExpectations; - /** - * @var array $currentConstructorExpectations - */ - private $currentConstructorExpectations; + private array $currentConstructorExpectations; - /** - * @var array $mocks - */ - private $mocks; + private array $mocks = []; - /** - * @var MockInterface $currentMock - */ - private $currentMock; + private MockInterface|Mockery\LegacyMockInterface|null $currentMock = null; /** * UnitMock constructor. - * - * @param string $unit - * @param array $constructorExpectations */ public function __construct(string $unit, array $constructorExpectations = []) { @@ -50,13 +32,13 @@ public function __construct(string $unit, array $constructorExpectations = []) $this->setConstructorExpectations($constructorExpectations); } - public function setConstructorExpectations(array $constructorExpectations) + public function setConstructorExpectations(array $constructorExpectations): void { $this->currentConstructorExpectations = $constructorExpectations; $this->constructorExpectations[] = $this->currentConstructorExpectations; } - public function getConstructorExpectations() + public function getConstructorExpectations(): array { return $this->constructorExpectations; } @@ -65,11 +47,11 @@ public function getConstructorExpectations() * Returns constructor expectations array that matches the given $unit. * Empty array otherwise. * - * @param $unit * @return array|mixed|void + * * @throws ReflectionException */ - public function getConstructorExpectationsForInstance($unit) + public function getConstructorExpectationsForInstance(mixed $unit) { foreach ($this->constructorExpectations as $index => $args) { $expected = new $unit(...$args); @@ -93,7 +75,6 @@ public function getConstructorExpectationsForInstance($unit) } /** - * @return array * @throws ReflectionException * @throws Exception */ @@ -120,7 +101,6 @@ private function getCurrentConstructorArgs(): array /** * Register unit mock for current constructor expectations. * - * @return $this * @throws ReflectionException * @throws Exception */ @@ -138,8 +118,8 @@ private function registerMock(): UnitMock } throw new Mockery\Exception\NoMatchingExpectationException( - "\n\nExpected one of the following arguments sets for {$this->unit}::__construct(): " . - print_r($this->constructorExpectations, true) . "\nGot: " . + "\n\nExpected one of the following arguments sets for {$this->unit}::__construct(): ". + print_r($this->constructorExpectations, true)."\nGot: ". print_r($args, true) ); }); @@ -150,42 +130,50 @@ private function registerMock(): UnitMock /** * Compare the mock to an actual instance. * - * @param object $unit - * @return void * @throws Mockery\Exception\NoMatchingExpectationException */ - public function compareTo(object $unit) + public function compareTo(object $unit): void { - $expected = array_map(fn($args) => new $unit(...$args), $this->constructorExpectations); + $expected = array_map(fn ($args) => new $unit(...$args), $this->constructorExpectations); $ref = new ReflectionClass($unit); foreach ($ref->getProperties() as $property) { + $expectations = array_map(fn ($instance) => $property->getValue($instance), $expected); - $expectations = array_map(fn($instance) => $property->getValue($instance), $expected); - - if (!in_array($property->getValue($unit), $expectations)) { + if (! in_array($property->getValue($unit), $expectations)) { throw new Mockery\Exception\NoMatchingExpectationException( "Mismatch in \${$property->getName()} when running {$this->unit} \n\n--- Expected (one of)\n". - print_r(join("\n", array_map(fn($instance) => $property->getValue($instance), $expected)), true). + print_r(implode("\n", array_map(fn ($instance) => $property->getValue($instance), $expected)), true). "\n\n+++Actual:\n".print_r($property->getValue($unit), true)."\n\n" ); } } } - public function getMock(): MockInterface + /** + * Compare the mock to an actual instance. + * + * @throws ReflectionException + */ + public function getMock(): MockInterface|Mockery\LegacyMockInterface { $this->registerMock(); return $this->currentMock; } - public function shouldBeDispatched() + /** + * @throws ReflectionException + */ + public function shouldBeDispatched(): void { $this->getMock()->shouldReceive('handle')->once(); } - public function shouldNotBeDispatched() + /** + * @throws ReflectionException + */ + public function shouldNotBeDispatched(): void { if ($this->currentMock) { $this->getMock()->shouldNotReceive('handle'); @@ -198,24 +186,46 @@ public function shouldNotBeDispatched() } } - public function shouldReturn($value) + /** + * @throws ReflectionException + */ + public function shouldReturn(mixed $value): void { - $this->getMock()->shouldReceive('handle')->once()->andReturn($value); + $this + ->getMock() + ->shouldReceive('handle') + ->once() + ->andReturn($value); } - public function shouldReturnTrue() + /** + * @throws ReflectionException + */ + public function shouldReturnTrue(): void { $this->shouldReturn(true); } - public function shouldReturnFalse() + /** + * @throws ReflectionException + */ + public function shouldReturnFalse(): void { $this->shouldReturn(false); } - public function shouldThrow($exception, $message = '', $code = 0, Exception $previous = null) - { - $this->getMock()->shouldReceive('handle') + /** + * @throws ReflectionException + */ + public function shouldThrow( + mixed $exception, + string $message = '', + int $code = 0, + Exception $previous = null + ): void { + $this + ->getMock() + ->shouldReceive('handle') ->once() ->andThrow($exception, $message, $code, $previous); } diff --git a/src/Testing/UnitMockRegistry.php b/src/Testing/UnitMockRegistry.php index 4bffc27..4fd219a 100644 --- a/src/Testing/UnitMockRegistry.php +++ b/src/Testing/UnitMockRegistry.php @@ -4,10 +4,7 @@ class UnitMockRegistry { - /** - * @var array - */ - private $mocks = []; + private array $mocks = []; public function __construct() { @@ -25,17 +22,19 @@ public function has(string $unit): bool public function get(string $unit): ?UnitMock { - if (!$this->has($unit)) return null; + if (! $this->has($unit)) { + return null; + } return $this->mocks[$unit]; } - public function register(string $unit, UnitMock $mock) + public function register(string $unit, UnitMock $mock): void { $this->mocks[$unit] = $mock; } - public function count() + public function count(): int { return count($this->mocks); } diff --git a/src/Units/Controller.php b/src/Units/Controller.php index f215a93..89312ac 100644 --- a/src/Units/Controller.php +++ b/src/Units/Controller.php @@ -2,15 +2,14 @@ namespace Lucid\Units; -use Lucid\Bus\ServesFeatures; -use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; +use Illuminate\Routing\Controller as BaseController; +use Lucid\Bus\ServesFeatures; /** * Base controller. */ class Controller extends BaseController { - use ValidatesRequests; - use ServesFeatures; + use ValidatesRequests, ServesFeatures; } diff --git a/src/Units/Feature.php b/src/Units/Feature.php index d70ac27..3c2345f 100644 --- a/src/Units/Feature.php +++ b/src/Units/Feature.php @@ -2,8 +2,8 @@ namespace Lucid\Units; -use Lucid\Testing\MockMe; use Lucid\Bus\UnitDispatcher; +use Lucid\Testing\MockMe; abstract class Feature { diff --git a/src/Units/Operation.php b/src/Units/Operation.php index 14732bc..3fbf856 100644 --- a/src/Units/Operation.php +++ b/src/Units/Operation.php @@ -2,8 +2,8 @@ namespace Lucid\Units; -use Lucid\Testing\MockMe; use Lucid\Bus\UnitDispatcher; +use Lucid\Testing\MockMe; abstract class Operation { diff --git a/src/Units/QueueableJob.php b/src/Units/QueueableJob.php index e1658d8..68e50c8 100644 --- a/src/Units/QueueableJob.php +++ b/src/Units/QueueableJob.php @@ -2,11 +2,10 @@ namespace Lucid\Units; -use Lucid\Units\Job; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; /** * An abstract Job that can be managed with a queue diff --git a/src/Units/QueueableOperation.php b/src/Units/QueueableOperation.php index 29e2c8d..73f3722 100644 --- a/src/Units/QueueableOperation.php +++ b/src/Units/QueueableOperation.php @@ -2,11 +2,10 @@ namespace Lucid\Units; -use Lucid\Units\Operation; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; /** * An abstract Operation that can be managed with a queue diff --git a/src/Validation/Validation.php b/src/Validation/Validation.php index c5a5420..be589cf 100644 --- a/src/Validation/Validation.php +++ b/src/Validation/Validation.php @@ -14,11 +14,14 @@ class Validation * @param array $rules * @param array $messages * @param array $customAttributes - * * @return \Illuminate\Validation\Validator */ - public function make(array $data, array $rules, array $messages = [], array $customAttributes = []) - { + public function make( + array $data, + array $rules, + array $messages = [], + array $customAttributes = [] + ): \Illuminate\Validation\Validator { return $this->getValidationFactory()->make($data, $rules, $messages, $customAttributes); } @@ -27,7 +30,7 @@ public function make(array $data, array $rules, array $messages = [], array $cus * * @return \Illuminate\Validation\Factory */ - public function getValidationFactory() + public function getValidationFactory(): \Illuminate\Validation\Factory { return app(\Illuminate\Contracts\Validation\Factory::class); } diff --git a/src/Validation/Validator.php b/src/Validation/Validator.php index e3ba9d5..0590c09 100644 --- a/src/Validation/Validator.php +++ b/src/Validation/Validator.php @@ -2,7 +2,6 @@ namespace Lucid\Validation; -use Lucid\Validation\Validation; use Lucid\Exceptions\InvalidInputException; /** @@ -13,9 +12,9 @@ */ class Validator { - protected $rules = []; + protected array $rules = []; - protected $validation; + protected Validation $validation; public function __construct(Validation $validation) { @@ -25,16 +24,18 @@ public function __construct(Validation $validation) /** * Validate the given input. * - * @param array $input The input to validate - * @param array $rules Specify custom rules (will override class rules) - * @param array $messages Specify custom messages (will override class messages) - * + * @param array $input The input to validate + * @param array $rules Specify custom rules (will override class rules) + * @param array $messages Specify custom messages (will override class messages) * @return bool * * @throws \Lucid\Exceptions\InvalidInputException */ - public function validate(array $input, array $rules = [], array $messages = []) - { + public function validate( + array $input, + array $rules = [], + array $messages = [] + ): bool { $validation = $this->validation($input, $rules, $messages); if ($validation->fails()) { @@ -48,14 +49,16 @@ public function validate(array $input, array $rules = [], array $messages = []) * Get a validation instance out of the given input and optionatlly rules * by default the $rules property will be used. * - * @param array $input - * @param array $rules - * @param array $messages - * + * @param array $input + * @param array $rules + * @param array $messages * @return \Illuminate\Validation\Validator */ - public function validation(array $input, array $rules = [], array $messages = []) - { + public function validation( + array $input, + array $rules = [], + array $messages = [] + ): \Illuminate\Validation\Validator { if (empty($rules)) { $rules = $this->rules; } diff --git a/tests/Pest.php b/tests/Pest.php new file mode 100644 index 0000000..5949c61 --- /dev/null +++ b/tests/Pest.php @@ -0,0 +1,45 @@ +in('Feature'); + +/* +|-------------------------------------------------------------------------- +| Expectations +|-------------------------------------------------------------------------- +| +| When you're writing tests, you often need to check that values meet certain conditions. The +| "expect()" function gives you access to a set of "expectations" methods that you can use +| to assert different things. Of course, you may extend the Expectation API at any time. +| +*/ + +expect()->extend('toBeOne', function () { + return $this->toBe(1); +}); + +/* +|-------------------------------------------------------------------------- +| Functions +|-------------------------------------------------------------------------- +| +| While Pest is very powerful out-of-the-box, you may have some testing code specific to your +| project that you don't want to repeat in every file. Here you can also expose helpers as +| global functions to help you to reduce the number of lines of code in your test files. +| +*/ + +function something() +{ + // .. +} diff --git a/tests/Unit/StrTest.php b/tests/Unit/StrTest.php new file mode 100644 index 0000000..838f83d --- /dev/null +++ b/tests/Unit/StrTest.php @@ -0,0 +1,183 @@ +assertEquals('StudlyCase', Str::studly('studly_case')); +}); + +it('converts null to empty', function () { + $this->assertEquals('', Str::studly(null)); +}); + +// Test cases for snake() + +it('converts string to snake', function () { + $this->assertEquals('snake_case', Str::snake('snakeCase')); +}); + +it('converts string to snake with custom delimiter', function () { + $this->assertEquals('snake-case', Str::snake('snakeCase', '-')); +}); + +// Test cases for replaceLast() + +it('replaces last occurrence of string', function () { + $this->assertEquals('foo bar qux', Str::replaceLast('baz', 'qux', 'foo bar baz')); +}); + +it('replaces last occurrence of string with empty string', function () { + $this->assertEquals('foo bar ', Str::replaceLast('baz', '', 'foo bar baz')); +}); + +it('replaces last occurrence of string with empty string when string ends with search', function () { + $this->assertEquals('foo ', Str::replaceLast('bar', '', 'foo bar')); +}); + +it('replaces last occurrence of string with empty string when string is search', function () { + $this->assertEquals('', Str::replaceLast('foo', '', 'foo')); +}); + +// Test cases for substr() + +it('returns empty string when offset is greater than string length', function () { + $this->assertEquals('', Str::substr('foo', 3)); +}); + +it('returns empty string when offset is equal to string length', function () { + $this->assertEquals('', Str::substr('foo', 3)); +}); + +it('returns correct substring', function () { + $this->assertEquals('oo', Str::substr('foo', 1)); +}); + +// Test cases for realName() + +it('returns real name', function () { + $this->assertEquals('Create Article', Str::realName('CreateArticleFeature.php', '/Feature.php/')); +}); + +// Test cases for feature() + +it('returns feature name', function () { + $this->assertEquals('CreateArticleFeature', Str::feature('CreateArticleFeature.php')); +}); + +it('returns feature name variation 2', function () { + $this->assertEquals('CreateArticleFeature', Str::feature('Create Article Feature')); +}); + +it('returns feature name variation 3', function () { + $this->assertEquals('CreateArticleFeature', Str::feature('Create Article')); +}); + +it('returns feature name variation 4', function () { + $this->assertEquals('CreateArticleFeature', Str::feature('CreateArticle')); +}); + +// Test cases for job() + +it('returns job name', function () { + $this->assertEquals('CreateArticleJob', Str::job('CreateArticleJob.php')); +}); + +it('returns job name variation 2', function () { + $this->assertEquals('CreateArticleJob', Str::job('Create Article Job')); +}); + +it('returns job name variation 3', function () { + $this->assertEquals('CreateArticleJob', Str::job('Create Article')); +}); + +it('returns job name variation 4', function () { + $this->assertEquals('CreateArticleJob', Str::job('CreateArticle')); +}); + +// Test cases for operation() + +it('returns operation name', function () { + $this->assertEquals('CreateArticleOperation', Str::operation('CreateArticleOperation.php')); +}); + +it('returns operation name variation 2', function () { + $this->assertEquals('CreateArticleOperation', Str::operation('Create Article Operation')); +}); + +it('returns operation name variation 3', function () { + $this->assertEquals('CreateArticleOperation', Str::operation('Create Article')); +}); + +it('returns operation name variation 4', function () { + $this->assertEquals('CreateArticleOperation', Str::operation('CreateArticle')); +}); + +// Test cases for domain() + +it('returns domain name', function () { + $this->assertEquals('TestDomain', Str::domain('testDomain')); +}); + +it('returns domain name variation 2', function () { + $this->assertEquals('TestDomain', Str::domain('test_domain')); +}); + +// Test cases for service() + +it('returns service name', function () { + $this->assertEquals('TestService', Str::service('testService')); +}); + +it('returns service name variation 2', function () { + $this->assertEquals('TestService', Str::service('test_service')); +}); + +// Test cases for controller() + +it('returns controller name', function () { + $this->assertEquals('TestController', Str::controller('testController')); +}); + +it('returns controller name variation 2', function () { + $this->assertEquals('TestController', Str::controller('testController.php')); +}); + +it('returns controller name variation 3', function () { + $this->assertEquals('TestController', Str::controller('test')); +}); + +// Test cases for model() + +it('returns model name', function () { + $this->assertEquals('TestModel', Str::model('testModel')); +}); + +it('returns model name variation 2', function () { + $this->assertEquals('TestModel', Str::model('test_model')); +}); + +// Test cases for policy() + +it('returns policy name', function () { + $this->assertEquals('TestPolicy', Str::policy('testPolicy')); +}); + +it('returns policy name variation 2', function () { + $this->assertEquals('TestPolicy', Str::policy('testPolicy.php')); +}); + +it('returns policy name variation 3', function () { + $this->assertEquals('TestPolicy', Str::policy('test')); +}); + +// Test cases for request() + +it('returns request name', function () { + $this->assertEquals('TestRequest', Str::request('testRequest')); +}); + +it('returns request name variation 2', function () { + $this->assertEquals('TestRequest', Str::request('test_request')); +});