Skip to content

Commit

Permalink
[Feature] Add Artisan generators
Browse files Browse the repository at this point in the history
Merge pull request #26 from jstoone/artisan-generators

Can now generate classes for a JSON API resource using Artisan generator commands. To view a list of all available commands, run `php artisan list make:json-api`.

The `make:json-api:resource` is the key command that generates all classes for a specific resource. However, each class can be individually created by using separate generators that are also in the `make:json-api` namespace.

Default settings for the generators, including the application's folder structure for the classes, are configurable via the `json-api.php` config file.
  • Loading branch information
lindyhopchris authored Nov 8, 2016
2 parents d0767af + 487ba97 commit 1804aa5
Show file tree
Hide file tree
Showing 16 changed files with 857 additions and 0 deletions.
35 changes: 35 additions & 0 deletions config/json-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,39 @@
*/
'adapters' => [],

/*
|--------------------------------------------------------------------------
| Generators
|--------------------------------------------------------------------------
|
| This package supplies a set of handy generators. These make it possible
| to easily generate every class needed to implement a JSON API resource.
|
| To smoothen out any rough edges, without enforcing any specific patterns
| we have included a few handy configuration options, so that the generators
| can follow your workflow.
|
| `namespace` = The folder in which you will be storing everything
| related to LaravelJsonApi.
| (default: 'JsonApi')
|
| 'by_resource` = Whether your JSON API resources relate to Eloquent models or not.
| You can override the setting here when running a generator. If the
| setting here is `true` running a generator with `--no-eloquent` will
| override it; if the setting is `false`, then `--eloquent` is the override.
| Choose:
| - true (default)
| e.g. \App\JsonApi\Tasks\{Schema, Request, Hydrator}
| - false
| e.g. \App\JsonApi\Schemas\{User, Post, Comment}
| e.g. \App\JsonApi\Requests\{User, Post, Comment}
|
| `use_eloquent` = Whether you are using Eloquent ORM in this app.
| (default: true)
*/
'generator' => [
'namespace' => 'JsonApi',
'by-resource' => true,
'use-eloquent' => true,
],
];
250 changes: 250 additions & 0 deletions src/Console/Commands/AbstractGeneratorCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
<?php

namespace CloudCreativity\LaravelJsonApi\Console\Commands;

use Illuminate\Console\GeneratorCommand as LaravelGeneratorCommand;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

abstract class JsonApiGeneratorCommand extends LaravelGeneratorCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name;

/**
* The console command description.
*
* @var string
*/
protected $description;

/**
* The type of class being generated.
*
* @var string
*/
protected $type;

/**
* Whether the resource type is non-dependent on eloquent.
*
* @var boolean
*/
protected $isIndependent = false;

/**
* Whether the resource should use eloquent implementations.
*
* @var boolean
*/
protected $useEloquent;

/**
* The folder within the root namespace, where files should be generated.
*
* @var string
*/
protected $subNamespace;

/**
* Whether generated files should be grouped by their resource files.
*
* @var mixed
*/
protected $namespaceByResource;

/**
* The location of all generator stubs
*
* @var string
*/
private $stubsDirectory = __DIR__.'/../../../stubs';

/**
* Create a new config clear command instance.
*
* @return void
*/
public function __construct(Filesystem $files)
{
parent::__construct($files);

$this->useEloquent = config('json-api.generator.use-eloquent');
$this->subNamespace = config('json-api.generator.namespace');
$this->namespaceByResource = config('json-api.generator.by-resource');
}

/**
* Build the class with the given name.
* Remove the base controller import if we are already in base namespace.
*
* @param string $name
* @return string
*/
protected function buildClass($name)
{
$namespace = $this->getNamespace($name);

$stub = $this->files->get($this->getStub());

$this->replaceNamespace($stub, $name)
->replaceResourceType($stub, $this->getResourceName());

return $stub;
}

/**
* Replace the value of the resource type constant
*
* @param mixed $stub
* @param mixed $resource
*/
protected function replaceResourceType(&$stub, $resource)
{
$stub = str_replace(
'dummyResourceType', snake_case($resource, '-'), $stub
);

return $this;
}

/**
* Get the resource name
*
* @return string
*/
protected function getResourceName()
{
$name = ucwords($this->argument('resource'));

if($this->namespaceByResource) {
return str_plural($name);
}

return $name;
}

/**
* Get the desired class name from the input.
*
* @return string
*/
protected function getNameInput()
{
if( ! $this->namespaceByResource) {
return $this->getResourceName();
}

return $this->type;
}

/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
if($this->isIndependent) {
return $this->getStubFor('independent');
}

if ($this->isEloquent()) {
return $this->getStubFor('eloquent');
}

return $this->getStubFor('abstract');
}

/**
* Get the stub for specific generator type
*
* @param string implementationType
*/
private function getStubFor($implementationType)
{
return implode('', [
$this->stubsDirectory,
'/',
$implementationType,
'/',
lcfirst($this->type),
'.stub'
]);
}

/**
* Determine whether a resource is eloquent or not
*
* @return boolean
*/
private function isEloquent()
{
if($this->isIndependent) {
return false;
}

if($this->option('no-eloquent')) {
return false;
}

return $this->option('eloquent') ?: $this->useEloquent;
}

/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
protected function getDefaultNamespace($rootNamespace)
{
$namespace = [
$rootNamespace, // #0
'\\', // #1
$this->subNamespace, // #2
'\\', // #3
$this->getResourceName() // #4
];

if(! $this->namespaceByResource) {
$namespace[4] = str_plural($this->type);
}

return implode('', $namespace);
}

/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['resource', InputArgument::REQUIRED, "The resource for which a {$this->type} class will be generated"],
];
}

/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
if($this->isIndependent) {
return [];
}

return [
['eloquent', 'e', InputOption::VALUE_NONE, 'Use eloquent as adapter'],
['no-eloquent', 'ne', InputOption::VALUE_NONE, 'Use an abstract adapter'],
];
}
}
27 changes: 27 additions & 0 deletions src/Console/Commands/HydratorMakeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace CloudCreativity\LaravelJsonApi\Console\Commands;

class HydratorMakeCommand extends AbstractGeneratorCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:json-api:hydrator';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new JSON API resource hydrator';

/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Hydrator';
}
34 changes: 34 additions & 0 deletions src/Console/Commands/RequestMakeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace CloudCreativity\LaravelJsonApi\Console\Commands;

class RequestMakeCommand extends AbstractGeneratorCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:json-api:request';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new JSON API resource request';

/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Request';

/**
* Whether the resource type is non-dependent on eloquent
*
* @var mixed
*/
protected $isIndependent = true;
}
Loading

0 comments on commit 1804aa5

Please sign in to comment.