diff --git a/src/Console/Commands/ActionCommand.php b/src/Console/Commands/ActionCommand.php deleted file mode 100644 index 2e3a9a4..0000000 --- a/src/Console/Commands/ActionCommand.php +++ /dev/null @@ -1,77 +0,0 @@ -resolveStubPath('/stubs/rest/action.stub'); - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Rest\Actions'; - } -} diff --git a/src/Console/Commands/ActionMakeCommand.php b/src/Console/Commands/ActionMakeCommand.php new file mode 100644 index 0000000..3d4be60 --- /dev/null +++ b/src/Console/Commands/ActionMakeCommand.php @@ -0,0 +1,67 @@ +resolveStubPath('/../stubs/action.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Rest\Actions'; + } +} diff --git a/src/Console/Commands/BaseControllerCommand.php b/src/Console/Commands/BaseControllerCommand.php deleted file mode 100644 index 28a1787..0000000 --- a/src/Console/Commands/BaseControllerCommand.php +++ /dev/null @@ -1,89 +0,0 @@ -resolveStubPath('/stubs/rest/base-controller.stub'); - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Rest'; - } -} diff --git a/src/Console/Commands/BaseControllerMakeCommand.php b/src/Console/Commands/BaseControllerMakeCommand.php new file mode 100644 index 0000000..e7258d2 --- /dev/null +++ b/src/Console/Commands/BaseControllerMakeCommand.php @@ -0,0 +1,74 @@ +resolveStubPath('/../stubs/base-controller.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath(string $stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Rest\Controllers'; + } +} diff --git a/src/Console/Commands/BaseResourceCommand.php b/src/Console/Commands/BaseResourceCommand.php deleted file mode 100644 index 40982f1..0000000 --- a/src/Console/Commands/BaseResourceCommand.php +++ /dev/null @@ -1,79 +0,0 @@ -resolveStubPath('/stubs/rest/base-resource.stub'); - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Rest'; - } -} diff --git a/src/Console/Commands/BaseResourceMakeCommand.php b/src/Console/Commands/BaseResourceMakeCommand.php new file mode 100644 index 0000000..81966f6 --- /dev/null +++ b/src/Console/Commands/BaseResourceMakeCommand.php @@ -0,0 +1,74 @@ +resolveStubPath('/../stubs/base-resource.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath(string $stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Rest\Resources'; + } +} diff --git a/src/Console/Commands/ControllerCommand.php b/src/Console/Commands/ControllerCommand.php deleted file mode 100644 index 729e962..0000000 --- a/src/Console/Commands/ControllerCommand.php +++ /dev/null @@ -1,136 +0,0 @@ -option('path'))) { - $this->callSilent('rest:base-controller', [ - 'name' => 'Controller', - ]); - } - } - - /** - * Build the class with the given name. - * - * @param string $name - * - * @return string - */ - protected function buildClass($name) - { - $resource = $this->option('resource'); - - $resourceNamespace = $this->getResourceNamespace(); - - if (is_null($resource)) { - $resource = $resourceNamespace.'ModelResource'; - } elseif (!Str::startsWith($resource, [ - $resourceNamespace, '\\', - ])) { - $resource = $resourceNamespace.$resource; - } - - $replace = [ - 'DummyFullResource' => $resource, - '{{ namespacedResource }}' => $resource, - '{{namespacedResource}}' => $resource, - ]; - - return str_replace( - array_keys($replace), - array_values($replace), - parent::buildClass($name) - ); - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - return $this->resolveStubPath('/stubs/rest/controller.stub'); - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Rest\Controllers'; - } - - /** - * Get the default namespace for the class. - * - * @return string - */ - protected function getResourceNamespace() - { - $rootNamespace = $this->laravel->getNamespace(); - - return is_dir(app_path('Rest/Resources')) ? $rootNamespace.'Rest\\Resources\\' : $rootNamespace; - } -} diff --git a/src/Console/Commands/ControllerMakeCommand.php b/src/Console/Commands/ControllerMakeCommand.php new file mode 100644 index 0000000..8dce2ef --- /dev/null +++ b/src/Console/Commands/ControllerMakeCommand.php @@ -0,0 +1,249 @@ +resolveStubPath('/../stubs/controller.stub'); + } + + /** + * Execute the console command. + * + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * + * @return bool|null + */ + public function handle(): ?bool + { + $this->callSilent('rest:base-controller', [ + 'name' => 'Controller', + ]); + + return parent::handle(); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath($stub) + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Build the class with the given name. + * + * @param string $name + * + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * + * @return string + */ + protected function buildClass($name): string + { + $rootNamespace = $this->rootNamespace(); + + $replace = []; + + if ($this->option('resource')) { + $replace = $this->buildResourceReplacements($replace); + } else { + $replace = array_merge( + $replace, + [ + '{{ namespacedResource }}' => 'Resource', + ] + ); + } + + $baseControllerExists = file_exists($this->getPath("{$rootNamespace}Rest\Controllers\Controller")); + + if (!$baseControllerExists) { + $replace["use {$rootNamespace}Rest\Controllers\Controller;\n"] = "use Lomkit\\Rest\\Http\\Controllers\\Controller;\n"; + } + + return str_replace( + array_keys($replace), + array_values($replace), + parent::buildClass($name) + ); + } + + /** + * Build the resource replacement values. + * + * @param array $replace + * + * @return array + */ + protected function buildResourceReplacements(array $replace): array + { + $resourceClass = $this->parseResource($this->option('resource')); + + $replace = []; + + return array_merge($replace, [ + 'DummyFullResourceClass' => $resourceClass, + '{{ namespacedResource }}' => $resourceClass, + '{{namespacedResource}}' => $resourceClass, + 'DummyResourceClass' => class_basename($resourceClass), + '{{ resource }}' => class_basename($resourceClass), + '{{resource}}' => class_basename($resourceClass), + 'DummyResourceVariable' => lcfirst(class_basename($resourceClass)), + '{{ resourceVariable }}' => lcfirst(class_basename($resourceClass)), + '{{resourceVariable}}' => lcfirst(class_basename($resourceClass)), + ]); + } + + /** + * Interact further with the user if they were prompted for missing arguments. + * + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return void + */ + protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void + { + if ($this->didReceiveOptions($input)) { + return; + } + $resource = select( + 'What resource should this resource relies to? (Optional)', + $this->possibleResources(), + required: false + ); + + if ($resource) { + $input->setOption('resource', $resource); + } + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions(): array + { + return [ + ['resource', null, InputOption::VALUE_REQUIRED, 'The resource associated with this resource'], + ]; + } + + /** + * Get a list of possible model names. + * + * @return array + */ + protected function possibleResources(): array + { + $resourcePath = app_path('Rest/Resources'); + + return (new Collection(Finder::create()->files()->depth(0)->in($resourcePath))) + ->map(fn ($file) => $file->getBasename('.php')) + ->sort() + ->values() + ->all(); + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Rest\Controllers'; + } + + /** + * Get the fully-qualified resource class name. + * + * @param string $model + * + * @throws \InvalidArgumentException + * + * @return string + */ + protected function parseResource($model): string + { + if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) { + throw new InvalidArgumentException('Resource name contains invalid characters.'); + } + + return $this->qualifyResource($model); + } + + /** + * Qualify the given resource class base name. + * + * @param string $resource + * + * @return string + */ + protected function qualifyResource(string $resource): string + { + $resource = ltrim($resource, '\\/'); + + $resource = str_replace('/', '\\', $resource); + + $rootNamespace = $this->rootNamespace(); + + if (Str::startsWith($resource, $rootNamespace)) { + return $resource; + } + + return $rootNamespace.'Rest\\Resources\\'.$resource; + } +} diff --git a/src/Console/Commands/DocumentationCommand.php b/src/Console/Commands/Documentation/DocumentationCommand.php similarity index 95% rename from src/Console/Commands/DocumentationCommand.php rename to src/Console/Commands/Documentation/DocumentationCommand.php index 0b30177..ca3b489 100644 --- a/src/Console/Commands/DocumentationCommand.php +++ b/src/Console/Commands/Documentation/DocumentationCommand.php @@ -1,8 +1,7 @@ resolveStubPath('/../../stubs/rest-documentation-service-provider.stub'); + } + + /** + * Get the console command arguments. + * + * @return array + */ + protected function getArguments(): array + { + return [ + ['name', InputArgument::OPTIONAL, 'The name of the '.strtolower($this->type), 'RestDocumentationServiceProvider'], + ]; + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Providers'; + } +} diff --git a/src/Console/Commands/DocumentationProviderCommand.php b/src/Console/Commands/DocumentationProviderCommand.php deleted file mode 100644 index 38d9d72..0000000 --- a/src/Console/Commands/DocumentationProviderCommand.php +++ /dev/null @@ -1,84 +0,0 @@ -resolveStubPath('/stubs/rest/rest-documentation-service-provider.stub'); - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Providers'; - } - - /** - * Get the default namespace for the class. - * - * @return string - */ - protected function getResourceNamespace() - { - $rootNamespace = $this->laravel->getNamespace(); - - return is_dir(app_path('Providers')) ? $rootNamespace.'Providers\\' : $rootNamespace; - } -} diff --git a/src/Console/Commands/InstructionCommand.php b/src/Console/Commands/InstructionCommand.php deleted file mode 100644 index 364c921..0000000 --- a/src/Console/Commands/InstructionCommand.php +++ /dev/null @@ -1,94 +0,0 @@ -resolveStubPath('/stubs/rest/instruction.stub'); - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Rest\Instructions'; - } -} diff --git a/src/Console/Commands/InstructionMakeCommand.php b/src/Console/Commands/InstructionMakeCommand.php new file mode 100644 index 0000000..645de43 --- /dev/null +++ b/src/Console/Commands/InstructionMakeCommand.php @@ -0,0 +1,67 @@ +resolveStubPath('/../stubs/instruction.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Rest\Instructions'; + } +} diff --git a/src/Console/Commands/QuickStartCommand.php b/src/Console/Commands/QuickStartCommand.php index 4baf622..381dc5e 100644 --- a/src/Console/Commands/QuickStartCommand.php +++ b/src/Console/Commands/QuickStartCommand.php @@ -5,12 +5,9 @@ use Illuminate\Console\Command; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Str; -use Lomkit\Rest\Console\ResolvesStubPath; class QuickStartCommand extends Command { - use ResolvesStubPath; - /** * The name and signature of the console command. * @@ -33,10 +30,10 @@ class QuickStartCommand extends Command public function handle() { $this->comment('Generating User Resource...'); - $this->callSilent('rest:resource', ['name' => 'UserResource']); + $this->callSilent('rest:resource', ['name' => 'UserResource', '--model' => 'User']); $this->comment('Generating User Controller...'); - $this->callSilent('rest:controller', ['name' => 'UsersController']); + $this->callSilent('rest:controller', ['name' => 'UsersController', '--resource' => 'UserResource']); $this->updateUserModelNamespace(); $this->setAppNamespace(); @@ -150,4 +147,18 @@ protected function updateApiRoutes() file_put_contents($routesPath, $routeContent.PHP_EOL.$newRoute); } } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath($stub) + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.str_replace('rest/', '', $stub); + } } diff --git a/src/Console/Commands/ResourceCommand.php b/src/Console/Commands/ResourceCommand.php deleted file mode 100644 index 545b95b..0000000 --- a/src/Console/Commands/ResourceCommand.php +++ /dev/null @@ -1,131 +0,0 @@ -option('path'))) { - $this->callSilent('rest:base-resource', [ - 'name' => 'Resource', - ]); - } - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Build the class with the given name. - * - * @param string $name - * - * @return string - */ - protected function buildClass($name) - { - $model = $this->option('model'); - - $modelNamespace = $this->getModelNamespace(); - - if (is_null($model)) { - $model = $modelNamespace.'Model'; - } elseif (!Str::startsWith($model, [ - $modelNamespace, '\\', - ])) { - $model = $modelNamespace.$model; - } - - $replace = [ - 'DummyFullModel' => $model, - '{{ namespacedModel }}' => $model, - '{{namespacedModel}}' => $model, - ]; - - return str_replace( - array_keys($replace), - array_values($replace), - parent::buildClass($name) - ); - } - - /** - * Get the stub file for the generator. - * - * @return string - */ - protected function getStub() - { - return $this->resolveStubPath('/stubs/rest/resource.stub'); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Rest\Resources'; - } - - /** - * Get the default namespace for the class. - * - * @return string - */ - protected function getModelNamespace() - { - $rootNamespace = $this->laravel->getNamespace(); - - return is_dir(app_path('Models')) ? $rootNamespace.'Models\\' : $rootNamespace; - } -} diff --git a/src/Console/Commands/ResourceMakeCommand.php b/src/Console/Commands/ResourceMakeCommand.php new file mode 100644 index 0000000..8ac40db --- /dev/null +++ b/src/Console/Commands/ResourceMakeCommand.php @@ -0,0 +1,206 @@ +resolveStubPath('/../stubs/resource.stub'); + } + + /** + * Execute the console command. + * + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * + * @return bool|null + */ + public function handle(): ?bool + { + $this->callSilent('rest:base-resource', [ + 'name' => 'Resource', + ]); + + return parent::handle(); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath($stub) + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Build the class with the given name. + * + * @param string $name + * + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * + * @return string + */ + protected function buildClass($name): string + { + $rootNamespace = $this->rootNamespace(); + + $replace = []; + + if ($this->option('model')) { + $replace = $this->buildModelReplacements($replace); + } else { + $replace = array_merge( + $replace, + [ + '{{ namespacedModel }}' => 'Model', + ] + ); + } + + $baseResourceExists = file_exists($this->getPath("{$rootNamespace}Rest\Resources\Resource")); + + if (!$baseResourceExists) { + $replace["use {$rootNamespace}Rest\Resources\Resource;\n"] = "use Lomkit\\Rest\\Http\\Resource;\n"; + } + + return str_replace( + array_keys($replace), + array_values($replace), + parent::buildClass($name) + ); + } + + /** + * Build the model replacement values. + * + * @param array $replace + * + * @return array + */ + protected function buildModelReplacements(array $replace): array + { + $modelClass = $this->parseModel($this->option('model')); + + return array_merge($replace, [ + 'DummyFullModelClass' => $modelClass, + '{{ namespacedModel }}' => $modelClass, + '{{namespacedModel}}' => $modelClass, + 'DummyModelClass' => class_basename($modelClass), + '{{ model }}' => class_basename($modelClass), + '{{model}}' => class_basename($modelClass), + 'DummyModelVariable' => lcfirst(class_basename($modelClass)), + '{{ modelVariable }}' => lcfirst(class_basename($modelClass)), + '{{modelVariable}}' => lcfirst(class_basename($modelClass)), + ]); + } + + /** + * Interact further with the user if they were prompted for missing arguments. + * + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return void + */ + protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void + { + if ($this->didReceiveOptions($input)) { + return; + } + + $model = select( + 'What model should this resource relies to? (Optional)', + $this->possibleModels(), + ); + + if ($model) { + $input->setOption('model', $model); + } + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions(): array + { + return [ + ['model', null, InputOption::VALUE_REQUIRED, 'The model associated with this resource'], + ]; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Rest\Resources'; + } + + /** + * Get the fully-qualified model class name. + * + * @param string $model + * + * @throws \InvalidArgumentException + * + * @return string + */ + protected function parseModel($model): string + { + if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) { + throw new InvalidArgumentException('Model name contains invalid characters.'); + } + + return $this->qualifyModel($model); + } +} diff --git a/src/Console/Commands/ResponseCommand.php b/src/Console/Commands/ResponseCommand.php deleted file mode 100644 index f69c706..0000000 --- a/src/Console/Commands/ResponseCommand.php +++ /dev/null @@ -1,95 +0,0 @@ -resolveStubPath('/stubs/rest/response.stub'); - } - - /** - * Get the path where the action file should be created. - * - * @param string $name - * - * @return string - */ - protected function getPath($name) - { - if (!is_null($this->option('path'))) { - return $this->option('path').'/'.$this->argument('name').'.php'; - } - - return parent::getPath($name); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * - * @return string - */ - protected function getDefaultNamespace($rootNamespace) - { - return $rootNamespace.'\Rest\Responses'; - } -} diff --git a/src/Console/Commands/ResponseMakeCommand.php b/src/Console/Commands/ResponseMakeCommand.php new file mode 100644 index 0000000..8aca145 --- /dev/null +++ b/src/Console/Commands/ResponseMakeCommand.php @@ -0,0 +1,67 @@ +resolveStubPath('/../stubs/response.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace.'\Rest\Responses'; + } +} diff --git a/src/Console/ResolvesStubPath.php b/src/Console/ResolvesStubPath.php deleted file mode 100644 index af4aa4f..0000000 --- a/src/Console/ResolvesStubPath.php +++ /dev/null @@ -1,20 +0,0 @@ -laravel->basePath(trim($stub, '/'))) - ? $customPath - : __DIR__.str_replace('rest/', '', $stub); - } -} diff --git a/src/Console/stubs/base-controller.stub b/src/Console/stubs/base-controller.stub index 09feefe..8a191e7 100644 --- a/src/Console/stubs/base-controller.stub +++ b/src/Console/stubs/base-controller.stub @@ -4,7 +4,7 @@ namespace {{ namespace }}; use Lomkit\Rest\Http\Controllers\Controller as RestController; -abstract class Controller extends RestController +abstract class {{ class }} extends RestController { } diff --git a/src/Console/stubs/base-resource.stub b/src/Console/stubs/base-resource.stub index 6c31d55..dca82ba 100644 --- a/src/Console/stubs/base-resource.stub +++ b/src/Console/stubs/base-resource.stub @@ -4,7 +4,7 @@ namespace {{ namespace }}; use Lomkit\Rest\Http\Resource as RestResource; -abstract class Resource extends RestResource +abstract class {{ class }} extends RestResource { /** * Build a "search" query for fetching resource. diff --git a/src/Console/stubs/controller.stub b/src/Console/stubs/controller.stub index 9f69045..165a8f5 100644 --- a/src/Console/stubs/controller.stub +++ b/src/Console/stubs/controller.stub @@ -2,9 +2,9 @@ namespace {{ namespace }}; -use App\Rest\Controller as RestController; +use {{ rootNamespace }}Rest\Controllers\Controller; -class {{ class }} extends RestController +class {{ class }} extends Controller { /** * The resource the controller corresponds to. diff --git a/src/Console/stubs/resource.stub b/src/Console/stubs/resource.stub index bf60b3c..abe4c5e 100644 --- a/src/Console/stubs/resource.stub +++ b/src/Console/stubs/resource.stub @@ -2,9 +2,9 @@ namespace {{ namespace }}; -use App\Rest\Resource as RestResource; +use {{ rootNamespace }}Rest\Resources\Resource; -class {{ class }} extends RestResource +class {{ class }} extends Resource { /** * The model the resource corresponds to. @@ -13,13 +13,6 @@ class {{ class }} extends RestResource */ public static $model = \{{ namespacedModel }}::class; - /** - * The default value for the pagination limit. - * - * @var int - */ - public int $defaultLimit = 50; - /** * The exposed fields that could be provided * @param RestRequest $request diff --git a/src/Console/stubs/rest-documentation-service-provider.stub b/src/Console/stubs/rest-documentation-service-provider.stub index 2682131..5a5e59c 100644 --- a/src/Console/stubs/rest-documentation-service-provider.stub +++ b/src/Console/stubs/rest-documentation-service-provider.stub @@ -8,7 +8,7 @@ use Lomkit\Rest\Documentation\Schemas\Operation; use Lomkit\Rest\Documentation\Schemas\Path; use Lomkit\Rest\Facades\Rest; -class RestDocumentationServiceProvider extends ServiceProvider +class {{ class }} extends ServiceProvider { /** * Register any application services. diff --git a/src/Console/stubs/user-controller.stub b/src/Console/stubs/user-controller.stub deleted file mode 100644 index 17c8aed..0000000 --- a/src/Console/stubs/user-controller.stub +++ /dev/null @@ -1,15 +0,0 @@ - - */ - public static $resource = \App\Rest\Resources\UserResource::class; -} diff --git a/src/Console/stubs/user-resource.stub b/src/Console/stubs/user-resource.stub deleted file mode 100644 index aa1a43b..0000000 --- a/src/Console/stubs/user-resource.stub +++ /dev/null @@ -1,81 +0,0 @@ - - */ - public static $model = \App\User::class; - - /** - * The default value for the pagination limit. - * - * @var int - */ - public int $defaultLimit = 50; - - /** - * The exposed fields that could be provided - * @param RestRequest $request - * @return array - */ - public function fields(\Lomkit\Rest\Http\Requests\RestRequest $request): array - { - return [ - 'id', - 'name', - 'email', - 'password' - ]; - } - - /** - * The exposed relations that could be provided - * @param RestRequest $request - * @return array - */ - public function relations(\Lomkit\Rest\Http\Requests\RestRequest $request): array - { - return []; - } - - /** - * The exposed scopes that could be provided - * @param RestRequest $request - * @return array - */ - public function scopes(\Lomkit\Rest\Http\Requests\RestRequest $request): array - { - return []; - } - - /** - * The exposed limits that could be provided - * @param RestRequest $request - * @return array - */ - public function limits(\Lomkit\Rest\Http\Requests\RestRequest $request): array - { - return [ - 10, - 25, - 50 - ]; - } - - /** - * The actions that should be linked - * @param RestRequest $request - * @return array - */ - public function actions(\Lomkit\Rest\Http\Requests\RestRequest $request): array - { - return []; - } -} diff --git a/src/RestServiceProvider.php b/src/RestServiceProvider.php index 4254a11..ff4f166 100644 --- a/src/RestServiceProvider.php +++ b/src/RestServiceProvider.php @@ -2,18 +2,20 @@ namespace Lomkit\Rest; +use Illuminate\Foundation\Events\PublishingStubs; +use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; -use Lomkit\Rest\Console\Commands\ActionCommand; -use Lomkit\Rest\Console\Commands\BaseControllerCommand; -use Lomkit\Rest\Console\Commands\BaseResourceCommand; -use Lomkit\Rest\Console\Commands\ControllerCommand; -use Lomkit\Rest\Console\Commands\DocumentationCommand; -use Lomkit\Rest\Console\Commands\DocumentationProviderCommand; -use Lomkit\Rest\Console\Commands\InstructionCommand; +use Lomkit\Rest\Console\Commands\ActionMakeCommand; +use Lomkit\Rest\Console\Commands\BaseControllerMakeCommand; +use Lomkit\Rest\Console\Commands\BaseResourceMakeCommand; +use Lomkit\Rest\Console\Commands\ControllerMakeCommand; +use Lomkit\Rest\Console\Commands\Documentation\DocumentationCommand; +use Lomkit\Rest\Console\Commands\Documentation\DocumentationServiceProviderMakeCommand; +use Lomkit\Rest\Console\Commands\InstructionMakeCommand; use Lomkit\Rest\Console\Commands\QuickStartCommand; -use Lomkit\Rest\Console\Commands\ResourceCommand; -use Lomkit\Rest\Console\Commands\ResponseCommand; +use Lomkit\Rest\Console\Commands\ResourceMakeCommand; +use Lomkit\Rest\Console\Commands\ResponseMakeCommand; use Lomkit\Rest\Contracts\QueryBuilder; use Lomkit\Rest\Http\Requests\ActionsRequest; use Lomkit\Rest\Http\Requests\DestroyRequest; @@ -53,6 +55,8 @@ public function boot() $this->registerCommands(); $this->registerPublishing(); + $this->registerStubs(); + $this->registerRoutes(); $this->loadViewsFrom( @@ -78,7 +82,7 @@ private function registerRoutes() * * @return array */ - private function routeConfiguration() + private function routeConfiguration(): array { return [ 'domain' => config('rest.documentation.routing.domain'), @@ -92,30 +96,47 @@ private function routeConfiguration() * * @return void */ - protected function registerCommands() + protected function registerCommands(): void { if ($this->app->runningInConsole()) { $this->commands([ - BaseControllerCommand::class, - ControllerCommand::class, - BaseResourceCommand::class, - ResourceCommand::class, - ResponseCommand::class, + BaseControllerMakeCommand::class, + ControllerMakeCommand::class, + BaseResourceMakeCommand::class, + ResourceMakeCommand::class, + ResponseMakeCommand::class, QuickStartCommand::class, - ActionCommand::class, - InstructionCommand::class, + ActionMakeCommand::class, + InstructionMakeCommand::class, DocumentationCommand::class, - DocumentationProviderCommand::class, + DocumentationServiceProviderMakeCommand::class, ]); } } + /** + * Register the stubs on the default laravel stub publish command. + */ + protected function registerStubs(): void + { + Event::listen(function (PublishingStubs $event) { + $event->add(realpath(__DIR__.'/Console/stubs/action.stub'), 'rest.action.stub'); + $event->add(realpath(__DIR__.'/Console/stubs/base-controller.stub'), 'rest.base-controller.stub'); + $event->add(realpath(__DIR__.'/Console/stubs/base-resource.stub'), 'rest.base-resource.stub'); + $event->add(realpath(__DIR__.'/Console/stubs/controller.stub'), 'rest.controller.stub'); + $event->add(realpath(__DIR__.'/Console/stubs/instruction.stub'), 'rest.instruction.stub'); + $event->add(realpath(__DIR__.'/Console/stubs/resource.stub'), 'rest.resource.stub'); + $event->add(realpath(__DIR__.'/Console/stubs/response.stub'), 'rest.response.stub'); + $event->add(realpath(__DIR__.'/Console/stubs/rest-documentation-service-provider.stub'), 'rest.rest-documentation-service-provider.stub'); + }); + } + /** * Register the package's publishable resources. * * @return void */ - private function registerPublishing() + private function registerPublishing(): void { if ($this->app->runningInConsole()) { $this->publishes([ @@ -129,7 +150,7 @@ private function registerPublishing() * * @return void */ - protected function registerServices() + protected function registerServices(): void { $this->app->singleton('lomkit-rest', Rest::class); diff --git a/tests/Feature/Commands/ActionCommandTest.php b/tests/Feature/Commands/ActionCommandTest.php deleted file mode 100644 index 562012a..0000000 --- a/tests/Feature/Commands/ActionCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan('rest:action', ['name' => 'TestAction', '--path' => './.phpunit.cache'])->assertOk(); - - $this->assertFileExists('./.phpunit.cache/TestAction.php'); - } -} diff --git a/tests/Feature/Commands/ActionMakeCommandTest.php b/tests/Feature/Commands/ActionMakeCommandTest.php new file mode 100644 index 0000000..81fc115 --- /dev/null +++ b/tests/Feature/Commands/ActionMakeCommandTest.php @@ -0,0 +1,23 @@ +artisan('rest:action', ['name' => 'TestAction']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Rest/Actions/TestAction.php')); + $this->assertStringContainsString('class TestAction extends RestAction', file_get_contents(app_path('Rest/Actions/TestAction.php'))); + + unlink(app_path('Rest/Actions/TestAction.php')); + } +} diff --git a/tests/Feature/Commands/BaseControllerCommandTest.php b/tests/Feature/Commands/BaseControllerCommandTest.php deleted file mode 100644 index 0b9eefd..0000000 --- a/tests/Feature/Commands/BaseControllerCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan('rest:base-controller', ['name' => 'TestBaseController', '--path' => './.phpunit.cache'])->assertOk(); - - $this->assertFileExists('./.phpunit.cache/TestBaseController.php'); - } -} diff --git a/tests/Feature/Commands/BaseControllerMakeCommandTest.php b/tests/Feature/Commands/BaseControllerMakeCommandTest.php new file mode 100644 index 0000000..63251cb --- /dev/null +++ b/tests/Feature/Commands/BaseControllerMakeCommandTest.php @@ -0,0 +1,23 @@ +artisan('rest:base-controller', ['name' => 'Controller']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Rest/Controllers/Controller.php')); + $this->assertStringContainsString('class Controller extends RestController', file_get_contents(app_path('Rest/Controllers/Controller.php'))); + + unlink(app_path('Rest/Controllers/Controller.php')); + } +} diff --git a/tests/Feature/Commands/BaseResourceCommandTest.php b/tests/Feature/Commands/BaseResourceCommandTest.php deleted file mode 100644 index e38ffee..0000000 --- a/tests/Feature/Commands/BaseResourceCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan('rest:base-resource', ['name' => 'TestBaseResource', '--path' => './.phpunit.cache'])->assertOk(); - - $this->assertFileExists('./.phpunit.cache/TestBaseResource.php'); - } -} diff --git a/tests/Feature/Commands/BaseResourceMakeCommandTest.php b/tests/Feature/Commands/BaseResourceMakeCommandTest.php new file mode 100644 index 0000000..50cf45d --- /dev/null +++ b/tests/Feature/Commands/BaseResourceMakeCommandTest.php @@ -0,0 +1,23 @@ +artisan('rest:base-resource', ['name' => 'Resource']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Rest/Resources/Resource.php')); + $this->assertStringContainsString('class Resource extends RestResource', file_get_contents(app_path('Rest/Resources/Resource.php'))); + + unlink(app_path('Rest/Resources/Resource.php')); + } +} diff --git a/tests/Feature/Commands/ControllerCommandTest.php b/tests/Feature/Commands/ControllerCommandTest.php deleted file mode 100644 index aa9b8ae..0000000 --- a/tests/Feature/Commands/ControllerCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan('rest:controller', ['name' => 'TestController', '--path' => './.phpunit.cache'])->assertOk(); - - $this->assertFileExists('./.phpunit.cache/TestController.php'); - } -} diff --git a/tests/Feature/Commands/ControllerMakeCommandTest.php b/tests/Feature/Commands/ControllerMakeCommandTest.php new file mode 100644 index 0000000..10cd50e --- /dev/null +++ b/tests/Feature/Commands/ControllerMakeCommandTest.php @@ -0,0 +1,40 @@ +artisan('rest:controller', ['name' => 'TestController']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Rest/Controllers/TestController.php')); + $this->assertStringContainsString('class TestController extends Controller', file_get_contents(app_path('Rest/Controllers/TestController.php'))); + $this->assertStringContainsString('public static $resource = \Resource::class;', file_get_contents(app_path('Rest/Controllers/TestController.php'))); + + unlink(app_path('Rest/Controllers/TestController.php')); + } + + public function test_make_controller_command_with_resource() + { + @unlink(app_path('Rest/Controllers/TestController.php')); + + $this + ->artisan('rest:controller', ['name' => 'TestController', '--resource' => 'TestResource']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Rest/Controllers/TestController.php')); + $this->assertStringContainsString('class TestController extends Controller', file_get_contents(app_path('Rest/Controllers/TestController.php'))); + $this->assertStringContainsString('public static $resource = \App\Rest\Resources\TestResource::class;', file_get_contents(app_path('Rest/Controllers/TestController.php'))); + + unlink(app_path('Rest/Controllers/TestController.php')); + } +} diff --git a/tests/Feature/Commands/DocumentationCommandTest.php b/tests/Feature/Commands/DocumentationCommandTest.php index cb92ab0..cc4675e 100644 --- a/tests/Feature/Commands/DocumentationCommandTest.php +++ b/tests/Feature/Commands/DocumentationCommandTest.php @@ -8,15 +8,23 @@ class DocumentationCommandTest extends TestCase { public function test_create_documentation_class(): void { - $this->artisan('rest:documentation', ['--path' => './.phpunit.cache'])->assertOk(); + $this->artisan('rest:documentation')->assertOk(); - $this->assertFileExists('./.phpunit.cache/openapi.json'); + $this->assertFileExists(public_path('vendor/rest/openapi.json')); } - public function test_create_documentation_service_provider_class(): void + public function test_make_documentation_service_provider_command() { - $this->artisan('rest:documentation-provider', ['--path' => './.phpunit.cache'])->assertOk(); + @unlink(app_path('Providers/RestDocumentationServiceProvider.php')); - $this->assertFileExists('./.phpunit.cache/RestDocumentationServiceProvider.php'); + $this + ->artisan('rest:documentation-provider', ['name' => 'RestDocumentationServiceProvider']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Providers/RestDocumentationServiceProvider.php')); + $this->assertStringContainsString('class RestDocumentationServiceProvider extends ServiceProvider', file_get_contents(app_path('Providers/RestDocumentationServiceProvider.php'))); + + unlink(app_path('Providers/RestDocumentationServiceProvider.php')); } } diff --git a/tests/Feature/Commands/InstructionCommandTest.php b/tests/Feature/Commands/InstructionCommandTest.php deleted file mode 100644 index 66037c0..0000000 --- a/tests/Feature/Commands/InstructionCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan('rest:instruction', ['name' => 'TestInstruction', '--path' => './.phpunit.cache'])->assertOk(); - - $this->assertFileExists('./.phpunit.cache/TestInstruction.php'); - } -} diff --git a/tests/Feature/Commands/QuickStartCommandTest.php b/tests/Feature/Commands/QuickStartCommandTest.php index b2bd07e..de3d432 100644 --- a/tests/Feature/Commands/QuickStartCommandTest.php +++ b/tests/Feature/Commands/QuickStartCommandTest.php @@ -61,11 +61,8 @@ public function test_quick_start_command_does_not_duplicate_routes() public function test_quick_start_command_updates_user_model_namespace() { - // Simulate the existence of App\Models\User - File::makeDirectory(app_path('Models'), 0755, true); - File::put(app_path('Models/User.php'), 'artisan('rest:quick-start')->assertExitCode(0); + $this->artisan('rest:quick-start') + ->assertExitCode(0); $this->assertFileExists(app_path('Rest/Resources/UserResource.php')); $this->assertFileExists(app_path('Rest/Controllers/UsersController.php')); @@ -73,10 +70,10 @@ public function test_quick_start_command_updates_user_model_namespace() $resourceContent = File::get(app_path('Rest/Resources/UserResource.php')); $controllerContent = File::get(app_path('Rest/Controllers/UsersController.php')); - $this->assertStringContainsString('\App\Models\User::class', $resourceContent); + $this->assertStringContainsString('\App\User::class', $resourceContent); $this->assertStringContainsString('\App\Rest\Resources\UserResource::class', $controllerContent); - $this->assertStringContainsString('public static $model = \App\Models\User::class;', $resourceContent); + $this->assertStringContainsString('public static $model = \App\User::class;', $resourceContent); } } diff --git a/tests/Feature/Commands/ResourceCommandTest.php b/tests/Feature/Commands/ResourceCommandTest.php deleted file mode 100644 index d225a8c..0000000 --- a/tests/Feature/Commands/ResourceCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan('rest:resource', ['name' => 'TestResource', '--path' => './.phpunit.cache'])->assertOk(); - - $this->assertFileExists('./.phpunit.cache/TestResource.php'); - } -} diff --git a/tests/Feature/Commands/ResourceMakeCommandTest.php b/tests/Feature/Commands/ResourceMakeCommandTest.php new file mode 100644 index 0000000..1a609d8 --- /dev/null +++ b/tests/Feature/Commands/ResourceMakeCommandTest.php @@ -0,0 +1,40 @@ +artisan('rest:resource', ['name' => 'TestResource']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Rest/Resources/TestResource.php')); + $this->assertStringContainsString('class TestResource extends Resource', file_get_contents(app_path('Rest/Resources/TestResource.php'))); + $this->assertStringContainsString('public static $model = \Model::class;', file_get_contents(app_path('Rest/Resources/TestResource.php'))); + + unlink(app_path('Rest/Resources/TestResource.php')); + } + + public function test_make_resource_command_with_model() + { + @unlink(app_path('Rest/Resources/TestResource.php')); + + $this + ->artisan('rest:resource', ['name' => 'TestResource', '--model' => 'Test']) + ->assertOk() + ->run(); + + $this->assertFileExists(app_path('Rest/Resources/TestResource.php')); + $this->assertStringContainsString('class TestResource extends Resource', file_get_contents(app_path('Rest/Resources/TestResource.php'))); + $this->assertStringContainsString('public static $model = \App\Test::class;', file_get_contents(app_path('Rest/Resources/TestResource.php'))); + + unlink(app_path('Rest/Resources/TestResource.php')); + } +} diff --git a/tests/Feature/Commands/ResponseCommandTest.php b/tests/Feature/Commands/ResponseCommandTest.php deleted file mode 100644 index 26f9ebd..0000000 --- a/tests/Feature/Commands/ResponseCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan('rest:response', ['name' => 'TestResponse', '--path' => './.phpunit.cache'])->assertOk(); - - $this->assertFileExists('./.phpunit.cache/TestResponse.php'); - } -} diff --git a/tests/Unit/LaravelScoutTest.php b/tests/Unit/LaravelScoutTest.php index 3eb78e2..45b5d44 100644 --- a/tests/Unit/LaravelScoutTest.php +++ b/tests/Unit/LaravelScoutTest.php @@ -1,5 +1,7 @@ dispatch($event = new \Illuminate\Foundation\Events\PublishingStubs([])); + + $this->assertEquals( + [ + realpath(__DIR__.'/../../src/Console/stubs/action.stub') => 'rest.action.stub', + realpath(__DIR__.'/../../src/Console/stubs/base-controller.stub') => 'rest.base-controller.stub', + realpath(__DIR__.'/../../src/Console/stubs/base-resource.stub') => 'rest.base-resource.stub', + realpath(__DIR__.'/../../src/Console/stubs/controller.stub') => 'rest.controller.stub', + realpath(__DIR__.'/../../src/Console/stubs/instruction.stub') => 'rest.instruction.stub', + realpath(__DIR__.'/../../src/Console/stubs/resource.stub') => 'rest.resource.stub', + realpath(__DIR__.'/../../src/Console/stubs/response.stub') => 'rest.response.stub', + realpath(__DIR__.'/../../src/Console/stubs/rest-documentation-service-provider.stub') => 'rest.rest-documentation-service-provider.stub', + ], + $event->stubs + ); + } +}