Skip to content

Commit

Permalink
File namer#1784 (#2114)
Browse files Browse the repository at this point in the history
* support a custom file namer for responsive images

* Fix styling

* apply code review suggestions

* let conversions use a new file namer class

* add documentation

* cleanup last conversion file namer parts

* apply code review suggestions

* split up conversion & responsive file namer

* remove get prefix on FileNamer methods

* Update naming-generated-files.md

* Update naming-generated-files.md

Co-authored-by: Nielsvanpach <[email protected]>
Co-authored-by: Freek Van der Herten <[email protected]>
  • Loading branch information
3 people authored Oct 27, 2020
1 parent 9ac9125 commit f2c5a56
Show file tree
Hide file tree
Showing 19 changed files with 243 additions and 145 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ All notable changes to `laravel-medialibrary` will be documented in this file
## 9.0.0 - Unreleased

- names of the generated conversions will now be put in a dedicated `generated_conversions` on media
- adds support for media library pro
- add support for media library pro
- responsive image files can now be named using the `file_namer` key in the `media-library` config file (#2114)

## 8.10.1 - 2020-10-05

Expand Down
1 change: 1 addition & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Because there are many breaking changes an upgrade is not that easy. There are m
## From v8 to v9

- add a column `generated_conversions` to the `media` table. If you are using Media Library Pro you used copy the values you now have in the `generated_conversions` key of the `custom_properties` column to `generated_conversions`
- rename `conversion_file_namer` key in the `media-library` config to `file_namer`. This will support both the conversions and responsive images from now on.

## From v7 to v8

Expand Down
5 changes: 2 additions & 3 deletions config/media-library.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,9 @@
'default_loading_attribute_value' => null,

/*
* This is the class that is responsible for naming conversion files. By default,
* it will use the filename of the original and concatenate the conversion name to it.
* This is the class that is responsible for naming generated files.
*/
'conversion_file_namer' => Spatie\MediaLibrary\Conversions\DefaultConversionFileNamer::class,
'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class,

/*
* The class that contains the strategy for determining a media file's path.
Expand Down
55 changes: 55 additions & 0 deletions docs/advanced-usage/naming-generated-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: Naming generated files
weight: 11
---

### Naming conversion files

By default, all conversion files will be named in this format:

```
{original-file-name-without-extension}-{name-of-the-conversion}.{extension}
```

Should you want to name your conversion file using another format,
then you can specify the class name of your own `FileNamer` in the `file_namer` key
of the `media-library.php` config file.

The only requirements is that your class extends `Spatie\MediaLibrary\Support\FileNamer`.
In your class you should implement 2 methods:
1. `conversionFileName` should return the media file name combined with the conversion name
2. `responsiveFileName` should return the media file name

Here is the implementation of `Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer`

```php
namespace Spatie\MediaLibrary\Support\FileNamer;

use Spatie\MediaLibrary\Conversions\Conversion;

class DefaultFileNamer extends FileNamer
{
public function conversionFileName(string $fileName, Conversion $conversion): string
{
$strippedFileName = pathinfo($fileName, PATHINFO_FILENAME);

return "{$strippedFileName}-{$conversion->getName()}";
}

public function responsiveFileName(string $fileName): string
{
return pathinfo($fileName, PATHINFO_FILENAME);
}
}
```

### Naming responsive image files

By default, all responsive image files will be named in this format:

```
{original-file-name-without-extension}___{name-of-the-conversion}_{width}_{height}.{extension}
```

Just like the conversion file names, you can use another format for naming your files
by using your own `FileNamer` class. It is only possible to prefix the name, because other parts are needed in processing responsive images.
32 changes: 0 additions & 32 deletions docs/converting-images/naming-conversion-files.md

This file was deleted.

5 changes: 2 additions & 3 deletions docs/installation-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,9 @@ return [
'default_loading_attribute_value' => null,

/*
* This is the class that is responsible for naming conversion files. By default,
* it will use the filename of the original and concatenate the conversion name to it.
* This is the class that is responsible for naming generated files.
*/
'conversion_file_namer' => \Spatie\MediaLibrary\Conversions\DefaultConversionFileNamer::class,
'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class,

/*
* The class that contains the strategy for determining a media file's path.
Expand Down
11 changes: 7 additions & 4 deletions src/Conversions/Conversion.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
use BadMethodCallException;
use Spatie\Image\Manipulations;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\MediaLibrary\Support\FileNamer\FileNamer;

/** @mixin \Spatie\Image\Manipulations */
class Conversion
{
protected string $name = '';

protected ConversionFileNamer $conversionFileNamer;
protected FileNamer $fileNamer;

protected float $extractVideoFrameAtSecond = 0;

Expand All @@ -37,7 +38,7 @@ public function __construct(string $name)
->optimize(config('media-library.image_optimizers'))
->format(Manipulations::FORMAT_JPG);

$this->conversionFileNamer = app(config('media-library.conversion_file_namer'));
$this->fileNamer = app(config('media-library.file_namer'));

$this->loadingAttributeValue = config('media-library.default_loading_attribute_value');

Expand Down Expand Up @@ -217,8 +218,10 @@ public function getResultExtension(string $originalFileExtension = ''): string

public function getConversionFile(Media $media): string
{
$fileName = $this->conversionFileNamer->getFileName($this, $media);
$extension = $this->conversionFileNamer->getExtension($this, $media);
$fileName = $this->fileNamer->conversionFileName($media->file_name, $this);

$fileExtension = $this->fileNamer->extensionFromBaseImage($media->file_name);
$extension = $this->getResultExtension($fileExtension) ?: $fileExtension;

return "{$fileName}.{$extension}";
}
Expand Down
17 changes: 0 additions & 17 deletions src/Conversions/ConversionFileNamer.php

This file was deleted.

15 changes: 0 additions & 15 deletions src/Conversions/DefaultConversionFileNamer.php

This file was deleted.

35 changes: 25 additions & 10 deletions src/ResponsiveImages/ResponsiveImageGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\TinyPlaceholderGenerator;
use Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\WidthCalculator;
use Spatie\MediaLibrary\Support\File;
use Spatie\MediaLibrary\Support\FileNamer\FileNamer;
use Spatie\MediaLibrary\Support\ImageFactory;
use Spatie\MediaLibrary\Support\TemporaryDirectory;
use Spatie\TemporaryDirectory\TemporaryDirectory as BaseTemporaryDirectory;
Expand All @@ -25,6 +26,8 @@ class ResponsiveImageGenerator

protected const DEFAULT_CONVERSION_QUALITY = 90;

protected FileNamer $fileNamer;

public function __construct(
Filesystem $filesystem,
WidthCalculator $widthCalculator,
Expand All @@ -35,6 +38,8 @@ public function __construct(
$this->widthCalculator = $widthCalculator;

$this->tinyPlaceholderGenerator = $tinyPlaceholderGenerator;

$this->fileNamer = app(config('media-library.file_namer'));
}

public function generateResponsiveImages(Media $media): void
Expand Down Expand Up @@ -87,11 +92,8 @@ public function generateResponsiveImage(
BaseTemporaryDirectory $temporaryDirectory,
int $conversionQuality = self::DEFAULT_CONVERSION_QUALITY
): void {
$responsiveImagePath = $this->appendToFileName(
$media->file_name,
"___{$conversionName}_{$targetWidth}",
$baseImage
);
$extension = $this->fileNamer->extensionFromBaseImage($baseImage);
$responsiveImagePath = $this->fileNamer->temporaryFileName($media, $extension);

$tempDestination = $temporaryDirectory->path($responsiveImagePath);

Expand All @@ -103,15 +105,22 @@ public function generateResponsiveImage(

$responsiveImageHeight = ImageFactory::load($tempDestination)->getHeight();

$finalImageFileName = $this->appendToFileName($responsiveImagePath, "_{$responsiveImageHeight}");
// Users can customize the name like they want, but we expect the last part in a certain format
$fileName = $this->addPropertiesToFileName(
$responsiveImagePath,
$conversionName,
$targetWidth,
$responsiveImageHeight,
$extension
);

$finalResponsiveImagePath = $temporaryDirectory->path($finalImageFileName);
$responsiveImagePath = $temporaryDirectory->path($fileName);

rename($tempDestination, $finalResponsiveImagePath);
rename($tempDestination, $responsiveImagePath);

$this->filesystem->copyToMediaLibrary($finalResponsiveImagePath, $media, 'responsiveImages');
$this->filesystem->copyToMediaLibrary($responsiveImagePath, $media, 'responsiveImages');

ResponsiveImage::register($media, $finalImageFileName, $conversionName);
ResponsiveImage::register($media, $fileName, $conversionName);
}

public function generateTinyJpg(
Expand Down Expand Up @@ -177,4 +186,10 @@ protected function cleanResponsiveImages(Media $media, string $conversionName =

return $media;
}

protected function addPropertiesToFileName(string $fileName, string $conversionName, int $width, int $height, string $extension): string
{
$fileName = pathinfo($fileName, PATHINFO_FILENAME);
return "{$fileName}___{$conversionName}_{$width}_{$height}.{$extension}";
}
}
20 changes: 20 additions & 0 deletions src/Support/FileNamer/DefaultFileNamer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Spatie\MediaLibrary\Support\FileNamer;

use Spatie\MediaLibrary\Conversions\Conversion;

class DefaultFileNamer extends FileNamer
{
public function conversionFileName(string $fileName, Conversion $conversion): string
{
$strippedFileName = pathinfo($fileName, PATHINFO_FILENAME);

return "{$strippedFileName}-{$conversion->getName()}";
}

public function responsiveFileName(string $fileName): string
{
return pathinfo($fileName, PATHINFO_FILENAME);
}
}
23 changes: 23 additions & 0 deletions src/Support/FileNamer/FileNamer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Spatie\MediaLibrary\Support\FileNamer;

use Spatie\MediaLibrary\Conversions\Conversion;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

abstract class FileNamer
{
abstract public function conversionFileName(string $fileName, Conversion $conversion): string;

abstract public function responsiveFileName(string $fileName): string;

public function temporaryFileName(Media $media, string $extension): string
{
return "{$this->responsiveFileName($media->file_name)}.{$extension}";
}

public function extensionFromBaseImage(string $baseImage): string
{
return pathinfo($baseImage, PATHINFO_EXTENSION);
}
}
14 changes: 8 additions & 6 deletions tests/Conversions/ConversionFileNamerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,27 @@
namespace Spatie\MediaLibrary\Tests\Conversions;

use Spatie\MediaLibrary\Tests\TestCase;
use Spatie\MediaLibrary\Tests\TestSupport\testfiles\TestConversionFileNamer;
use Spatie\MediaLibrary\Tests\TestSupport\TestFileNamer;

class ConversionFileNamerTest extends TestCase
{
public string $fileName = "prefix_test_suffix";

/** @test */
public function it_can_use_a_custom_conversion_file_namer()
public function it_can_use_a_custom_file_namer()
{
config()->set('media-library.conversion_file_namer', TestConversionFileNamer::class);
config()->set("media-library.file_namer", TestFileNamer::class);

$this
->testModelWithConversion
->addMedia($this->getTestJpg())
->toMediaCollection();

$path = $this->testModelWithConversion->refresh()->getFirstMediaPath('default', 'thumb');
$path = $this->testModelWithConversion->refresh()->getFirstMediaPath("default", "thumb");

$this->assertStringEndsWith('test---thumb.jpg', $path);
$this->assertStringEndsWith("{$this->fileName}---thumb.jpg", $path);
$this->assertFileExists($path);

$this->assertEquals('/media/1/conversions/test---thumb.jpg', $this->testModelWithConversion->getFirstMediaUrl('default', 'thumb'));
$this->assertEquals("/media/1/conversions/{$this->fileName}---thumb.jpg", $this->testModelWithConversion->getFirstMediaUrl("default", "thumb"));
}
}
17 changes: 17 additions & 0 deletions tests/ResponsiveImages/ResponsiveImageFileNamerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Spatie\MediaLibrary\Tests\ResponsiveImages;

use Spatie\MediaLibrary\Tests\TestSupport\TestFileNamer;

class ResponsiveImageFileNamerTest extends ResponsiveImageTest
{
public function setUp(): void
{
parent::setUp();

config()->set("media-library.file_namer", TestFileNamer::class);

$this->fileName = "prefix_test_suffix";
}
}
17 changes: 17 additions & 0 deletions tests/ResponsiveImages/ResponsiveImageGeneratorFileNamerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Spatie\MediaLibrary\Tests\ResponsiveImages;

use Spatie\MediaLibrary\Tests\TestSupport\TestFileNamer;

class ResponsiveImageGeneratorFileNamerTest extends ResponsiveImageGeneratorTest
{
public function setUp(): void
{
parent::setUp();

config()->set("media-library.file_namer", TestFileNamer::class);

$this->fileName = "prefix_test_suffix";
}
}
Loading

0 comments on commit f2c5a56

Please sign in to comment.