diff --git a/composer.json b/composer.json index 0191b75..d939927 100644 --- a/composer.json +++ b/composer.json @@ -60,14 +60,19 @@ }, "scripts": { "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", - "analyse": "vendor/bin/phpstan", - "test": "vendor/bin/pest --testsuite=RESTPresenter", - "test-coverage": "vendor/bin/pest --testsuite=RESTPresenter --coverage", - "test-starter-kit:lunar": "vendor/bin/pest --testsuite=starter-kit:lunar", + "pest": "vendor/bin/pest --testsuite=RESTPresenter", + "pest-coverage": "vendor/bin/pest --testsuite=RESTPresenter --coverage", + "pest-starter-kit:lunar": "vendor/bin/pest --testsuite=starter-kit:lunar", "test:format": "pint --test", "test:refactor": "rector --dry-run", + "test:types": "phpstan analyse", "format": "vendor/bin/pint", - "refactor": "rector" + "refactor": "rector", + "test": [ + "@test:format", + "@test:refactor", + "@test:types" + ] }, "config": { "sort-packages": true, diff --git a/config/rest-presenter.php b/config/rest-presenter.php index 43fa1ab..d3140b8 100644 --- a/config/rest-presenter.php +++ b/config/rest-presenter.php @@ -1,5 +1,7 @@ withPaths([ - __DIR__ . '/src', - __DIR__ . '/tests', + __DIR__.'/src', + __DIR__.'/tests', ]) ->withSkip([ AddOverrideAttributeToOverriddenMethodsRector::class, + BooleanInBooleanNotRuleFixerRector::class, ]) ->withAttributesSets( symfony: true, diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php index e2d7e41..f808f84 100644 --- a/resources/lang/en/auth.php +++ b/resources/lang/en/auth.php @@ -1,5 +1,7 @@ 'You have been logged out from this device.', 'logout_message' => 'You have been logged out from all devices.', diff --git a/src/Base/RESTPresenter.php b/src/Base/RESTPresenter.php index 2186c11..830f136 100644 --- a/src/Base/RESTPresenter.php +++ b/src/Base/RESTPresenter.php @@ -1,12 +1,14 @@ isKitRegistered($kit)) { $this->app->register($kit); } } - protected function isKitRegistered(string $kit): bool + private function isKitRegistered(string $kit): bool { return $this->app->providerIsLoaded($kit); } diff --git a/src/Base/StarterKit.php b/src/Base/StarterKit.php index 2b0fce5..66bb6c0 100644 --- a/src/Base/StarterKit.php +++ b/src/Base/StarterKit.php @@ -1,12 +1,16 @@ > diff --git a/src/Commands/Generator/MakeAction.php b/src/Commands/Generator/MakeAction.php index 67cd428..5a99cfe 100644 --- a/src/Commands/Generator/MakeAction.php +++ b/src/Commands/Generator/MakeAction.php @@ -1,5 +1,7 @@ getDefaultNamespace($rootNamespace) . '\\' . $name; + return $this->getDefaultNamespace($rootNamespace).'\\'.$name; } protected function getStub(): string { - return __DIR__ . '/stubs/' . type($this->argument('type'))->asString() . '/action.php.stub'; + return __DIR__.'/stubs/'.type($this->argument('type'))->asString().'/action.php.stub'; } protected function getDefaultNamespace($rootNamespace): string @@ -44,10 +46,10 @@ protected function getDefaultNamespace($rootNamespace): string $namespace = type(config('rest-presenter.generator.namespace'))->asString(); if ($this->argument('kit_namespace')) { - return $namespace . '\\' . type($this->argument('kit_namespace'))->asString() . '\\Actions'; + return $namespace.'\\'.type($this->argument('kit_namespace'))->asString().'\\Actions'; } - return $namespace . '\\Resources\\' . $resourceDirectory . '\\Actions'; + return $namespace.'\\Resources\\'.$resourceDirectory.'\\Actions'; } protected function getNameInput(): string @@ -65,35 +67,35 @@ protected function buildClass($name): string } /** - * @return array + * @return array> */ - protected function buildResourceReplacements(): array + protected function getArguments(): array { - $kitNamespace = type($this->argument('kit_namespace'))->asString(); - $resourceName = type($this->argument('name'))->asString(); - return [ - '{{ actionNamespace }}' => $kitNamespace !== '' && $kitNamespace !== '0' - ? 'XtendPackages\\RESTPresenter\\' . $kitNamespace . '\\Actions\\' . $this->getNameInput() . '\\' . $this->getNameInput() - : 'XtendPackages\\RESTPresenter\\Resources\\' . Str::plural($resourceName) . '\\Actions\\' . $this->getNameInput() . '\\' . $this->getNameInput(), - '{{ aliasAction }}' => 'Xtend' . $this->getNameInput() . 'Action', - '{{ relationship }}' => strtolower($resourceName), - '{{ relationship_search_key }}' => type($this->argument('relation_search_key') ?? '')->asString(), + ['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)], + ['resource', InputArgument::REQUIRED, 'The resource of the '.strtolower($this->type)], + ['type', InputArgument::REQUIRED, 'The type of action to create'], + ['relation', InputArgument::OPTIONAL, 'The relation of the '.strtolower($this->type)], + ['relation_search_key', InputArgument::OPTIONAL, 'The search key of the '.strtolower($this->type)], + ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the '.strtolower($this->type)], ]; } /** - * @return array> + * @return array */ - protected function getArguments(): array + private function buildResourceReplacements(): array { + $kitNamespace = type($this->argument('kit_namespace'))->asString(); + $resourceName = type($this->argument('name'))->asString(); + return [ - ['name', InputArgument::REQUIRED, 'The name of the ' . strtolower($this->type)], - ['resource', InputArgument::REQUIRED, 'The resource of the ' . strtolower($this->type)], - ['type', InputArgument::REQUIRED, 'The type of action to create'], - ['relation', InputArgument::OPTIONAL, 'The relation of the ' . strtolower($this->type)], - ['relation_search_key', InputArgument::OPTIONAL, 'The search key of the ' . strtolower($this->type)], - ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the ' . strtolower($this->type)], + '{{ actionNamespace }}' => $kitNamespace !== '' && $kitNamespace !== '0' + ? 'XtendPackages\\RESTPresenter\\'.$kitNamespace.'\\Actions\\'.$this->getNameInput().'\\'.$this->getNameInput() + : 'XtendPackages\\RESTPresenter\\Resources\\'.Str::plural($resourceName).'\\Actions\\'.$this->getNameInput().'\\'.$this->getNameInput(), + '{{ aliasAction }}' => 'Xtend'.$this->getNameInput().'Action', + '{{ relationship }}' => strtolower($resourceName), + '{{ relationship_search_key }}' => type($this->argument('relation_search_key') ?? '')->asString(), ]; } } diff --git a/src/Commands/Generator/MakeController.php b/src/Commands/Generator/MakeController.php index 569eb80..7f7473d 100644 --- a/src/Commands/Generator/MakeController.php +++ b/src/Commands/Generator/MakeController.php @@ -1,5 +1,7 @@ argument('type'))->asString() . '/controller.php.stub'; + return __DIR__.'/stubs/'.type($this->argument('type'))->asString().'/controller.php.stub'; } protected function getDefaultNamespace($rootNamespace): string @@ -33,10 +35,10 @@ protected function getDefaultNamespace($rootNamespace): string $kitNamespace = type($this->argument('kit_namespace'))->asString(); if ($kitNamespace !== '' && $kitNamespace !== '0') { - return $namespace . '\\' . $kitNamespace; + return $namespace.'\\'.$kitNamespace; } - return $namespace . '\\Controllers\\' . $controllerDirectory; + return $namespace.'\\Controllers\\'.$controllerDirectory; } protected function getNameInput(): string @@ -53,30 +55,15 @@ protected function buildClass($name): string ); } - /** - * @return array - */ - protected function buildControllerReplacements(): array - { - $controllerName = type($this->argument('name'))->asString(); - - return [ - '{{ controllerNamespace }}' => $this->argument('kit_namespace') - ? 'XtendPackages\\RESTPresenter\\' . type($this->argument('kit_namespace'))->asString() . '\\' . $this->getNameInput() - : 'XtendPackages\\RESTPresenter\\Controllers\\' . $controllerName . '\\' . $this->getNameInput(), - '{{ aliasController }}' => 'Xtend' . $this->getNameInput(), - ]; - } - /** * @return array> */ protected function getArguments(): array { return [ - ['name', InputArgument::REQUIRED, 'The name of the ' . strtolower($this->type)], - ['type', InputArgument::REQUIRED, 'The type of the ' . strtolower($this->type)], - ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the ' . strtolower($this->type)], + ['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)], + ['type', InputArgument::REQUIRED, 'The type of the '.strtolower($this->type)], + ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the '.strtolower($this->type)], ]; } @@ -108,4 +95,19 @@ protected function afterPromptingForMissingArguments(InputInterface $input, Outp $input->setOption(type($type)->asString(), true); } } + + /** + * @return array + */ + private function buildControllerReplacements(): array + { + $controllerName = type($this->argument('name'))->asString(); + + return [ + '{{ controllerNamespace }}' => $this->argument('kit_namespace') + ? 'XtendPackages\\RESTPresenter\\'.type($this->argument('kit_namespace'))->asString().'\\'.$this->getNameInput() + : 'XtendPackages\\RESTPresenter\\Controllers\\'.$controllerName.'\\'.$this->getNameInput(), + '{{ aliasController }}' => 'Xtend'.$this->getNameInput(), + ]; + } } diff --git a/src/Commands/Generator/MakeData.php b/src/Commands/Generator/MakeData.php index a505eab..b594521 100644 --- a/src/Commands/Generator/MakeData.php +++ b/src/Commands/Generator/MakeData.php @@ -1,5 +1,7 @@ generateTypeScriptDeclarations(); + + return null; } protected function qualifyClass($name) @@ -45,12 +52,12 @@ protected function qualifyClass($name) return $name; } - return $this->getDefaultNamespace($rootNamespace) . '\\' . $name; + return $this->getDefaultNamespace($rootNamespace).'\\'.$name; } protected function getStub(): string { - return __DIR__ . '/stubs/' . type($this->argument('type'))->asString() . '/data.php.stub'; + return __DIR__.'/stubs/'.type($this->argument('type'))->asString().'/data.php.stub'; } protected function getDefaultNamespace($rootNamespace): string @@ -61,10 +68,10 @@ protected function getDefaultNamespace($rootNamespace): string $resourceDirectory = Str::plural($resourceName); if ($this->argument('kit_namespace')) { - return $namespace . '\\' . type($this->argument('kit_namespace'))->asString() . '\\Presenters\\' . $presenterName . '\\Data'; + return $namespace.'\\'.type($this->argument('kit_namespace'))->asString().'\\Presenters\\'.$presenterName.'\\Data'; } - return $namespace . '\\Resources\\' . $resourceDirectory . '\\Presenters\\' . $presenterName . '\\Data'; + return $namespace.'\\Resources\\'.$resourceDirectory.'\\Presenters\\'.$presenterName.'\\Data'; } protected function getNameInput(): string @@ -81,67 +88,19 @@ protected function buildClass($name): string ); } - /** - * @return array - */ - protected function buildResourceReplacements(): array - { - $resourceName = type($this->argument('name'))->asString(); - $model = type($this->argument('model'))->asString(); - $fields = type($this->argument('fields') ?? [])->asArray(); - - return [ - '{{ presenterNamespace }}' => $this->argument('kit_namespace') - ? 'XtendPackages\\RESTPresenter\\' . type($this->argument('kit_namespace'))->asString() . '\\Presenters\\' . $this->getNameInput() . '\\' . $this->getNameInput() - : 'XtendPackages\\RESTPresenter\\Resources\\' . Str::plural($resourceName) . '\\Presenters\\' . $this->getNameInput() . '\\' . $this->getNameInput(), - '{{ aliasPresenter }}' => 'Xtend' . $this->getNameInput() . 'Presenter', - '{{ modelClassImport }}' => $model, - '{{ modelClassName }}' => class_basename($model), - '{{ $modelVarSingular }}' => strtolower(class_basename($model)), - '{{ $modelVarPlural }}' => strtolower(Str::plural(class_basename($model))), - '{{ properties }}' => $this->transformFieldProperties($fields), - ]; - } - - /** - * @param array> $fields - */ - protected function transformFieldProperties(array $fields): string - { - return collect($fields)->map(function (array $fieldProperties, string $field): string { - $fieldType = strtolower(type($fieldProperties['type'])->asString()); - $propertyType = match ($fieldType) { - 'int', 'integer', 'bigint' => 'int', - 'tinyint' => 'bool', - 'timestamp', 'datetime' => 'Carbon', - 'json' => 'array', - default => 'string', - }; - - $nullable = $this->isFieldNullable($fieldProperties); - - if ($nullable) { - $propertyType = '?' . $propertyType; - } - $tsOptional = $nullable ? "#[TypeScriptOptional]\n\t\t" : ''; - - return $tsOptional . "public {$propertyType} \${$field}"; - })->implode(",\n\t\t"); - } - /** * @return array> */ protected function getArguments(): array { return [ - ['name', InputArgument::REQUIRED, 'The name of the ' . strtolower($this->type)], - ['resource', InputArgument::REQUIRED, 'The resource of the ' . strtolower($this->type)], + ['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)], + ['resource', InputArgument::REQUIRED, 'The resource of the '.strtolower($this->type)], ['type', InputArgument::REQUIRED, 'The type of filter to create'], ['model', InputArgument::OPTIONAL, 'The model class to use'], ['presenter', InputArgument::OPTIONAL, 'The presenter class to use'], ['fields', InputArgument::OPTIONAL, 'The fields to include in the presenter'], - ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the ' . strtolower($this->type)], + ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the '.strtolower($this->type)], ]; } @@ -173,4 +132,52 @@ protected function afterPromptingForMissingArguments(InputInterface $input, Outp $input->setOption(type($type)->asString(), true); } } + + /** + * @return array + */ + private function buildResourceReplacements(): array + { + $resourceName = type($this->argument('name'))->asString(); + $model = type($this->argument('model'))->asString(); + $fields = type($this->argument('fields') ?? [])->asArray(); + + return [ + '{{ presenterNamespace }}' => $this->argument('kit_namespace') + ? 'XtendPackages\\RESTPresenter\\'.type($this->argument('kit_namespace'))->asString().'\\Presenters\\'.$this->getNameInput().'\\'.$this->getNameInput() + : 'XtendPackages\\RESTPresenter\\Resources\\'.Str::plural($resourceName).'\\Presenters\\'.$this->getNameInput().'\\'.$this->getNameInput(), + '{{ aliasPresenter }}' => 'Xtend'.$this->getNameInput().'Presenter', + '{{ modelClassImport }}' => $model, + '{{ modelClassName }}' => class_basename($model), + '{{ $modelVarSingular }}' => strtolower(class_basename($model)), + '{{ $modelVarPlural }}' => strtolower(Str::plural(class_basename($model))), + '{{ properties }}' => $this->transformFieldProperties($fields), + ]; + } + + /** + * @param array> $fields + */ + private function transformFieldProperties(array $fields): string + { + return collect($fields)->map(function (array $fieldProperties, string $field): string { + $fieldType = strtolower(type($fieldProperties['type'])->asString()); + $propertyType = match ($fieldType) { + 'int', 'integer', 'bigint' => 'int', + 'tinyint' => 'bool', + 'timestamp', 'datetime' => 'Carbon', + 'json' => 'array', + default => 'string', + }; + + $nullable = $this->isFieldNullable($fieldProperties); + + if ($nullable) { + $propertyType = '?'.$propertyType; + } + $tsOptional = $nullable ? "#[TypeScriptOptional]\n\t\t" : ''; + + return $tsOptional."public {$propertyType} \${$field}"; + })->implode(",\n\t\t"); + } } diff --git a/src/Commands/Generator/MakeFilter.php b/src/Commands/Generator/MakeFilter.php index 4103bd8..91c021d 100644 --- a/src/Commands/Generator/MakeFilter.php +++ b/src/Commands/Generator/MakeFilter.php @@ -1,5 +1,7 @@ getDefaultNamespace($rootNamespace) . '\\' . $name; + return $this->getDefaultNamespace($rootNamespace).'\\'.$name; } protected function getStub(): string @@ -41,7 +43,7 @@ protected function getStub(): string default => 'attribute', }; - return __DIR__ . '/stubs/' . type($this->argument('type'))->asString() . '/filter/' . $filterStub . '.php.stub'; + return __DIR__.'/stubs/'.type($this->argument('type'))->asString().'/filter/'.$filterStub.'.php.stub'; } protected function getDefaultNamespace($rootNamespace): string @@ -51,10 +53,10 @@ protected function getDefaultNamespace($rootNamespace): string $namespace = type(config('rest-presenter.generator.namespace'))->asString(); if ($this->argument('kit_namespace')) { - return $namespace . '\\' . type($this->argument('kit_namespace'))->asString() . '\\Filters'; + return $namespace.'\\'.type($this->argument('kit_namespace'))->asString().'\\Filters'; } - return $namespace . '\\Resources\\' . $resourceDirectory . '\\Filters'; + return $namespace.'\\Resources\\'.$resourceDirectory.'\\Filters'; } protected function getNameInput(): string @@ -72,34 +74,34 @@ protected function buildClass($name): string } /** - * @return array + * @return array> */ - protected function buildResourceReplacements(): array + protected function getArguments(): array { - $resourceName = type($this->argument('name'))->asString(); - return [ - '{{ filterNamespace }}' => $this->argument('kit_namespace') - ? 'XtendPackages\\RESTPresenter\\' . type($this->argument('kit_namespace'))->asString() . '\\Filters\\' . $this->getNameInput() . '\\' . $this->getNameInput() - : 'XtendPackages\\RESTPresenter\\Resources\\' . Str::plural($resourceName) . '\\Filters\\' . $this->getNameInput() . '\\' . $this->getNameInput(), - '{{ aliasFilter }}' => 'Xtend' . $this->getNameInput() . 'Filter', - '{{ relationship }}' => strtolower($resourceName), - '{{ relationship_search_key }}' => type($this->argument('relation_search_key') ?? '')->asString(), + ['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)], + ['resource', InputArgument::REQUIRED, 'The resource of the '.strtolower($this->type)], + ['type', InputArgument::OPTIONAL, 'The type of filter to create'], + ['relation', InputArgument::OPTIONAL, 'The relation of the '.strtolower($this->type)], + ['relation_search_key', InputArgument::OPTIONAL, 'The search key of the '.strtolower($this->type)], + ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the '.strtolower($this->type)], ]; } /** - * @return array> + * @return array */ - protected function getArguments(): array + private function buildResourceReplacements(): array { + $resourceName = type($this->argument('name'))->asString(); + return [ - ['name', InputArgument::REQUIRED, 'The name of the ' . strtolower($this->type)], - ['resource', InputArgument::REQUIRED, 'The resource of the ' . strtolower($this->type)], - ['type', InputArgument::OPTIONAL, 'The type of filter to create'], - ['relation', InputArgument::OPTIONAL, 'The relation of the ' . strtolower($this->type)], - ['relation_search_key', InputArgument::OPTIONAL, 'The search key of the ' . strtolower($this->type)], - ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the ' . strtolower($this->type)], + '{{ filterNamespace }}' => $this->argument('kit_namespace') + ? 'XtendPackages\\RESTPresenter\\'.type($this->argument('kit_namespace'))->asString().'\\Filters\\'.$this->getNameInput().'\\'.$this->getNameInput() + : 'XtendPackages\\RESTPresenter\\Resources\\'.Str::plural($resourceName).'\\Filters\\'.$this->getNameInput().'\\'.$this->getNameInput(), + '{{ aliasFilter }}' => 'Xtend'.$this->getNameInput().'Filter', + '{{ relationship }}' => strtolower($resourceName), + '{{ relationship_search_key }}' => type($this->argument('relation_search_key') ?? '')->asString(), ]; } } diff --git a/src/Commands/Generator/MakePresenter.php b/src/Commands/Generator/MakePresenter.php index 0e47c64..f82ff84 100644 --- a/src/Commands/Generator/MakePresenter.php +++ b/src/Commands/Generator/MakePresenter.php @@ -1,5 +1,7 @@ hasArgument('fields') && is_array($this->argument('fields'))) { $name = type($this->argument('name'))->asString(); $presenter = Str::of($name)->replace('Presenter', ''); $this->call('rest-presenter:make-data', [ 'type' => 'new', - 'name' => $presenter->singular()->value() . 'Data', + 'name' => $presenter->singular()->value().'Data', 'resource' => $this->argument('resource'), 'fields' => $this->argument('fields'), 'model' => $this->argument('model'), @@ -37,6 +42,8 @@ public function handle(): void } parent::handle(); + + return null; } protected function qualifyClass($name) @@ -52,33 +59,17 @@ protected function qualifyClass($name) return $name; } - return $this->getDefaultNamespace($rootNamespace) . '\\' . $name; + return $this->getDefaultNamespace($rootNamespace).'\\'.$name; } protected function getStub(): string { - return __DIR__ . '/stubs/' . type($this->argument('type'))->asString() . '/presenter.php.stub'; + return __DIR__.'/stubs/'.type($this->argument('type'))->asString().'/presenter.php.stub'; } protected function getDefaultNamespace($rootNamespace): string { - return config('rest-presenter.generator.namespace') . '\\' . $this->getPresenterNamespace(); - } - - protected function getPresenterNamespace(): string - { - $resourceName = type($this->argument('resource'))->asString(); - $presenterName = type($this->argument('name'))->asString(); - $resourceDirectory = 'Resources\\' . Str::plural($resourceName); - $presenterNamespace = Str::of($presenterName) - ->replace('Presenter', '') - ->plural() - ->value(); - - $resourceNamespace = $this->argument('kit_namespace') ?: $resourceDirectory; - - $resourceNamespace = type($resourceNamespace)->asString(); - return $resourceNamespace . '\\Presenters\\' . $presenterNamespace; + return config('rest-presenter.generator.namespace').'\\'.$this->getPresenterNamespace(); } protected function getNameInput(): string @@ -95,39 +86,18 @@ protected function buildClass($name): string ); } - /** - * @return array - */ - protected function buildResourceReplacements(): array - { - $name = type($this->argument('name'))->asString(); - $model = type($this->argument('model'))->asString(); - - return [ - '{{ presenterNamespace }}' => $this->argument('kit_namespace') - ? 'XtendPackages\\RESTPresenter\\' . type($this->argument('kit_namespace'))->asString() . '\\Presenters\\' . $this->getNameInput() . '\\' . $this->getNameInput() - : 'XtendPackages\\RESTPresenter\\Resources\\' . Str::plural($name) . '\\Presenters\\' . $this->getNameInput() . '\\' . $this->getNameInput(), - '{{ aliasPresenter }}' => 'Xtend' . $this->getNameInput() . 'Presenter', - '{{ modelClassImport }}' => $model, - '{{ modelClassName }}' => class_basename($model), - '{{ $modelVarSingular }}' => strtolower(class_basename($model)), - '{{ $modelVarPlural }}' => strtolower(Str::plural(class_basename($model))), - '{{ dataClass }}' => Str::of($name)->remove('Presenter')->append('Data')->value(), - ]; - } - /** * @return array> */ protected function getArguments(): array { return [ - ['name', InputArgument::REQUIRED, 'The name of the ' . strtolower($this->type)], + ['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)], ['type', InputArgument::REQUIRED, 'The type of filter to create'], - ['resource', InputArgument::OPTIONAL, 'The resource of the ' . strtolower($this->type)], + ['resource', InputArgument::OPTIONAL, 'The resource of the '.strtolower($this->type)], ['model', InputArgument::OPTIONAL, 'The model class to use'], ['fields', InputArgument::OPTIONAL, 'The fields to include in the presenter'], - ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the ' . strtolower($this->type)], + ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the '.strtolower($this->type)], ]; } @@ -159,4 +129,42 @@ protected function afterPromptingForMissingArguments(InputInterface $input, Outp $input->setOption(type($type)->asString(), true); } } + + private function getPresenterNamespace(): string + { + $resourceName = type($this->argument('resource'))->asString(); + $presenterName = type($this->argument('name'))->asString(); + $resourceDirectory = 'Resources\\'.Str::plural($resourceName); + $presenterNamespace = Str::of($presenterName) + ->replace('Presenter', '') + ->plural() + ->value(); + + $resourceNamespace = $this->argument('kit_namespace') ?: $resourceDirectory; + + $resourceNamespace = type($resourceNamespace)->asString(); + + return $resourceNamespace.'\\Presenters\\'.$presenterNamespace; + } + + /** + * @return array + */ + private function buildResourceReplacements(): array + { + $name = type($this->argument('name'))->asString(); + $model = type($this->argument('model'))->asString(); + + return [ + '{{ presenterNamespace }}' => $this->argument('kit_namespace') + ? 'XtendPackages\\RESTPresenter\\'.type($this->argument('kit_namespace'))->asString().'\\Presenters\\'.$this->getNameInput().'\\'.$this->getNameInput() + : 'XtendPackages\\RESTPresenter\\Resources\\'.Str::plural($name).'\\Presenters\\'.$this->getNameInput().'\\'.$this->getNameInput(), + '{{ aliasPresenter }}' => 'Xtend'.$this->getNameInput().'Presenter', + '{{ modelClassImport }}' => $model, + '{{ modelClassName }}' => class_basename($model), + '{{ $modelVarSingular }}' => strtolower(class_basename($model)), + '{{ $modelVarPlural }}' => strtolower(Str::plural(class_basename($model))), + '{{ dataClass }}' => Str::of($name)->remove('Presenter')->append('Data')->value(), + ]; + } } diff --git a/src/Commands/Generator/MakeResource.php b/src/Commands/Generator/MakeResource.php index f1cc92e..9688f50 100644 --- a/src/Commands/Generator/MakeResource.php +++ b/src/Commands/Generator/MakeResource.php @@ -1,5 +1,7 @@ */ - protected Collection $actions; + private Collection $actions; /** * @var \Illuminate\Support\Collection */ - protected Collection $filters; + private Collection $filters; /** * @var \Illuminate\Support\Collection */ - protected Collection $presenters; + private Collection $presenters; /** * @var \Illuminate\Support\Collection */ - protected Collection $presentersArgument; + private Collection $presentersArgument; - public function handle(): void + /** + * {@inheritdoc} + */ + public function handle(): ?bool { $this->actions ??= collect(); $this->filters ??= collect(); @@ -91,7 +96,7 @@ public function handle(): void fn (mixed $fields, string $presenter) => $this->call( command: 'rest-presenter:make-presenter', arguments: [ - 'name' => $presenter . 'Presenter', + 'name' => $presenter.'Presenter', 'type' => 'new', 'model' => $this->argument('model'), 'resource' => Str::plural($name), @@ -101,23 +106,13 @@ public function handle(): void ); parent::handle(); - } - protected function guessRelationSearchKey(string $filter): ?string - { - if (! $relationTable = $this->findTableByName(table: $filter, exactMatch: false)) { - return null; - } - - return $this->getTableColumnsForRelation( - table: type($relationTable)->asString(), - exclude: ['id', 'created_at', 'updated_at'], - )->first(); + return null; } protected function getStub(): string { - return __DIR__ . '/stubs/' . type($this->argument('type'))->asString() . '/resource.controller.php.stub'; + return __DIR__.'/stubs/'.type($this->argument('type'))->asString().'/resource.controller.php.stub'; } protected function getDefaultNamespace($rootNamespace): string @@ -128,16 +123,18 @@ protected function getDefaultNamespace($rootNamespace): string if ($this->argument('kit_namespace')) { $namespace = type(config('rest-presenter.generator.namespace'))->asString(); $kitNamespace = type($this->argument('kit_namespace'))->asString(); - return $namespace . '\\' . $kitNamespace; + + return $namespace.'\\'.$kitNamespace; } - return config('rest-presenter.generator.namespace') . '\\Resources\\' . $resourceDirectory; + return config('rest-presenter.generator.namespace').'\\Resources\\'.$resourceDirectory; } protected function getNameInput(): string { $name = type($this->argument('name'))->asString(); - return trim($name) . 'ResourceController'; + + return trim($name).'ResourceController'; } protected function buildClass($name): string @@ -149,52 +146,107 @@ protected function buildClass($name): string ); } + /** + * @return array> + */ + protected function getArguments(): array + { + return [ + ['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)], + ['type', InputArgument::REQUIRED, 'The type of resource to create'], + ['model', InputArgument::OPTIONAL, 'The model that the resource references'], + ['filters', InputArgument::OPTIONAL, 'The filters to include in the resource'], + ['presenters', InputArgument::OPTIONAL, 'The presenters to include in the resource'], + ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the '.strtolower($this->type)], + ]; + } + + /** + * @return array> + */ + protected function promptForMissingArgumentsUsing(): array + { + return [ + 'name' => [ + 'Whats the name of your resource? (singular)', + 'e.g. Post', + ], + ]; + } + + protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void + { + if ($this->didReceiveOptions($input)) { + return; + } + + $this->promptForResourceType($input); + $this->promptForModel($input); + $this->promptForFilters($input); + $this->promptForPresenters($input); + } + + private function guessRelationSearchKey(string $filter): ?string + { + if (! $relationTable = $this->findTableByName(table: $filter, exactMatch: false)) { + return null; + } + + /** @var string $columns */ + $columns = $this->getTableColumnsForRelation( + table: type($relationTable)->asString(), + exclude: ['id', 'created_at', 'updated_at'], + )->first(); + + return $columns; + } + /** * @return array */ - protected function buildResourceReplacements(): array - {; + private function buildResourceReplacements(): array + { $modelName = type($this->argument('model'))->asString(); $modelClass = Str::of(class_basename($modelName)); return [ '{{ resourceNamespace }}' => $this->argument('kit_namespace') - ? 'XtendPackages\\RESTPresenter\\' . type($this->argument('kit_namespace'))->asString() . '\\' . $this->getNameInput() - : 'XtendPackages\\RESTPresenter\\Resources\\' . Str::plural($modelName) . '\\' . $this->getNameInput(), - '{{ aliasResource }}' => 'Xtend' . $this->getNameInput(), + ? 'XtendPackages\\RESTPresenter\\'.type($this->argument('kit_namespace'))->asString().'\\'.$this->getNameInput() + : 'XtendPackages\\RESTPresenter\\Resources\\'.Str::plural($modelName).'\\'.$this->getNameInput(), + '{{ aliasResource }}' => 'Xtend'.$this->getNameInput(), '{{ modelClassImport }}' => $modelName, '{{ modelClassName }}' => $modelClass->value(), - '{{ $modelVarSingular }}' => $modelClass->lcfirst(), - '{{ $modelVarPlural }}' => $modelClass->plural()->lcfirst(), + '{{ $modelVarSingular }}' => $modelClass->lcfirst()->value(), + '{{ $modelVarPlural }}' => $modelClass->plural()->lcfirst()->value(), '{{ actions }}' => $this->transformActions(), '{{ filters }}' => $this->transformFilters(), '{{ presenters }}' => $this->transformPresenters(), ]; } - protected function transformActions(): string + private function transformActions(): string { if ($this->actions->isEmpty()) { return ''; } return $this->actions->map( - fn ($action): string => "'$action' => Actions\\" . ucfirst($action) . '::class', - )->implode(",\n\t\t\t") . ','; + fn ($action): string => "'$action' => Actions\\".ucfirst($action).'::class', + )->implode(",\n\t\t\t").','; } - protected function transformFilters(): string + private function transformFilters(): string { if ($this->filters->isEmpty()) { return ''; } return $this->filters->map( - fn ($filter): string => "'$filter' => Filters\\" . ucfirst($filter) . '::class', - )->implode(",\n\t\t\t") . ','; + fn ($filter): string => "'$filter' => Filters\\".ucfirst($filter).'::class', + )->implode(",\n\t\t\t").','; } - protected function transformPresenters(): string + private function transformPresenters(): string { if (! $this->hasPresenters()) { return ''; @@ -208,12 +260,12 @@ function (string $presenter, $presenterKey): string { ->plural() ->value(); - return "'$presenterKey' => Presenters\\" . $presenterNamespace . '\\' . $presenter; + return "'$presenterKey' => Presenters\\".$presenterNamespace.'\\'.$presenter; }, - )->implode(",\n\t\t\t") . ','; + )->implode(",\n\t\t\t").','; } - protected function hasPresenters(): bool + private function hasPresenters(): bool { return $this->getPresenters()->isNotEmpty(); } @@ -221,7 +273,7 @@ protected function hasPresenters(): bool /** * @return \Illuminate\Support\Collection */ - protected function getPresenters(): Collection + private function getPresenters(): Collection { if ($this->argument('presenters') && is_array($this->argument('presenters'))) { return collect($this->argument('presenters')); @@ -230,47 +282,7 @@ protected function getPresenters(): Collection return $this->presentersArgument; } - /** - * @return array> - */ - protected function getArguments(): array - { - return [ - ['name', InputArgument::REQUIRED, 'The name of the ' . strtolower($this->type)], - ['type', InputArgument::REQUIRED, 'The type of resource to create'], - ['model', InputArgument::OPTIONAL, 'The model that the resource references'], - ['filters', InputArgument::OPTIONAL, 'The filters to include in the resource'], - ['presenters', InputArgument::OPTIONAL, 'The presenters to include in the resource'], - ['kit_namespace', InputArgument::OPTIONAL, 'The namespace of the ' . strtolower($this->type)], - ]; - } - - /** - * @return array> - */ - protected function promptForMissingArgumentsUsing(): array - { - return [ - 'name' => [ - 'Whats the name of your resource? (singular)', - 'e.g. Post', - ], - ]; - } - - protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void - { - if ($this->didReceiveOptions($input)) { - return; - } - - $this->promptForResourceType($input); - $this->promptForModel($input); - $this->promptForFilters($input); - $this->promptForPresenters($input); - } - - protected function promptForResourceType(InputInterface $input): void + private function promptForResourceType(InputInterface $input): void { $type = select('Which type of resource would you like to create?', [ 'new' => 'New resource', @@ -280,7 +292,7 @@ protected function promptForResourceType(InputInterface $input): void $input->setArgument('type', $type); } - protected function promptForModel(InputInterface $input): void + private function promptForModel(InputInterface $input): void { $model = search( label: 'Which model should the resource use?', @@ -295,7 +307,7 @@ protected function promptForModel(InputInterface $input): void $input->setArgument('model', $model); } - protected function promptForFilters(InputInterface $input): void + private function promptForFilters(InputInterface $input): void { $suggestFilters = $this->generateFilterSuggestions(); @@ -322,7 +334,7 @@ protected function promptForFilters(InputInterface $input): void } } - protected function promptForCustomFilters(InputInterface $input): void + private function promptForCustomFilters(InputInterface $input): void { $customFilter = text( label: 'Enter the custom filter you would like to add to your resource:', @@ -343,7 +355,7 @@ protected function promptForCustomFilters(InputInterface $input): void } } - protected function promptForPresenters(InputInterface $input, bool $init = true): void + private function promptForPresenters(InputInterface $input, bool $init = true): void { $setupPresenters = select( label: 'Would you like to setup presenters for this resource?', @@ -383,7 +395,7 @@ protected function promptForPresenters(InputInterface $input, bool $init = true) ->kebab() ->value(); - $this->presentersArgument->put($presenterKey, $presenterName . 'Presenter::class'); + $this->presentersArgument->put($presenterKey, $presenterName.'Presenter::class'); $addAnother = select( label: 'Add another custom presenter?', @@ -397,9 +409,9 @@ protected function promptForPresenters(InputInterface $input, bool $init = true) } /** - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection> */ - protected function generateModelFields(): Collection + private function generateModelFields(): Collection { $table = $this->model->getTable(); @@ -409,7 +421,7 @@ protected function generateModelFields(): Collection ); } - protected function setModel(string $model): void + private function setModel(string $model): void { $this->model = resolve($model); } @@ -417,7 +429,7 @@ protected function setModel(string $model): void /** * @return \Illuminate\Support\Collection */ - protected function generateFilterSuggestions(): Collection + private function generateFilterSuggestions(): Collection { $reflect = new ReflectionClass($this->model); @@ -431,7 +443,7 @@ protected function generateFilterSuggestions(): Collection $returnNamedType = $method->getReturnType() instanceof ReflectionNamedType ? $method->getReturnType()->getName() : ''; return [ - $method->getName() . '=>' . class_basename($returnNamedType) => $method->getName(), + $method->getName().'=>'.class_basename($returnNamedType) => $method->getName(), ]; }); } @@ -439,14 +451,14 @@ protected function generateFilterSuggestions(): Collection /** * @return array */ - protected function scanModels(): array + private function scanModels(): array { return collect(app('files')->allFiles(app_path())) ->filter(fn (SplFileInfo $file) => Str::endsWith($file->getFilename(), '.php')) ->map(fn (SplFileInfo $file): string => $file->getRelativePathname()) - ->map(fn (string $file) => 'App\\' . str_replace(['/', '.php'], ['\\', ''], $file)) + ->map(fn (string $file) => 'App\\'.str_replace(['/', '.php'], ['\\', ''], $file)) ->filter(fn (string $class): bool => class_exists($class)) - ->map(fn (string $class): \ReflectionClass => new ReflectionClass($class)) + ->map(fn (string $class): ReflectionClass => new ReflectionClass($class)) ->filter(fn (ReflectionClass $class) => $class->isSubclassOf(Model::class)) ->mapWithKeys(fn (ReflectionClass $class): array => [$class->getName() => $class->getShortName()]) ->toArray(); diff --git a/src/Commands/Generator/Writers/ModuleWriter.php b/src/Commands/Generator/Writers/ModuleWriter.php index 8807b8c..88061f8 100644 --- a/src/Commands/Generator/Writers/ModuleWriter.php +++ b/src/Commands/Generator/Writers/ModuleWriter.php @@ -1,24 +1,28 @@ $iterator */ + /** @var ArrayIterator $iterator */ $iterator = $collection->getIterator(); - $iterator->uasort(fn(TransformedType $a, TransformedType $b): int => strcmp(type($a->name)->asString(), type($b->name)->asString())); + $iterator->uasort(fn (TransformedType $a, TransformedType $b): int => strcmp(type($a->name)->asString(), type($b->name)->asString())); foreach ($iterator as $type) { /** @var TransformedType $type */ @@ -29,7 +33,7 @@ public function format(TypesCollection $collection): string $type->keyword = type(config('rest-presenter.generator.ts_types_keyword'))->asString(); $type->trailingSemicolon = type(config('rest-presenter.generator.ts_types_trailing_semicolon'))->asBool(); - $output .= "export {$type->toString()}" . PHP_EOL; + $output .= "export {$type->toString()}".PHP_EOL; } return $output; diff --git a/src/Commands/RESTPresenterSetupCommand.php b/src/Commands/RESTPresenterSetupCommand.php index 276c529..68cfa74 100644 --- a/src/Commands/RESTPresenterSetupCommand.php +++ b/src/Commands/RESTPresenterSetupCommand.php @@ -1,5 +1,7 @@ components->info('Welcome to REST Presenter setup wizard'); @@ -51,7 +53,7 @@ protected function initialSetup(): void $this->publishStarterKits(); } - protected function starGitHubRepo(): void + private function starGitHubRepo(): void { if (confirm('Please star this project on GitHub 🤩')) { $repoUrl = 'https://github.com/xtend-packages/rest-presenter'; @@ -67,7 +69,7 @@ protected function starGitHubRepo(): void } } - protected function sponsorThisProject(): void + private function sponsorThisProject(): void { if (confirm('Show your support 💙 for Adam Lee and sponsor this project')) { $authorUrl = 'https://github.com/sponsors/adam-code-labx'; @@ -83,12 +85,12 @@ protected function sponsorThisProject(): void } } - protected function publishingConfig(): void + private function publishingConfig(): void { $this->call('vendor:publish', ['--tag' => 'rest-presenter-config']); } - protected function publishingServiceProvider(): void + private function publishingServiceProvider(): void { $this->call('vendor:publish', ['--tag' => 'rest-presenter-provider']); @@ -101,29 +103,29 @@ protected function publishingServiceProvider(): void call_user_func($callable, 'App\\Providers\\RESTPresenterServiceProvider', $providersPath); } - protected function publishingDefaultResources(): void + private function publishingDefaultResources(): void { - collect($this->filesystem->directories(__DIR__ . '/../Resources')) + collect($this->filesystem->directories(__DIR__.'/../Resources')) ->map(fn ($resource) => Str::singular(basename((string) $resource))) ->each(fn ($resource) => $this->call('rest-presenter:make-resource', [ - 'model' => 'App\\Models\\' . Str::singular($resource), + 'model' => 'App\\Models\\'.Str::singular($resource), 'name' => $resource, 'type' => 'new', ])); } - protected function publishStarterKits(): void + private function publishStarterKits(): void { - $starterKitsDirectory = __DIR__ . '/../StarterKits'; - $generatedKitsDirectory = config('rest-presenter.generator.path') . '/StarterKits'; + $starterKitsDirectory = __DIR__.'/../StarterKits'; + $generatedKitsDirectory = config('rest-presenter.generator.path').'/StarterKits'; $this->filesystem->ensureDirectoryExists($generatedKitsDirectory); /** @var \Illuminate\Support\Collection $unpublishedStarterKits */ $unpublishedStarterKits = collect($this->filesystem->allFiles($starterKitsDirectory)) ->map(fn ($file): string => $file->getRelativePathname()) - ->filter(fn ($file): bool => ! $this->filesystem->exists($generatedKitsDirectory . '/' . $file)) + ->filter(fn ($file): bool => ! $this->filesystem->exists($generatedKitsDirectory.'/'.$file)) ->filter(fn ($file): bool => str_ends_with($file, 'ApiKitServiceProvider.php')) - ->map(fn ($file): string|array => str_replace('ApiKitServiceProvider.php', '', basename($file))) + ->map(fn ($file): string => str_replace('ApiKitServiceProvider.php', '', basename($file))) ->map(fn ($kit): string => $kit) ->values(); @@ -148,14 +150,14 @@ protected function publishStarterKits(): void } } - protected function firstTimeSetup(): bool + private function firstTimeSetup(): bool { return ! $this->filesystem->exists( path: type(config('rest-presenter.generator.path'))->asString(), ); } - protected function checkForUpdates(): void + private function checkForUpdates(): void { $this->components->info('Checking for updates...'); } diff --git a/src/Commands/XtendStarterKit.php b/src/Commands/XtendStarterKit.php index 908b695..4f94d86 100644 --- a/src/Commands/XtendStarterKit.php +++ b/src/Commands/XtendStarterKit.php @@ -1,5 +1,7 @@ argument('name'))->asString(); - $starterKitsDirectory = __DIR__ . '/../StarterKits'; - $generatedKitsDirectory = config('rest-presenter.generator.path') . '/StarterKits'; + $starterKitsDirectory = __DIR__.'/../StarterKits'; + $generatedKitsDirectory = config('rest-presenter.generator.path').'/StarterKits'; $kitFindPath = collect($this->filesystem->allFiles($starterKitsDirectory)) ->filter(fn ($file) => Str::startsWith($file->getFilename(), $name)) ->first(); @@ -43,12 +45,12 @@ public function handle(): int return self::FAILURE; } - $this->generateStarterKit($starterKitsDirectory, $generatedKitsDirectory, $kitPath); + $this->generateStarterKit($starterKitsDirectory, $kitPath); return self::SUCCESS; } - protected function generateStarterKit(string $starterKitsDirectory, string $generatedKitsDirectory, string $kitPath): void + private function generateStarterKit(string $starterKitsDirectory, string $kitPath): void { $this->extendControllers($starterKitsDirectory, $kitPath); $this->extendResources($starterKitsDirectory, $kitPath); @@ -56,11 +58,11 @@ protected function generateStarterKit(string $starterKitsDirectory, string $gene $this->autoDiscoverResources($kitPath); } - protected function extendControllers(string $starterKitsDirectory, string $kitPath): void + private function extendControllers(string $starterKitsDirectory, string $kitPath): void { $kitPath = Str::of($kitPath)->beforeLast('/Base')->value(); if ($this->kitCanExtendControllers($starterKitsDirectory, $kitPath)) { - collect($this->filesystem->allFiles($starterKitsDirectory . '/' . $kitPath . '/Http/Controllers')) + collect($this->filesystem->allFiles($starterKitsDirectory.'/'.$kitPath.'/Http/Controllers')) ->filter(fn (SplFileInfo $file) => Str::endsWith($file->getFilename(), 'Controller.php')) ->each(function (SplFileInfo $file) use ($kitPath): void { $path = $file->getRelativePathName(); @@ -78,22 +80,22 @@ protected function extendControllers(string $starterKitsDirectory, string $kitPa } } - protected function extendResources(string $starterKitsDirectory, string $kitPath): void + private function extendResources(string $starterKitsDirectory, string $kitPath): void { $kitPath = Str::of($kitPath)->beforeLast('/Base')->value(); if ($this->kitCanExtendResources($starterKitsDirectory, $kitPath)) { - collect($this->filesystem->allFiles($starterKitsDirectory . '/' . $kitPath . '/Resources')) + collect($this->filesystem->allFiles($starterKitsDirectory.'/'.$kitPath.'/Resources')) ->filter(fn (SplFileInfo $file) => Str::endsWith($file->getFilename(), 'ResourceController.php')) ->each(function (SplFileInfo $file) use ($starterKitsDirectory, $kitPath): void { $path = $file->getRelativePath(); $kitNamespace = Str::of($kitPath) ->replace('/', '\\')->prepend('StarterKits\\') - ->append('\\Resources\\' . Str::of($path)->replace('/', '\\')->beforeLast('\\')) + ->append('\\Resources\\'.Str::of($path)->replace('/', '\\')->beforeLast('\\')) ->value(); $resource = basename($path); - $resourcePath = $kitPath . '/Resources/' . $path; - $kitNamespace .= class_basename($resource) !== $path ? '\\' . $resource : ''; + $resourcePath = $kitPath.'/Resources/'.$path; + $kitNamespace .= class_basename($resource) !== $path ? '\\'.$resource : ''; $this->extendActions($starterKitsDirectory, $resourcePath, $kitNamespace); $this->extendPresenters($starterKitsDirectory, $resourcePath, $kitNamespace); @@ -108,7 +110,7 @@ protected function extendResources(string $starterKitsDirectory, string $kitPath } } - protected function autoDiscoverResources(string $kitPath): void + private function autoDiscoverResources(string $kitPath): void { $kitNamespace = Str::of($kitPath)->replace('/', '\\')->value(); $supportedKit = match ($kitNamespace) { @@ -123,7 +125,7 @@ protected function autoDiscoverResources(string $kitPath): void } /** @var \XtendPackages\RESTPresenter\Base\StarterKit $starterKit */ - $starterKit = resolve('XtendPackages\\RESTPresenter\\StarterKits\\' . $kitNamespace . '\\' . $supportedKit); + $starterKit = resolve('XtendPackages\\RESTPresenter\\StarterKits\\'.$kitNamespace.'\\'.$supportedKit); $resources = $starterKit->autoDiscover(); if (! $resources) { @@ -147,8 +149,8 @@ protected function autoDiscoverResources(string $kitPath): void $this->call( command: 'rest-presenter:make-presenter', arguments: [ - 'kit_namespace' => $kitNamespace . '\\' . $resourceNamespace, - 'name' => $resourceName . 'Presenter', + 'kit_namespace' => $kitNamespace.'\\'.$resourceNamespace, + 'name' => $resourceName.'Presenter', 'type' => 'new', 'model' => $resource['model'], 'resource' => $resourceName, @@ -161,11 +163,11 @@ protected function autoDiscoverResources(string $kitPath): void ->value(); $this->call('rest-presenter:make-resource', [ - 'kit_namespace' => $kitNamespace . '\\' . $resourceNamespace, + 'kit_namespace' => $kitNamespace.'\\'.$resourceNamespace, 'name' => $resourceName, 'model' => $resource['model'], 'presenters' => [ - $resourceKey => $resourceName . 'Presenter::class', + $resourceKey => $resourceName.'Presenter::class', ], 'type' => 'new', ]); @@ -173,15 +175,15 @@ protected function autoDiscoverResources(string $kitPath): void }); } - protected function extendActions(string $starterKitsDirectory, string $resourcePath, string $kitNamespace): void + private function extendActions(string $starterKitsDirectory, string $resourcePath, string $kitNamespace): void { - if (! $this->filesystem->exists($starterKitsDirectory . '/' . $resourcePath . '/Actions')) { + if (! $this->filesystem->exists($starterKitsDirectory.'/'.$resourcePath.'/Actions')) { $this->components->warn(__('No actions were found for this kit :kit_namespace', ['kit_namespace' => $kitNamespace])); return; } - collect($this->filesystem->directories($starterKitsDirectory . '/' . $resourcePath . '/Actions')) + collect($this->filesystem->directories($starterKitsDirectory.'/'.$resourcePath.'/Actions')) ->each(function ($path) use ($kitNamespace): void { $action = basename($path); @@ -193,15 +195,15 @@ protected function extendActions(string $starterKitsDirectory, string $resourceP }); } - protected function extendPresenters(string $starterKitsDirectory, string $resourcePath, string $kitNamespace): void + private function extendPresenters(string $starterKitsDirectory, string $resourcePath, string $kitNamespace): void { - if (! $this->filesystem->exists($starterKitsDirectory . '/' . $resourcePath . '/Presenters')) { + if (! $this->filesystem->exists($starterKitsDirectory.'/'.$resourcePath.'/Presenters')) { $this->components->warn(__('No presenters were found for this kit :kit_namespace', ['kit_namespace' => $kitNamespace])); return; } - collect($this->filesystem->directories($starterKitsDirectory . '/' . $resourcePath . '/Presenters')) + collect($this->filesystem->directories($starterKitsDirectory.'/'.$resourcePath.'/Presenters')) ->each(function ($path) use ($kitNamespace): void { $presenter = basename($path); @@ -213,18 +215,18 @@ protected function extendPresenters(string $starterKitsDirectory, string $resour }); } - protected function kitCanExtendControllers(string $starterKitsDirectory, string $kitPath): bool + private function kitCanExtendControllers(string $starterKitsDirectory, string $kitPath): bool { - return $this->filesystem->exists($starterKitsDirectory . '/' . $kitPath . '/Http/Controllers'); + return $this->filesystem->exists($starterKitsDirectory.'/'.$kitPath.'/Http/Controllers'); } - protected function kitCanExtendResources(string $starterKitsDirectory, string $kitPath): bool + private function kitCanExtendResources(string $starterKitsDirectory, string $kitPath): bool { - return $this->filesystem->exists($starterKitsDirectory . '/' . $kitPath . '/Resources'); + return $this->filesystem->exists($starterKitsDirectory.'/'.$kitPath.'/Resources'); } - protected function kitAlreadyExtended(string $generatedKitsDirectory, string $kitPath): bool + private function kitAlreadyExtended(string $generatedKitsDirectory, string $kitPath): bool { - return $this->filesystem->exists($generatedKitsDirectory . '/' . $kitPath); + return $this->filesystem->exists($generatedKitsDirectory.'/'.$kitPath); } } diff --git a/src/Concerns/InteractsWithDbSchema.php b/src/Concerns/InteractsWithDbSchema.php index b5be55c..f1d91b3 100644 --- a/src/Concerns/InteractsWithDbSchema.php +++ b/src/Concerns/InteractsWithDbSchema.php @@ -1,5 +1,7 @@ + * @return \Illuminate\Support\Collection> */ protected function getTableColumns(string $table, bool $withProperties = false): Collection { if (DB::connection()->getDriverName() === 'sqlite' && $withProperties) { return $this->replaceJsonColumnsSqliteWorkaround($table); } + return collect($withProperties ? Schema::getColumns($table) : Schema::getColumnListing($table), @@ -33,12 +36,12 @@ protected function getTableColumns(string $table, bool $withProperties = false): /** * @param array $exclude - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection> */ protected function getTableColumnsForRelation(string $table, array $exclude = []): Collection { return $this->getTableColumns($table)->filter( - fn (string $column): bool => ! in_array($column, $exclude), + fn (string $column): bool => ! in_array($column, $exclude), // @phpstan-ignore-line ); } diff --git a/src/Concerns/InteractsWithModel.php b/src/Concerns/InteractsWithModel.php index 62f90c8..9559e62 100644 --- a/src/Concerns/InteractsWithModel.php +++ b/src/Concerns/InteractsWithModel.php @@ -1,5 +1,7 @@ replace('XtendPackages\RESTPresenter', '') ->replace('\\', '/') ->prepend(app()->path('Api')) - ->append('.php'); + ->append('.php') + ->value(); return file_exists($extendPresenterFile) ? $xtendPresenter : $fromRequest; } @@ -51,11 +55,11 @@ protected function getPresenters(): array { return array_merge([ 'default' => ResourceDefaultPresenter::class, - ], method_exists($this, 'presenters') ? $this->presenters() : []); + ], method_exists($this, 'presenters') ? $this->presenters() : []); // @phpstan-ignore-line } /** - * @throws \Exception + * @throws Exception */ protected function getPresenterFromRequestHeader(): string { diff --git a/src/Concerns/InteractsWithRequest.php b/src/Concerns/InteractsWithRequest.php index fc3406b..ed8584e 100644 --- a/src/Concerns/InteractsWithRequest.php +++ b/src/Concerns/InteractsWithRequest.php @@ -1,5 +1,7 @@ each(function ($controller, $name) use ($isKit, $namespace) { $kit = Str::of($controller) - ->remove($namespace . '\\StarterKits\\') + ->remove($namespace.'\\StarterKits\\') ->remove('Auth\\') ->before('\\') ->lower() ->value(); - $routeName = $isKit ? $kit . '.' : null; - if ($routeName === null || $routeName === '' || $routeName === '0') { + $routeName = $isKit ? $kit.'.' : null; + if (! $routeName) { return null; } @@ -64,8 +66,9 @@ private function registerActionRoutes(string $controller): void /** @var ResourceController $resource */ $resource = $this->getXtendResourceController($controller); + // @phpstan-ignore-next-line collect($resource->routeActions()) - ->each(fn($controller, $name) => Route::match($controller::$method, $name, $controller) // @phpstan-ignore-line + ->each(fn ($controller, $name) => Route::match($controller::$method, $name, $controller) // @phpstan-ignore-line ->middleware($controller::$middleware ?? []) // @phpstan-ignore-line ->name($name)); } @@ -83,15 +86,17 @@ private function isResourceOnlyActionRoutes(string $controller): bool private function getXtendResourceController(string $controller): ResourceController { $name = type($this->getXtendResourceControllerClass($controller))->asString(); + return resolve($name, [ 'request' => request(), 'init' => false, ]); } - private function getXtendResourceControllerClass(string $controller): string | ResourceController + private function getXtendResourceControllerClass(string $controller): string|ResourceController { $namespace = type(config('rest-presenter.generator.namespace'))->asString(); + return Str::of($controller) ->replace($namespace, 'XtendPackages\\RESTPresenter') ->value(); diff --git a/src/Concerns/WithResourceFiltering.php b/src/Concerns/WithResourceFiltering.php index 7aeac93..8d63565 100644 --- a/src/Concerns/WithResourceFiltering.php +++ b/src/Concerns/WithResourceFiltering.php @@ -1,5 +1,7 @@ $query */ protected function applyFilters(Builder $query): mixed diff --git a/src/Concerns/WithResourcePagination.php b/src/Concerns/WithResourcePagination.php index 878557c..f0f5108 100644 --- a/src/Concerns/WithResourcePagination.php +++ b/src/Concerns/WithResourcePagination.php @@ -1,5 +1,7 @@ argument('name'))->asString()) ->kebab() - ->prepend(config('rest-presenter.generator.ts_types_path') . '/') + ->prepend(config('rest-presenter.generator.ts_types_path').'/') ->append('.d.ts') ->value(); } @@ -58,7 +60,7 @@ protected function ensureSpatieEnumTransformerIsRemoved(): void /** @var array $transformerArray */ $transformerArray = $transformersFromConfig['transformers']; - $transformers = collect($transformerArray)->reject(fn($transformer): bool => $transformer === \Spatie\TypeScriptTransformer\Transformers\SpatieEnumTransformer::class)->values()->all(); + $transformers = collect($transformerArray)->reject(fn ($transformer): bool => $transformer === \Spatie\TypeScriptTransformer\Transformers\SpatieEnumTransformer::class)->values()->all(); $this->config->set('typescript-transformer.transformers', $transformers); } diff --git a/src/Contracts/Presentable.php b/src/Contracts/Presentable.php index e0c5313..490a6e4 100644 --- a/src/Contracts/Presentable.php +++ b/src/Contracts/Presentable.php @@ -1,5 +1,7 @@ |null $attributes */ public function __construct( public mixed $id, - public Optional | string | null $name, - public Carbon | Optional | null $createdAt, - public Carbon | Optional | null $updatedAt, + public Optional|string|null $name, + public Carbon|Optional|null $createdAt, + public Carbon|Optional|null $updatedAt, public ?array $attributes, ) { } diff --git a/src/Exceptions/PresenterNotFoundException.php b/src/Exceptions/PresenterNotFoundException.php index eb617e7..457c768 100644 --- a/src/Exceptions/PresenterNotFoundException.php +++ b/src/Exceptions/PresenterNotFoundException.php @@ -1,10 +1,12 @@ */ -class User extends Authenticatable +final class User extends Authenticatable { use HasApiTokens; use HasFactory; @@ -46,6 +48,7 @@ protected static function newFactory(): UserFactory { return UserFactory::new(); } + /** * The attributes that should be cast. * diff --git a/src/RESTPresenterServiceProvider.php b/src/RESTPresenterServiceProvider.php index 3852314..39072f3 100644 --- a/src/RESTPresenterServiceProvider.php +++ b/src/RESTPresenterServiceProvider.php @@ -1,5 +1,7 @@ app->singleton('rest-presenter', fn(): \XtendPackages\RESTPresenter\Base\RESTPresenter => new RESTPresenter()); + $this->app->singleton('rest-presenter', fn (): \XtendPackages\RESTPresenter\Base\RESTPresenter => new RESTPresenter()); - $this->app->bind('xtend-router', fn(Application $app): \XtendPackages\RESTPresenter\Support\XtendRouter => new Support\XtendRouter($app['events'], $app)); + $this->app->bind('xtend-router', fn (Application $app): \XtendPackages\RESTPresenter\Support\XtendRouter => new Support\XtendRouter($app['events'], $app)); XtendRoute::register(); } diff --git a/src/Resources/ResourceController.php b/src/Resources/ResourceController.php index 18b60d5..d933a6a 100644 --- a/src/Resources/ResourceController.php +++ b/src/Resources/ResourceController.php @@ -1,7 +1,10 @@ getModelQuery(); - $this->sorts = type($request->sorts ?? [])->asArray(); $this->applyFilters($query); @@ -45,15 +47,15 @@ protected function init(Request $request): void } /** - * @throws \Exception + * @throws Exception */ protected function setModelForResource(): void { if (static::$model === Model::class) { - $userModelFromConfig = type(config('rest-presenter.resources.user.model'))->as(Model::class); + $userModelFromConfig = type(config('rest-presenter.resources.user.model'))->asString(); match (class_basename(static::class)) { 'AuthResourceController', 'UserResourceController' => $this->setModel($userModelFromConfig), - default => throw new \Exception('Model not found for resource controller'), + default => throw new Exception('Model not found for resource controller'), }; } } diff --git a/src/Resources/Users/Data/Response/ProfileData.php b/src/Resources/Users/Data/Response/ProfileData.php index bfa09e7..c0fe9b0 100644 --- a/src/Resources/Users/Data/Response/ProfileData.php +++ b/src/Resources/Users/Data/Response/ProfileData.php @@ -1,5 +1,7 @@ ensureIsNotRateLimited($request); diff --git a/src/StarterKits/Auth/Sanctum/Actions/Logout.php b/src/StarterKits/Auth/Sanctum/Actions/Logout.php index 06b8226..2112e4f 100644 --- a/src/StarterKits/Auth/Sanctum/Actions/Logout.php +++ b/src/StarterKits/Auth/Sanctum/Actions/Logout.php @@ -1,11 +1,13 @@ user())->as(User::class); @@ -40,7 +42,7 @@ protected function deleteAllTokens(): void $this->message = __('rest-presenter::auth.logout_message'); } - protected function deleteCurrentToken(): void + private function deleteCurrentToken(): void { /** @var User $user */ $user = type(auth()->user())->as(User::class); diff --git a/src/StarterKits/Auth/Sanctum/Actions/Register.php b/src/StarterKits/Auth/Sanctum/Actions/Register.php index 0798401..5dc8ad4 100644 --- a/src/StarterKits/Auth/Sanctum/Actions/Register.php +++ b/src/StarterKits/Auth/Sanctum/Actions/Register.php @@ -1,5 +1,7 @@ id, 4, '0'); + } + + private function sendResetLink(string $email): void { $status = Password::sendResetLink( credentials: ['email' => $email], @@ -33,7 +40,7 @@ protected function sendResetLink(string $email): void }, ); - if ($status != Password::RESET_LINK_SENT) { + if ($status !== Password::RESET_LINK_SENT) { $this->message = __($status); return; @@ -42,14 +49,9 @@ protected function sendResetLink(string $email): void $this->message = __('rest-presenter::auth.reset_password_message'); } - protected function setTemporaryPassword(User $user, string $token): void + private function setTemporaryPassword(User $user, string $token): void { $user->password = bcrypt(self::generateTemporaryPassword($user, $token)); // @phpstan-ignore-line $user->save(); } - - public static function generateTemporaryPassword(User $user, string $token): string - { - return 'temp-' . Str::take($token, 5) . '-' . Str::padLeft((string)$user->id, 4, '0'); - } } diff --git a/src/StarterKits/Auth/Sanctum/Actions/VerifyEmail.php b/src/StarterKits/Auth/Sanctum/Actions/VerifyEmail.php index 3309cb5..2124392 100644 --- a/src/StarterKits/Auth/Sanctum/Actions/VerifyEmail.php +++ b/src/StarterKits/Auth/Sanctum/Actions/VerifyEmail.php @@ -1,11 +1,13 @@ ip(); + + return Str::transliterate(Str::lower($request->email).'|'.$ipAddress); + } + protected function ensureIsNotRateLimited(LoginDataRequest $request): void { $maxAttempts = type(config('rest-presenter.auth.rate_limit.max_attempts'))->asInt(); @@ -31,14 +43,4 @@ protected function ensureIsNotRateLimited(LoginDataRequest $request): void ]), ]); } - - /** - * Get the rate limiting throttle key for the request. - */ - public function throttleKey(LoginDataRequest $request): string - { - $ipAddress = request()->ip(); - - return Str::transliterate(Str::lower($request->email) . '|' . $ipAddress); - } } diff --git a/src/StarterKits/Auth/Sanctum/Data/Request/LoginDataRequest.php b/src/StarterKits/Auth/Sanctum/Data/Request/LoginDataRequest.php index 40e9e50..bd3c00a 100644 --- a/src/StarterKits/Auth/Sanctum/Data/Request/LoginDataRequest.php +++ b/src/StarterKits/Auth/Sanctum/Data/Request/LoginDataRequest.php @@ -1,5 +1,7 @@ (new MailMessage) + ResetPassword::toMailUsing(static fn ($notifiable, string $token) => (new MailMessage) ->subject(Lang::get('Reset Password Notification')) // @phpstan-ignore-line ->line(Lang::get('You are receiving this email because we received a password reset request for your account.')) ->action(Lang::get('Login'), url(config('app.frontend_url'))) // @phpstan-ignore-line @@ -30,9 +31,9 @@ public function boot(): void ->line(Lang::get('If you did not request a password reset, no further action is required.'))); } - protected function ensurePersonalAccessTokensHasExpiresAtColumn(): void + private function ensurePersonalAccessTokensHasExpiresAtColumn(): void { - if (!Schema::hasTable('personal_access_tokens')) { + if (! Schema::hasTable('personal_access_tokens')) { return; } if (Schema::hasColumn('personal_access_tokens', 'expires_at')) { diff --git a/src/StarterKits/Auth/Sanctum/Tests/Feature/AuthenticationTest.php b/src/StarterKits/Auth/Sanctum/Tests/Feature/AuthenticationTest.php index 2b0a09a..dab389b 100644 --- a/src/StarterKits/Auth/Sanctum/Tests/Feature/AuthenticationTest.php +++ b/src/StarterKits/Auth/Sanctum/Tests/Feature/AuthenticationTest.php @@ -1,5 +1,7 @@ fresh()->hasVerifiedEmail())->toBeTrue(); - $response->assertRedirect(config('app.frontend_url') . '/dashboard?verified=1'); + $response->assertRedirect(config('app.frontend_url').'/dashboard?verified=1'); }); test('email is not verified with invalid hash', function (): void { diff --git a/src/StarterKits/Auth/Sanctum/Tests/Feature/PasswordResetTest.php b/src/StarterKits/Auth/Sanctum/Tests/Feature/PasswordResetTest.php index 0dedc49..02b7313 100644 --- a/src/StarterKits/Auth/Sanctum/Tests/Feature/PasswordResetTest.php +++ b/src/StarterKits/Auth/Sanctum/Tests/Feature/PasswordResetTest.php @@ -1,5 +1,7 @@ post('/register', [ 'name' => 'Test User', diff --git a/src/StarterKits/Filament/Base/FilamentStarterKit.php b/src/StarterKits/Filament/Base/FilamentStarterKit.php index ae4802b..b159771 100644 --- a/src/StarterKits/Filament/Base/FilamentStarterKit.php +++ b/src/StarterKits/Filament/Base/FilamentStarterKit.php @@ -1,5 +1,7 @@ > */ - protected array $resources = []; + private array $resources = []; /** * @return array> @@ -29,7 +31,7 @@ public function autoDiscover(): array return $this->resources; } - protected function autoDiscoverResources(): void + private function autoDiscoverResources(): void { if (! $this->filesystem->isDirectory(app_path('Filament/Resources'))) { return; @@ -38,10 +40,10 @@ protected function autoDiscoverResources(): void collect($this->filesystem->allFiles(app_path('Filament/Resources'))) ->filter(fn (SplFileInfo $file): bool => basename($file->getRelativePath()) === 'Pages') ->map(fn (SplFileInfo $file): string => $file->getRelativePathname()) - ->map(fn (string $file) => resolve('App\\Filament\\Resources\\' . str_replace(['/', '.php'], ['\\', ''], $file))) + ->map(fn (string $file) => resolve('App\\Filament\\Resources\\'.str_replace(['/', '.php'], ['\\', ''], $file))) ->filter(fn ($class): bool => is_subclass_of($class, ListRecords::class)) ->each(function ($page): void { - /** @var \Filament\Resources\Pages\ListRecords $page */ + /** @var ListRecords $page */ $page = type($page)->as(ListRecords::class); /** @var \Filament\Tables\Table $table */ $table = $page->table( @@ -75,9 +77,9 @@ protected function autoDiscoverResources(): void } /** - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection> */ - protected function generateModelFields(Model $model): Collection + private function generateModelFields(Model $model): Collection { $table = $model->getTable(); diff --git a/src/StarterKits/Filament/FilamentApiKitServiceProvider.php b/src/StarterKits/Filament/FilamentApiKitServiceProvider.php index f7542bf..22ff38b 100644 --- a/src/StarterKits/Filament/FilamentApiKitServiceProvider.php +++ b/src/StarterKits/Filament/FilamentApiKitServiceProvider.php @@ -1,10 +1,12 @@ loadRoutesFrom(__DIR__ . '/Routes/api.php'); + $this->loadRoutesFrom(__DIR__.'/Routes/api.php'); } } diff --git a/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/BrandResourceController.php b/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/BrandResourceController.php index 387c745..a889ba6 100644 --- a/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/BrandResourceController.php +++ b/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/BrandResourceController.php @@ -1,5 +1,7 @@ $this->model->id, @@ -30,7 +33,7 @@ public function transform(): BrandData | Data ]); } - protected function getBrandSlug(): string + private function getBrandSlug(): string { return $this->model->urls->first(function (Url $url): bool { $matchesLocale = $url->language->code === app()->getLocale(); @@ -39,10 +42,10 @@ protected function getBrandSlug(): string })?->slug; } - protected function getImage(): ?MediaData + private function getImage(): ?MediaData { $mediaItem = $this->model->getFirstMedia('images'); - if (!$mediaItem instanceof \Spatie\MediaLibrary\MediaCollections\Models\Media) { + if (! $mediaItem instanceof \Spatie\MediaLibrary\MediaCollections\Models\Media) { return null; } diff --git a/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/Presenters/Brand/Data/BrandData.php b/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/Presenters/Brand/Data/BrandData.php index 05cf4cb..c580bf0 100644 --- a/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/Presenters/Brand/Data/BrandData.php +++ b/src/StarterKits/Stores/Lunar/Resources/Catalog/Brands/Presenters/Brand/Data/BrandData.php @@ -1,11 +1,13 @@ getCollections(); @@ -30,7 +33,7 @@ public function transform(): TreeData | Data ); } - protected function getCollections(): \Illuminate\Support\Collection + private function getCollections(): \Illuminate\Support\Collection { return $this->model ->collections() diff --git a/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Concerns/WithGenerateCollectionsTree.php b/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Concerns/WithGenerateCollectionsTree.php index 0179ba4..e0af6e6 100644 --- a/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Concerns/WithGenerateCollectionsTree.php +++ b/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Concerns/WithGenerateCollectionsTree.php @@ -1,5 +1,7 @@ map(fn(Collection $collection): array => [ + return $collections->map(fn (Collection $collection): array => [ 'id' => $collection->id, 'name' => $collection->translateAttribute('name'), 'slug' => $this->generateSlugComputed($collection), @@ -19,6 +21,6 @@ public function generateTree(\Illuminate\Support\Collection $collections): array protected function generateSlugComputed(Collection $collection): string { - return $collection->id . '-' . Str::slug($collection->translateAttribute('name')); + return $collection->id.'-'.Str::slug($collection->translateAttribute('name')); } } diff --git a/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Data/CategoryData.php b/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Data/CategoryData.php index d70fd71..9c521df 100644 --- a/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Data/CategoryData.php +++ b/src/StarterKits/Stores/Lunar/Resources/Catalog/CollectionGroups/Presenters/CategoryTree/Data/CategoryData.php @@ -1,10 +1,12 @@ $this->model->id, @@ -31,7 +34,7 @@ public function transform(): CategoryData | Data ]); } - protected function getStyleSlug(): string + private function getStyleSlug(): string { return $this->model->urls->first(function (Url $url): bool { $matchesLocale = $url->language->code === app()->getLocale(); @@ -40,10 +43,10 @@ protected function getStyleSlug(): string })?->slug; } - protected function getBanner(): ?MediaData + private function getBanner(): ?MediaData { $mediaItem = $this->model->getFirstMedia('images'); - if (!$mediaItem instanceof \Spatie\MediaLibrary\MediaCollections\Models\Media) { + if (! $mediaItem instanceof \Spatie\MediaLibrary\MediaCollections\Models\Media) { return null; } diff --git a/src/StarterKits/Stores/Lunar/Resources/Catalog/Collections/Presenters/Category/Data/CategoryData.php b/src/StarterKits/Stores/Lunar/Resources/Catalog/Collections/Presenters/Category/Data/CategoryData.php index 074414c..f7243c0 100644 --- a/src/StarterKits/Stores/Lunar/Resources/Catalog/Collections/Presenters/Category/Data/CategoryData.php +++ b/src/StarterKits/Stores/Lunar/Resources/Catalog/Collections/Presenters/Category/Data/CategoryData.php @@ -1,11 +1,13 @@ $this->model->id, diff --git a/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/Presenters/Item/Data/ItemData.php b/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/Presenters/Item/Data/ItemData.php index bee9542..141d515 100644 --- a/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/Presenters/Item/Data/ItemData.php +++ b/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/Presenters/Item/Data/ItemData.php @@ -1,5 +1,7 @@ $this->model->id, diff --git a/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/ProductResourceController.php b/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/ProductResourceController.php index a1f69d4..adffa8e 100644 --- a/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/ProductResourceController.php +++ b/src/StarterKits/Stores/Lunar/Resources/Catalog/Products/ProductResourceController.php @@ -1,5 +1,7 @@ prefix('api/v1') ->middleware(config('rest-presenter.api.middleware')) ->group(function (): void { - Route::name('catalog:')->prefix('catalog')->group(__DIR__ . '/catalog.php'); + Route::name('catalog:')->prefix('catalog')->group(__DIR__.'/catalog.php'); }); diff --git a/src/StarterKits/Stores/Lunar/Routes/catalog.php b/src/StarterKits/Stores/Lunar/Routes/catalog.php index d47e023..f205f0f 100644 --- a/src/StarterKits/Stores/Lunar/Routes/catalog.php +++ b/src/StarterKits/Stores/Lunar/Routes/catalog.php @@ -1,5 +1,7 @@ forceFill([ 'id' => $id, 'attribute_data' => collect([ - 'name' => new Text('Category ' . $id), + 'name' => new Text('Category '.$id), ]), 'children' => collect(), ]); @@ -62,14 +64,14 @@ function mockCollection($id = null) expect($result)->toBeInstanceOf(TreeData::class) ->and($result->id)->toBe(1) ->and($result->name)->toBe('Test Name') - ->and($result->categories)->toBeInstanceOf(\Illuminate\Support\Collection::class) + ->and($result->categories)->toBeInstanceOf(Illuminate\Support\Collection::class) ->and($result->categories)->toHaveCount(5); // Test the categories within nested children collect($result->categories)->each(function (CategoryData $category, $index): void { expect($category->id)->toBe($index + 1) - ->and($category->name)->toBe('Category ' . ($index + 1)) - ->and($category->slug)->toBe(($index + 1) . '-category-' . ($index + 1)) + ->and($category->name)->toBe('Category '.($index + 1)) + ->and($category->slug)->toBe(($index + 1).'-category-'.($index + 1)) // @todo Add additional assertions for children later ->and($category->children)->toBeArray() ->and($category->children)->toHaveCount(0); diff --git a/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/CollectionsFeatureTest.php b/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/CollectionsFeatureTest.php index d265215..217cffe 100644 --- a/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/CollectionsFeatureTest.php +++ b/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/CollectionsFeatureTest.php @@ -1,5 +1,7 @@ resourceController = new class() { + $this->resourceController = new class() + { use InteractsWithModel; use WithResourceFiltering; public function __construct() { - static::$model = Collection::class; + self::$model = Collection::class; } public function filters(): array diff --git a/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/Presenters/Category/CategoryFeatureTest.php b/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/Presenters/Category/CategoryFeatureTest.php index ec58861..0d1c203 100644 --- a/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/Presenters/Category/CategoryFeatureTest.php +++ b/src/StarterKits/Stores/Lunar/Tests/Catalog/Collections/Presenters/Category/CategoryFeatureTest.php @@ -1,5 +1,7 @@ resourceController = new class() { + $this->resourceController = new class() + { use InteractsWithModel; use WithResourceFiltering; public function __construct() { - static::$model = Product::class; + self::$model = Product::class; } public function filters(): array diff --git a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Filters/Status/StatusFeatureTest.php b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Filters/Status/StatusFeatureTest.php index 7a77137..0a6047f 100644 --- a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Filters/Status/StatusFeatureTest.php +++ b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Filters/Status/StatusFeatureTest.php @@ -1,5 +1,7 @@ resourceController = new class() { + $this->resourceController = new class() + { use InteractsWithModel; use WithResourceFiltering; public function __construct() { - static::$model = Product::class; + self::$model = Product::class; } public function filters(): array diff --git a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Detail/DetailFeatureTest.php b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Detail/DetailFeatureTest.php index 8a54830..4f5781d 100644 --- a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Detail/DetailFeatureTest.php +++ b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Detail/DetailFeatureTest.php @@ -1,5 +1,7 @@ and($result->name)->toBe('Test Name') ->and($result->description)->toBe('Test Description') ->and($result->availability)->toBe('available') - ->and($result->variants)->toBeInstanceOf(\Illuminate\Support\Collection::class) - ->and($result->colors)->toBeInstanceOf(\Illuminate\Support\Collection::class) - ->and($result->sizes)->toBeInstanceOf(\Illuminate\Support\Collection::class) - ->and($result->prices)->toBeInstanceOf(\Illuminate\Support\Collection::class) - ->and($result->images)->toBeInstanceOf(\Illuminate\Support\Collection::class); + ->and($result->variants)->toBeInstanceOf(Illuminate\Support\Collection::class) + ->and($result->colors)->toBeInstanceOf(Illuminate\Support\Collection::class) + ->and($result->sizes)->toBeInstanceOf(Illuminate\Support\Collection::class) + ->and($result->prices)->toBeInstanceOf(Illuminate\Support\Collection::class) + ->and($result->images)->toBeInstanceOf(Illuminate\Support\Collection::class); }); }); diff --git a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Item/ItemFeatureTest.php b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Item/ItemFeatureTest.php index c968b07..8143f0a 100644 --- a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Item/ItemFeatureTest.php +++ b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/Presenters/Item/ItemFeatureTest.php @@ -1,5 +1,7 @@ 1, 'customer_group_id' => 1, 'currency_id' => 1, - 'price' => new \Lunar\DataTypes\Price(100, $this->currency), - 'compare_price' => new \Lunar\DataTypes\Price(0, $this->currency), + 'price' => new Lunar\DataTypes\Price(100, $this->currency), + 'compare_price' => new Lunar\DataTypes\Price(0, $this->currency), 'tier' => 1, ]); $this->product = mock(Product::class) diff --git a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/ProductsFeatureTest.php b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/ProductsFeatureTest.php index c74d0b1..fd1fe44 100644 --- a/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/ProductsFeatureTest.php +++ b/src/StarterKits/Stores/Lunar/Tests/Catalog/Products/ProductsFeatureTest.php @@ -1,5 +1,7 @@ loadMigrationsFrom(__DIR__ . '/../../../../../vendor/lunarphp/core/database/migrations'); + $this->loadMigrationsFrom(__DIR__.'/../../../../../vendor/lunarphp/core/database/migrations'); } protected function getEnvironmentSetUp($app): void @@ -28,7 +30,7 @@ protected function getEnvironmentSetUp($app): void $this->registerBlueprintMacros(); - app()->singleton(ModelManifestInterface::class, fn($app) => $app->make(ModelManifest::class)); + app()->singleton(ModelManifestInterface::class, fn ($app) => $app->make(ModelManifest::class)); $app['config']->set('lunar.database.connection', 'testbench'); $app['config']->set('lunar.database.table_prefix', 'lunar_'); @@ -46,7 +48,7 @@ protected function getPackageProviders($app): array ]); } - protected function registerBlueprintMacros(): void + private function registerBlueprintMacros(): void { Blueprint::macro('scheduling', function (): void { /** @var Blueprint $this */ @@ -68,13 +70,13 @@ protected function registerBlueprintMacros(): void $type = config('lunar.database.users_id_type', 'bigint'); - if ($type == 'uuid') { + if ($type === 'uuid') { $this->foreignUuId($field_name) ->nullable($nullable) ->constrained( (new $userModel())->getTable() // @phpstan-ignore-line ); - } elseif ($type == 'int') { + } elseif ($type === 'int') { $this->unsignedInteger($field_name)->nullable($nullable); $this->foreign($field_name)->references('id')->on('users'); } else { diff --git a/src/Support/ResourceDefaultPresenter.php b/src/Support/ResourceDefaultPresenter.php index 333613f..e7f1ba5 100644 --- a/src/Support/ResourceDefaultPresenter.php +++ b/src/Support/ResourceDefaultPresenter.php @@ -1,5 +1,7 @@ prefix($prefix . '/' . $version) + return Route::name($prefix.'.'.$version.'.') + ->prefix($prefix.'/'.$version) ->middleware(config('rest-presenter.api.middleware') ?? []) // @phpstan-ignore-line ->group(fn () => $this->routes()); } @@ -51,14 +53,14 @@ public function routes(): void public function autoDiscoverResources(): void { $this->autoDiscover( - path: app()->basePath(config('rest-presenter.generator.path') . '/Resources'), + path: app()->basePath(config('rest-presenter.generator.path').'/Resources'), ); } public function autoDiscoverStarterKits(): void { $this->autoDiscover( - path: app()->basePath(config('rest-presenter.generator.path') . '/StarterKits'), + path: app()->basePath(config('rest-presenter.generator.path').'/StarterKits'), isKit: true, ); } @@ -75,8 +77,6 @@ public function resources(array $resources, array $options = []): void } /** - * @param $name - * @param $controller * @param array $options */ public function resource($name, $controller, array $options = []): PendingResourceRegistration @@ -87,7 +87,8 @@ public function resource($name, $controller, array $options = []): PendingResour $extendControllerFile = Str::of($controller)->replace('XtendPackages\RESTPresenter', '') ->replace('\\', '/') ->prepend(app()->path('Api')) - ->append('.php'); + ->append('.php') + ->value(); $controller = file_exists($extendControllerFile) ? $xtendController : $controller; @@ -105,7 +106,9 @@ public function auth(string $httpVerb, string $uri, string $controller, string $ $extendControllerFile = Str::of($controller)->replace('XtendPackages\RESTPresenter', '') ->replace('\\', '/') ->prepend(app()->path('Api')) - ->append('.php'); + ->append('.php') + ->value(); + $controller = file_exists($extendControllerFile) ? $xtendController : $controller; Route::match([$httpVerb], $uri, [$controller, 'store']) diff --git a/tests/Helpers.php b/tests/Helpers.php index bf4e606..4aad236 100644 --- a/tests/Helpers.php +++ b/tests/Helpers.php @@ -1,12 +1,14 @@ create(), @@ -72,14 +74,14 @@ function fakeMediaItem(int $id): Media ->forceFill([ 'id' => $id, 'uuid' => Str::uuid(), - 'name' => 'Name ' . $id, + 'name' => 'Name '.$id, 'custom_properties' => ['custom' => 'properties'], 'order_column' => $id, ]); $media ->shouldReceive('getUrl') - ->andReturn('http://example.com/' . $id); + ->andReturn('http://example.com/'.$id); return $media; } diff --git a/tests/Pest.php b/tests/Pest.php index 21d4c1b..8fee87b 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,9 +1,11 @@ in(__DIR__); // StarterKits Tests -uses(LunarTestCase::class)->in(__DIR__ . '/../src/StarterKits/Stores/Lunar/Tests'); +uses(LunarTestCase::class)->in(__DIR__.'/../src/StarterKits/Stores/Lunar/Tests'); diff --git a/tests/Resources/ResourcePresenterFeatureTest.php b/tests/Resources/ResourcePresenterFeatureTest.php index cf9207b..f25b063 100644 --- a/tests/Resources/ResourcePresenterFeatureTest.php +++ b/tests/Resources/ResourcePresenterFeatureTest.php @@ -1,5 +1,7 @@ resourceController = new class { + $this->resourceController = new class + { use InteractsWithPresenter; public function presenters(): array diff --git a/tests/Support/Concerns/InteractsWithRequestTest.php b/tests/Support/Concerns/InteractsWithRequestTest.php index 1de5271..1574802 100644 --- a/tests/Support/Concerns/InteractsWithRequestTest.php +++ b/tests/Support/Concerns/InteractsWithRequestTest.php @@ -1,5 +1,7 @@ merge(['filters' => ['filterKey' => 'filterValue']]); app()->instance('request', $request); - $this->resourceController = new class { + $this->resourceController = new class + { use InteractsWithRequest; public function filters(): array diff --git a/tests/Support/Concerns/WithResourceFilteringTest.php b/tests/Support/Concerns/WithResourceFilteringTest.php index a230659..6a8d688 100644 --- a/tests/Support/Concerns/WithResourceFilteringTest.php +++ b/tests/Support/Concerns/WithResourceFilteringTest.php @@ -1,5 +1,7 @@ resourceController = new class() { + $this->resourceController = new class() + { use InteractsWithModel; use WithResourceFiltering; public function __construct() { - static::$model = User::class; + self::$model = User::class; } public function filters(): array diff --git a/tests/TestCase.php b/tests/TestCase.php index 1ccb8a9..01bb3b8 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,13 +1,14 @@ loadLaravelMigrations(['--database' => 'testbench']); } - - protected function getEnvironmentSetUp($app) - { - $app['config']->set('database.default', 'testbench'); - $app['config']->set('database.connections.testbench', [ - 'driver' => 'sqlite', - 'database' => ':memory:', - 'prefix' => '', - ]); - - $app['config']->set('data.date_format', 'Y-m-d H:i:s'); - $app['config']->set('rest-presenter.resources.user.model', User::class); - } - - protected function getPackageProviders($app): array - { - return [ - SanctumServiceProvider::class, - RESTPresenterServiceProvider::class, - LaravelDataServiceProvider::class, - ]; - } }