Skip to content

Commit

Permalink
Very, very terrible code. But storage generation works 😅
Browse files Browse the repository at this point in the history
  • Loading branch information
andrey-helldar committed Jun 18, 2024
1 parent cee6f6c commit f605cf5
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 33 deletions.
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"illuminate/database": "^10.0 || ^11.0",
"illuminate/support": "^10.0 || ^11.0",
"laravel-lang/config": "dev-main as 1.6.0",
"laravel-lang/locales": "^2.8"
"laravel-lang/locales": "^2.8",
"laravel/prompts": "^0.1.24"
},
"require-dev": {
"orchestra/testbench": "^8.23 || ^9.1",
Expand All @@ -58,6 +59,7 @@
},
"autoload-dev": {
"psr-4": {
"App\\": "vendor/orchestra/testbench-core/laravel/app/",
"Tests\\": "tests/"
}
},
Expand Down
171 changes: 146 additions & 25 deletions src/Console/ModelMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,118 @@

namespace LaravelLang\Models\Console;

use App\Models\Test;
use DragonCode\Support\Facades\Instances\Instance;
use DragonCode\Support\Facades\Filesystem\File;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Console\ModelMakeCommand as BaseMakeCommand;
use Illuminate\Support\Str;
use LaravelLang\Config\Facades\Config;
use LaravelLang\Models\Eloquent\Translation;
use LaravelLang\Models\Services\ClassMap;

use function Laravel\Prompts\confirm;
use function Laravel\Prompts\info;
use function Laravel\Prompts\search;
use function Laravel\Prompts\text;

class ModelMakeCommand extends Command
{
protected $signature = 'make:model:localization {model} {--columns=*}';

protected $description = 'Creates a model for storing translations';

protected array $columns = ['locale', 'title', 'description'];

public function handle(): void
{
if (! $model = $this->model()) {
dd('nope', $model);
if (!$model = $this->model()) {
info('You haven\'t selected a model.');

return;
}

dd('aaa');

$columns = $this->columns();

$this->generateModel($model, $columns, Config::shared()->models->suffix);
$this->generateMigration($model, $columns, Config::shared()->models->suffix);
$this->generateHelper($model);
}

protected function generateModel(string $model, array $columns, string $suffix): void
{
$fillable = array_map(
fn (string $column) => sprintf(" '$column',"),
$columns
);

$casts = array_map(
fn (string $column) => sprintf(" '%s' => ColumnCast::class,", $column),
array_filter($columns, fn (string $column) => $column !== 'locale')
);

$content = \DragonCode\Support\Facades\Helpers\Str::of(
file_get_contents(__DIR__ . '/../../stubs/model.stub')
)->replaceFormat([
'namespace' => Str::of($model)->ltrim('\\')->beforeLast('\\'),
'model' => Str::afterLast($model, '\\'),
'suffix' => $suffix,
'fillable' => implode(PHP_EOL, $fillable),
'casts' => implode(PHP_EOL, $casts),
], '{{%s}}')
->toString();

$path = ClassMap::path($model);
$extension = pathinfo($path, PATHINFO_EXTENSION);

File::store(
Str::beforeLast($path, '.' . $extension) . $suffix . '.' . $extension,
$content
);
}

protected function generateMigration(string $model, array $columns, string $suffix): void
{
/** @var Model $base */
$base = new $model;

/** @var Translation $translated */
$translated = new ($model . $suffix);

$columns = array_map(
fn (string $column) => sprintf(" \$table->string('$column')->nullable();"),
array_filter($columns, fn (string $column) => $column !== 'locale')
);

$columnType = $base->getKeyType() === 'uuid' ? 'uuid' : 'bigInteger';

$content = \DragonCode\Support\Facades\Helpers\Str::of(
file_get_contents(__DIR__ . '/../../stubs/migration_create.stub')
)->replaceFormat([
'table' => $translated->getTable(),
'primaryType' => $columnType,
'columns' => implode(PHP_EOL, $columns),
], '{{%s}}')
->toString();

File::store(
database_path(sprintf("migrations/%s_create_%s_table.php", date('Y_m_d_His'), $translated->getTable())),
$content
);
}

protected function generateHelper(string $model): void
{
$this->call(ModelsHelperCommand::class, compact('model'));
}

protected function model(): ?string
{
$model = $this->askTranslationModel();
$model = $this->resolveModelClass(
$this->askTranslationModel()
);

if (! $this->modelExists($model)) {
if (! $this->askModel()) {
if (!$model) {
if (!$this->ascToCreate()) {
return null;
}

Expand All @@ -41,40 +125,77 @@ protected function model(): ?string
return $model;
}

protected function columns(): array
{
if ($columns = $this->option('columns')) {
return collect($columns)->prepend('locale')->all();
}

if ($columns = $this->askColumns()) {
return collect($columns)->prepend('locale')->all();
}

return $this->columns;
}

protected function askTranslationModel(): string
{
if ($model = $this->argument('model')) {
return $model;
}

return $this->ask('Specify the namespace of the model for which you want to create a storage');
return search(
'Specify the model name for which you want to create a translation repository:',
fn (string $value) => $this->findModel($value),
'E.g. Post'
);
}

protected function askModel(): bool
protected function findModel(string $value): array
{
return $this->confirm('No model with this namespace was found. Do you want to create it?', true);
return ClassMap::find($value);
}

protected function modelExists(string $class): bool
protected function askColumns(array $columns = []): ?array
{
dd(
$class ,
Str::start($class, '\\'),
class_exists(Str::start($class, '\\')),
Test::class,
class_exists(Test::class),
Instance::exists(Test::class)
);
return class_exists(Str::start($class, '\\'));
if ($column = text('Enter a column name', hint: 'Or press Enter for continue')) {
return array_filter(array_merge([$column], $this->askColumns($columns)));
}

return null;
}

protected function ascToCreate(): bool
{
return confirm('No model with this namespace was found. Do you want to create it?', true);
}

protected function resolveModelClass(string $model): ?string
{
$model = Str::of($model)->replace('/', '\\')->start('\\')->toString();

$values = [
$model,
'\App' . $model,
'\App\Models' . $model,
];

foreach ($values as $value) {
if (class_exists($value)) {
return $value;
}
}

return null;
}

protected function createBaseModel(string $model): void
{
$this->call(BaseMakeCommand::class, [
'name' => $model,
'name' => Str::after($model, 'App\\Models\\'),
'--migration' => true,
'--factory' => true,
'--seed' => true,
'--factory' => true,
'--seed' => true,
]);
}
}
2 changes: 1 addition & 1 deletion src/Console/ModelsHelperCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected function generate(string $model): void
protected function models(): array
{
if ($model = $this->argument('model')) {
return [$model];
return [ltrim($model, '\\')];
}

return ClassMap::get();
Expand Down
26 changes: 24 additions & 2 deletions src/Services/ClassMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Composer\ClassMapGenerator\ClassMapGenerator;
use DragonCode\Support\Facades\Instances\Instance;
use Illuminate\Support\Str;
use LaravelLang\Config\Facades\Config;
use LaravelLang\Models\HasTranslations;

Expand All @@ -19,18 +20,39 @@ public static function get(): array
->all();
}

public static function find(string $value): array
{
return collect(static::map())
->keys()
->filter(static fn (string $class) => static::contains($class, $value))
->all();
}

public static function path(string $class): ?string
{
return collect(static::map())
->filter(static fn (string $path, string $name) => $name === ltrim($class, '\\'))
->first();
}

protected static function map(): array
{
return ClassMapGenerator::createMap(static::path());
return ClassMapGenerator::createMap(static::modelsPath());
}

protected static function path(): string
protected static function modelsPath(): string
{
return base_path('app');
return Config::hidden()->models->directory;
}

protected static function isTranslatable(string $class): bool
{
return Instance::of($class, HasTranslations::class);
}

protected static function contains(string $class, string $needle): bool
{
return Str::of($class)->lower()->contains(strtolower($needle));
}
}
4 changes: 2 additions & 2 deletions stubs/migration_create.stub
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ return new class extends Migration {
Schema::create('{{table}}', function (Blueprint $table) {
$table->id();

$table->string('locale');

$table->{{primaryType}}('item_id')->index();

$table->string('locale');

{{columns}}

$table->unique(['item_id', 'locale']);
Expand Down
9 changes: 7 additions & 2 deletions stubs/model.stub
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ declare(strict_types=1);

namespace {{namespace}};

use LaravelLang\Models\Translation;
use LaravelLang\Models\Casts\ColumnCast;
use LaravelLang\Models\Eloquent\Translation;

class {{model}}{{suffix}} extends Translation
{
protected $fillable = [
{{columns}}
{{fillable}}
];

protected $casts = [
{{casts}}
];
}
1 change: 1 addition & 0 deletions tests/Unit/Console/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@
->toContain('$table->string(\'title\')->nullable()')
->toContain('$table->string(\'description\')->nullable()');

expect($migration)->toBeReadableFile();
expect($helper)->toBeReadableFile();
});

0 comments on commit f605cf5

Please sign in to comment.