Skip to content

Commit

Permalink
Add artisan setup commands (#56)
Browse files Browse the repository at this point in the history
Automate adding love_reacter_id & love_reactant_id columns to app models
  • Loading branch information
antonkomarev committed Jun 13, 2019
1 parent 52f7a6d commit 4a65521
Show file tree
Hide file tree
Showing 35 changed files with 945 additions and 75 deletions.
159 changes: 159 additions & 0 deletions src/Console/Commands/SetupReactable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php

/*
* This file is part of Laravel Love.
*
* (c) Anton Komarev <a.komarev@cybercog.su>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Cog\Laravel\Love\Console\Commands;

use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableContract;
use Cog\Laravel\Love\Reactant\Models\Reactant;
use Cog\Laravel\Love\Support\Database\MigrationCreator;
use Cog\Laravel\Love\Support\Database\AddForeignColumnStub;
use Illuminate\Console\Command;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Composer;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;

final class SetupReactable extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'love:setup-reactable
{model? : The name of the reactable model}
{--nullable : Indicate if foreign column allows null values}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Set up reactable model';

private $files;

private $creator;

private $composer;

public function __construct(Filesystem $files, MigrationCreator $creator, Composer $composer)
{
parent::__construct();

$this->files = $files;
$this->creator = $creator;
$this->composer = $composer;
}

public function handle(): int
{
$model = $this->resolveModel();
$model = $this->sanitizeName($model);
$foreignColumn = 'love_reactant_id';
$isForeignColumnNullable = boolval($this->option('nullable'));

if (!class_exists($model)) {
$this->error(sprintf(
'Model `%s` not exists.',
$model
));

return 1;
}

/** @var \Illuminate\Database\Eloquent\Model $model */
$model = new $model();

if ($this->isModelInvalid($model)) {
$this->error(sprintf(
'Model `%s` does not implements Reactable interface.',
get_class($model)
));

return 1;
}

$table = $model->getTable();
$referencedModel = new Reactant();
$referencedTable = $referencedModel->getTable();
$referencedColumn = $referencedModel->getKeyName();

if (!Schema::hasTable($referencedTable)) {
$this->error(sprintf(
'Referenced table `%s` does not exists in database.',
$referencedTable
));

return 1;
}

if (Schema::hasColumn($table, $foreignColumn)) {
$this->error(sprintf(
'Foreign column `%s` already exists in `%s` database table.',
$foreignColumn,
$table
));

return 1;
}

try {
$stub = new AddForeignColumnStub(
$this->files,
$table,
$referencedTable,
$foreignColumn,
$referencedColumn,
$isForeignColumnNullable
);

$this->creator->create($this->getMigrationsPath(), $stub);
} catch (FileNotFoundException $exception) {
$this->error($exception->getMessage());

return 1;
}

$this->composer->dumpAutoloads();

return 0;
}

private function resolveModel(): string
{
return $this->argument('model')
?? $this->ask('What model should be reactable?')
?? $this->resolveModel();
}

private function sanitizeName(string $name): string
{
$name = trim($name);
$name = Str::studly($name);

return $name;
}

private function isModelInvalid(Model $model): bool
{
return !$model instanceof ReactableContract;
}

private function getMigrationsPath(): string
{
return $this->laravel->databasePath('migrations');
}
}
159 changes: 159 additions & 0 deletions src/Console/Commands/SetupReacterable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php

/*
* This file is part of Laravel Love.
*
* (c) Anton Komarev <a.komarev@cybercog.su>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Cog\Laravel\Love\Console\Commands;

use Cog\Contracts\Love\Reacterable\Models\Reacterable as ReacterableContract;
use Cog\Laravel\Love\Reacter\Models\Reacter;
use Cog\Laravel\Love\Support\Database\MigrationCreator;
use Cog\Laravel\Love\Support\Database\AddForeignColumnStub;
use Illuminate\Console\Command;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Composer;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;

final class SetupReacterable extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'love:setup-reacterable
{model? : The name of the reacterable model}
{--nullable : Indicate if foreign column allows null values}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Set up reacterable model';

private $files;

private $creator;

private $composer;

public function __construct(Filesystem $files, MigrationCreator $creator, Composer $composer)
{
parent::__construct();

$this->files = $files;
$this->creator = $creator;
$this->composer = $composer;
}

public function handle(): int
{
$model = $this->resolveModel();
$model = $this->sanitizeName($model);
$foreignColumn = 'love_reacter_id';
$isForeignColumnNullable = boolval($this->option('nullable'));

if (!class_exists($model)) {
$this->error(sprintf(
'Model `%s` not exists.',
$model
));

return 1;
}

/** @var \Illuminate\Database\Eloquent\Model $model */
$model = new $model();

if ($this->isModelInvalid($model)) {
$this->error(sprintf(
'Model `%s` does not implements Reacterable interface.',
get_class($model)
));

return 1;
}

$table = $model->getTable();
$referencedModel = new Reacter();
$referencedTable = $referencedModel->getTable();
$referencedColumn = $referencedModel->getKeyName();

if (!Schema::hasTable($referencedTable)) {
$this->error(sprintf(
'Referenced table `%s` does not exists in database.',
$referencedTable
));

return 1;
}

if (Schema::hasColumn($table, $foreignColumn)) {
$this->error(sprintf(
'Foreign column `%s` already exists in `%s` database table.',
$foreignColumn,
$table
));

return 1;
}

try {
$stub = new AddForeignColumnStub(
$this->files,
$table,
$referencedTable,
$foreignColumn,
$referencedColumn,
$isForeignColumnNullable
);

$this->creator->create($this->getMigrationsPath(), $stub);
} catch (FileNotFoundException $exception) {
$this->error($exception->getMessage());

return 1;
}

$this->composer->dumpAutoloads();

return 0;
}

private function resolveModel(): string
{
return $this->argument('model')
?? $this->ask('What model should be reacterable?')
?? $this->resolveModel();
}

private function sanitizeName(string $name): string
{
$name = trim($name);
$name = Str::studly($name);

return $name;
}

private function isModelInvalid(Model $model): bool
{
return !$model instanceof ReacterableContract;
}

private function getMigrationsPath(): string
{
return $this->laravel->databasePath('migrations');
}
}
8 changes: 4 additions & 4 deletions src/Console/Commands/UpgradeV5ToV6.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

final class UpgradeV5ToV6 extends Command
{
Expand Down Expand Up @@ -320,10 +321,9 @@ private function getUserClass(): string
return $class;
}

private function reactionTypeNameFromLikeTypeName(
string $name
): string {
return studly_case(strtolower($name));
private function reactionTypeNameFromLikeTypeName(string $name): string
{
return Str::studly(strtolower($name));
}

private function deleteMigrationFiles(array $files): void
Expand Down
4 changes: 4 additions & 0 deletions src/LoveServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

use Cog\Laravel\Love\Console\Commands\ReactionTypeAdd;
use Cog\Laravel\Love\Console\Commands\Recount;
use Cog\Laravel\Love\Console\Commands\SetupReactable;
use Cog\Laravel\Love\Console\Commands\SetupReacterable;
use Cog\Laravel\Love\Console\Commands\UpgradeV5ToV6;
use Cog\Laravel\Love\Reactant\Listeners\DecrementAggregates;
use Cog\Laravel\Love\Reactant\Listeners\IncrementAggregates;
Expand Down Expand Up @@ -71,6 +73,8 @@ private function registerConsoleCommands(): void
$this->commands([
ReactionTypeAdd::class,
Recount::class,
SetupReactable::class,
SetupReacterable::class,
UpgradeV5ToV6::class,
]);
}
Expand Down
Loading

0 comments on commit 4a65521

Please sign in to comment.