Skip to content

Commit

Permalink
Fix placeholder generation failing when changing `assets.image_manipu…
Browse files Browse the repository at this point in the history
…lation.cache` value (#174)
  • Loading branch information
ncla authored Oct 16, 2022
1 parent 016ff6e commit 70c853a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 16 deletions.
28 changes: 13 additions & 15 deletions src/Breakpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use League\Flysystem\FileNotFoundException;
use League\Glide\Server;
use Spatie\ResponsiveImages\Jobs\GenerateImageJob;
use Statamic\Contracts\Assets\Asset;
use Statamic\Facades\Blink;
use Statamic\Facades\Glide as GlideManager;
use Statamic\Imaging\ImageGenerator;
use Statamic\Support\Str;

Expand Down Expand Up @@ -251,25 +250,24 @@ private function placeholderSvg(): string
{
return Blink::once("placeholder-{$this->asset->id()}-{$this->ratio}", function () {
$imageGenerator = app(ImageGenerator::class);
$server = app(Server::class);

$path = $imageGenerator->generateByAsset($this->asset, [
$manipulationPath = $imageGenerator->generateByAsset($this->asset, [
'w' => 32,
'h' => round(32 / $this->ratio),
'blur' => 5,
// Arbitrary parameter to change md5 hash for Glide manipulation cache key
// to force Glide to generate new manipulated image if cache setting changes.
// TODO: Remove this line once the issue has been resolved in statamic/cms package
'cache' => Config::get('statamic.assets.image_manipulation.cache', false),
]);

try {
$source = base64_encode($server->getCache()->read($path));
$cache = $server->getCache();
$mimetype = method_exists($cache, 'getMimetype')
? $cache->getMimetype($path)
: $cache->mimeType($path);

$base64Placeholder = "data:{$mimetype};base64,{$source}";
} catch (FileNotFoundException $e) {
return '';
}
/**
* Glide tag has undocumented method for generating data URL that we borrow from
* @see \Statamic\Tags\Glide::generateGlideDataUrl
*/
$cache = GlideManager::cacheDisk();
$assetContentEncoded = base64_encode($cache->read($manipulationPath));
$base64Placeholder = 'data:'.$cache->mimeType($manipulationPath).';base64,'.$assetContentEncoded;

return view('responsive-images::placeholderSvg', [
'width' => 32,
Expand Down
51 changes: 50 additions & 1 deletion tests/Feature/BreakpointTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
namespace Spatie\ResponsiveImages\Tests\Feature;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Spatie\ResponsiveImages\Tests\TestCase;
use Spatie\ResponsiveImages\Breakpoint;
use Statamic\Console\Commands\GlideClear;
use Statamic\Facades\Stache;
use Statamic\Facades\YAML;
use Statamic\Facades\Blink;

class BreakpointTest extends TestCase
{
Expand All @@ -24,7 +28,6 @@ protected function setUp(): void
$file = new UploadedFile($this->getTestJpg(), 'test.jpg');
$path = ltrim('/'.$file->getClientOriginalName(), '/');
$this->asset = $this->assetContainer->makeAsset($path)->upload($file);

Stache::clear();
}

Expand Down Expand Up @@ -128,4 +131,50 @@ public function it_uses_crop_focus_value_from_assets_metadata()
$breakpoint->buildImageJob(100 )->handle()
);
}

/**
* @test
*/
public function it_generates_placeholder_data_url_when_toggling_cache_from_on_to_off()
{
/**
* Clear regular cache and both Glide path cache storages
* @see: https://statamic.dev/image-manipulation#path-cache-store
*/
Config::set('statamic.assets.image_manipulation.cache', false);
$this->artisan(GlideClear::class);
Config::set('statamic.assets.image_manipulation.cache', true);
$this->artisan(GlideClear::class);

// Glide server has already initialized in service container, we clear it so the cache config value gets read.
App::forgetInstance(\League\Glide\Server::class);

$cacheDiskPathBefore = \Statamic\Facades\Glide::cacheDisk()->getConfig()['root'];

// Generate placeholder
$responsive = new Breakpoint($this->asset, 'default', 0, []);
$firstPlaceholder = $responsive->placeholder();

/**
* We use Blink cache for placeholder generation that we need to clear just in case
* @see https://statamic.dev/extending/blink-cache
* @see Breakpoint::placeholderSvg()
*/
Blink::store()->flush();

Config::set('statamic.assets.image_manipulation.cache', false);

// Once again, because we are running in the same session, we need Glide server instance to be forgotten
// so that it uses different Filesystem that depends on the statamic.assets.image_manipulation.cache value
App::forgetInstance(\League\Glide\Server::class);

$cacheDiskPathAfter = \Statamic\Facades\Glide::cacheDisk()->getConfig()['root'];

// Generate placeholder again
$responsive = new Breakpoint($this->asset, 'default', 0, []);
$secondPlaceholder = $responsive->placeholder();

$this->assertEquals($firstPlaceholder, $secondPlaceholder);
$this->assertNotEquals($cacheDiskPathBefore, $cacheDiskPathAfter);
}
}

0 comments on commit 70c853a

Please sign in to comment.