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

Add underscore translatable support #1

Merged
merged 2 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,61 @@ $post->getVersionedFileUrl('file'); // returns https://www.example.com/storage/p
$post->deleteFile('file');
```

### Using with underscore translatable
This package ships with support for the [underscore translatable](github.com/esign/laravel-underscore-translatable) package.

Make sure to include the file, filename and mime columns within the `translatable` array:
```php
use Esign\ModelFiles\Concerns\HasFiles;
use Esign\UnderscoreTranslatable\UnderscoreTranslatable;
use Illuminate\Database\Eloquent\Model;

class UnderscoreTranslatablePost extends Model
{
use HasFiles;
use UnderscoreTranslatable;

public $translatable = [
'document',
'document_filename',
'document_mime',
];
}
```

Next up, your migrations should look like the following:
```php
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->boolean('document_en')->default(0);
$table->boolean('document_nl')->default(0);
$table->string('document_filename_en')->nullable();
$table->string('document_filename_nl')->nullable();
$table->string('document_mime_en')->nullable();
$table->string('document_mime_nl')->nullable();
});
```

You may now use the internal methods using the default or the specific locale:
```php
$post->hasFile('document'); // returns true/false
$post->getFolderPath('document'); // returns posts/document_en
$post->getFilePath('document'); // returns posts/document_en/1.pdf
$post->getFileMime('document'); // returns application/pdf
$post->getFileExtension('document'); // returns pdf
$post->getFileUrl('document'); // returns https://www.example.com/storage/posts/document_en/1.pdf
$post->getVersionedFileUrl('document'); // returns https://www.example.com/storage/posts/document_en/1.pdf?t=1675776047
```

```php
$post->hasFile('document_en'); // returns true/false
$post->getFolderPath('document_en'); // returns posts/document_en
$post->getFilePath('document_en'); // returns posts/document_en/1.pdf
$post->getFileMime('document_en'); // returns application/pdf
$post->getFileExtension('document_en'); // returns pdf
$post->getFileUrl('document_en'); // returns https://www.example.com/storage/posts/document_en/1.pdf
$post->getVersionedFileUrl('document_en'); // returns https://www.example.com/storage/posts/document_en/1.pdf?t=1675776047
```

### Testing

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
],
"require": {
"php": "^8.0",
"esign/laravel-underscore-translatable": "^1.4",
"illuminate/http": "^8.74|^9.0|^10.0",
"illuminate/support": "^8.0|^9.0|^10.0"
},
Expand Down
70 changes: 67 additions & 3 deletions src/Concerns/HasFiles.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,31 @@

namespace Esign\ModelFiles\Concerns;

use BadMethodCallException;
use Esign\ModelFiles\Exceptions\ModelNotPersistedException;
use Esign\UnderscoreTranslatable\UnderscoreTranslatable;
use Illuminate\Http\File;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

trait HasFiles
{
protected ?string $fileDisk = null;

public function hasFile(string $column): bool
{
return (bool) $this->getAttribute($column);
return (bool) $this->getAttribute(
$this->guessFileColumn($column)
);
}

public function setHasFile(string $column, bool $value): static
{
return $this->setAttribute($column, $value);
return $this->setAttribute(
$this->guessFileColumn($column),
$value
);
}

public function getFileName(string $column): ?string
Expand Down Expand Up @@ -63,7 +71,7 @@ public function getFilePath(string $column): ?string

public function getFolderPath(string $column): string
{
return $this->getTable() . '/' . $column;
return $this->getTable() . '/' . $this->guessFileColumn($column);
}

public function getFileUrl(string $column): ?string
Expand Down Expand Up @@ -143,16 +151,72 @@ protected function ensureModelIsPersisted(): void
}
}

protected function guessFileColumn(string $column): string
{
if (
$this->usesTrait(UnderscoreTranslatable::class) &&
$translatedColumnName = $this->guessUnderscoreTranslatableColumn($column)
) {
return $translatedColumnName;
}

return $column;
}

protected function guessFileNameColumn(string $column): string
{
if (
$this->usesTrait(UnderscoreTranslatable::class) &&
$translatedColumnName = $this->guessUnderscoreTranslatableColumn($column, 'filename')
) {
return $translatedColumnName;
}

return "{$column}_filename";
}

protected function guessFileMimeColumn(string $column): string
{
if (
$this->usesTrait(UnderscoreTranslatable::class) &&
$translatedColumnName = $this->guessUnderscoreTranslatableColumn($column, 'mime')
) {
return $translatedColumnName;
}

return "{$column}_mime";
}

protected function usesTrait(string $className): bool
{
return in_array($className, class_uses_recursive($this));
}

protected function ensureTraitIsUsed(string $className): void
{
if (! $this->usesTrait($className)) {
throw new BadMethodCallException("The {$className} trait must be used to call this method.");
}
}

protected function guessUnderscoreTranslatableColumn(string $column, ?string $columnSuffix = null): ?string
{
$this->ensureTraitIsUsed(UnderscoreTranslatable::class);

$columnSuffix = $columnSuffix ? "_{$columnSuffix}" : null;

if ($this->isTranslatableAttribute($column)) {
return $this->getTranslatableAttributeName("{$column}{$columnSuffix}");
}

$columnWithoutPossibleLocaleSuffix = Str::beforeLast($column, '_');
if ($this->isTranslatableAttribute($columnWithoutPossibleLocaleSuffix)) {
return $this->getTranslatableAttributeName("{$columnWithoutPossibleLocaleSuffix}{$columnSuffix}");
}

return null;
}

public function usingFileDisk(string $fileDisk): static
{
$this->fileDisk = $fileDisk;
Expand Down
36 changes: 36 additions & 0 deletions tests/Feature/Concerns/HasFilesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,34 @@
use Esign\ModelFiles\Exceptions\ModelNotPersistedException;
use Esign\ModelFiles\Tests\Support\Models\Post;
use Esign\ModelFiles\Tests\TestCase;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Http\File;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;

class HasFilesTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();

Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->boolean('document')->default(false);
$table->string('document_filename')->nullable();
$table->string('document_mime')->nullable();
$table->timestamps();
});
}

protected function tearDown(): void
{
Schema::dropIfExists('posts');

parent::tearDown();
}

/** @test */
public function it_can_check_if_it_has_a_file()
{
Expand Down Expand Up @@ -263,4 +285,18 @@ public function it_can_store_jpeg_as_jpg()
$this->it_can_store_an_uploaded_file_using_the_guessed_extension_instead_of_the_one_provided_in_the_client_name();
$this->it_can_store_a_file_using_the_guessed_extension_instead_of_the_one_provided_in_the_client_name();
}

protected function createPostWithDocument(
bool $document,
?string $documentFilename,
?string $documentMime,
array $attributes = [],
): Post {
return Post::create([
'document' => $document,
'document_filename' => $documentFilename,
'document_mime' => $documentMime,
...$attributes,
]);
}
}
Loading
Loading