Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First functionality #1

Merged
merged 14 commits into from
Jun 14, 2024
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
[![Github Workflow Status][badge_build]][link_build]
[![License][badge_license]](https://laravel-lang.com/license.html)

## ToDo

У астрономик взять принцип хранения данных, а у Спати - способ их использования.

- https://github.com/Astrotomic/laravel-translatable
- https://github.com/spatie/laravel-translatable

## Documentation

See the [documentation](https://laravel-lang.com/packages-models.html) for detailed installation.
Expand Down
14 changes: 13 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"translations",
"translate",
"localization",
"locales",
"l18n"
],
"authors": [
Expand All @@ -29,8 +30,12 @@
},
"require": {
"php": "^8.1",
"composer/class-map-generator": "^1.3",
"dragon-code/support": "^6.13",
"illuminate/database": "^10.0 || ^11.0",
"illuminate/support": "^10.0 || ^11.0",
"laravel-lang/config": "^1.1"
"laravel-lang/config": "^1.4.2",
"laravel-lang/locales": "^2.8"
},
"require-dev": {
"orchestra/testbench": "^8.23 || ^9.1",
Expand Down Expand Up @@ -62,6 +67,13 @@
"preferred-install": "dist",
"sort-packages": true
},
"extra": {
"laravel": {
"providers": [
"LaravelLang\\Models\\ServiceProvider"
]
}
},
"scripts": {
"test": "vendor/bin/pest --parallel"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use LaravelLang\Config\Data\Shared\ModelsData;
use LaravelLang\Config\Facades\Config;

return new class extends Migration {
public function up(): void
{
$config = $this->config();

Schema::connection($config->connection)->create($config->table, function (Blueprint $table) {
$table->id();

$table->string('model_type', 255);
$table->string('model_id', 255);

$table->jsonb('content')->nullable();

$table->timestamps();
$table->softDeletes();
});

DB::statement(
"CREATE UNIQUE INDEX {$config->table}_model_type_model_id_unique ON {$config->table} (model_type, model_id) WHERE deleted_at IS NULL"
);
}

public function down(): void
{
$config = $this->config();

Schema::connection($config->connection)->dropIfExists($config->table);
}

protected function config(): ModelsData
{
return Config::shared()->models;
}
};
3 changes: 3 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@

<env name="SESSION_DRIVER" value="array" />
<env name="CACHE_STORE" value="array" />

<env name="DB_CONNECTION" value="testing" />
<env name="DB_DATABASE" value=":memory:" />
</php>
</phpunit>
Empty file removed src/.gitkeep
Empty file.
32 changes: 32 additions & 0 deletions src/Casts/TranslationCast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
use LaravelLang\Config\Facades\Config;
use LaravelLang\Models\Data\ContentData;

class TranslationCast implements CastsAttributes
{
public function get(Model $model, string $key, mixed $value, array $attributes): ?ContentData
{
return new ContentData(
$value ? json_decode($value, true) : []
);
}

/**
* @param ContentData $value
*/
public function set(Model $model, string $key, mixed $value, array $attributes): ?string
{
if ($value) {
return $value->toJson(Config::shared()->models->flags);
}

return null;
}
}
18 changes: 18 additions & 0 deletions src/Concerns/HasSetUp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Concerns;

use LaravelLang\Config\Facades\Config;

trait HasSetUp
{
public function initializeHasSetUp(): void
{
$config = Config::shared()->models;

$this->connection = $config->connection;
$this->table = $config->table;
}
}
17 changes: 17 additions & 0 deletions src/Concerns/HasStrings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Concerns;

trait HasStrings
{
protected function trim(mixed $value): mixed
{
if (is_string($value)) {
return trim($value) ?: null;
}

return $value;
}
}
48 changes: 48 additions & 0 deletions src/Console/ModelsHelperCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Console;

use DragonCode\Support\Facades\Filesystem\Directory;
use Illuminate\Console\Command;
use LaravelLang\Config\Facades\Config;
use LaravelLang\Models\Services\ClassMap;
use LaravelLang\Models\Services\HelperGenerator;

class ModelsHelperCommand extends Command
{
protected $signature = 'lang:models';

protected $description = 'Generating autocomplete translatable properties for models';

public function handle(): void
{
$this->cleanUp();
$this->process();
}

protected function process(): void
{
foreach ($this->models() as $model) {
$this->components->task($model, fn () => $this->generate($model));
}
}

protected function generate(string $model): void
{
HelperGenerator::of($model)->generate();
}

protected function models(): array
{
return ClassMap::get();
}

protected function cleanUp(): void
{
Directory::ensureDelete(
Config::shared()->models->helpers
);
}
}
114 changes: 114 additions & 0 deletions src/Data/ContentData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Data;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use LaravelLang\LocaleList\Locale;
use LaravelLang\Locales\Facades\Locales;
use LaravelLang\Models\Concerns\HasStrings;
use LaravelLang\Models\Exceptions\UnavailableLocaleException;

class ContentData implements Arrayable, Jsonable
{
use HasStrings;

public function __construct(
protected array $locales
) {}

public function set(
string $column,
array|ContentData|float|int|string|null $value,
Locale|string|null $locale = null
): void {
$locale = $locale ? $this->locale($locale) : $this->getDefault();

$value = $this->trim($value);

if ($value instanceof ContentData) {
$this->locales[$column] = $value->getRaw($column);

return;
}

is_array($value)
? $this->locales[$column] = $value
: $this->locales[$column][$locale] = $value;
}

public function get(string $column, Locale|string|null $locale = null): float|int|string|null
{
if ($locale) {
return $this->locales[$column][$this->locale($locale)] ?? null;
}

return $this->locales[$column][$this->getDefault()]
?? $this->locales[$column][$this->getFallback()]
?? null;
}

public function has(string $column, Locale|string|null $locale = null): bool
{
if ($locale) {
return isset($this->locales[$column][$this->locale($locale)]);
}

return isset($this->locales[$column][$this->getDefault()])
|| isset($this->locales[$column][$this->getFallback()]);
}

public function forget(string $column, Locale|string|null $locale = null): void
{
if ($locale) {
unset($this->locales[$column][$this->locale($locale)]);

return;
}

unset($this->locales[$column]);
}

public function getRaw(?string $path = null): mixed
{
return $path ? data_get($this->locales, $path) : $this->locales;
}

public function toJson($options = 0): ?string
{
if ($items = $this->toArray()) {
return json_encode($items, $options);
}

return null;
}

public function toArray(): array
{
return collect($this->locales)
->map(fn (array $locale) => array_filter($locale, fn (mixed $value) => ! blank($value)))
->filter()
->all();
}

protected function locale(Locale|string|null $locale): string
{
if (! Locales::isInstalled($locale)) {
throw new UnavailableLocaleException($locale);
}

return Locales::get($locale)->code;
}

protected function getDefault(): string
{
return Locales::getDefault()->code;
}

protected function getFallback(): string
{
return Locales::getFallback()->code;
}
}
17 changes: 17 additions & 0 deletions src/Events/AllTranslationsHasBeenForgetEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Events;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;

class AllTranslationsHasBeenForgetEvent
{
use Dispatchable;

public function __construct(
public Model $model
) {}
}
19 changes: 19 additions & 0 deletions src/Events/TranslationHasBeenForgetEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Events;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;

class TranslationHasBeenForgetEvent
{
use Dispatchable;

public function __construct(
public Model $model,
public string $column,
public ?string $locale
) {}
}
21 changes: 21 additions & 0 deletions src/Events/TranslationHasBeenSetEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace LaravelLang\Models\Events;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;

class TranslationHasBeenSetEvent
{
use Dispatchable;

public function __construct(
public Model $model,
public string $column,
public ?string $locale,
public mixed $oldValue,
public mixed $newValue,
) {}
}
Loading
Loading