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 asset reference updating. #149

Merged
merged 16 commits into from
Sep 26, 2022
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
82 changes: 82 additions & 0 deletions src/Listeners/UpdateResponsiveReferences.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Spatie\ResponsiveImages\Listeners;

use Illuminate\Contracts\Queue\ShouldQueue;
use Spatie\ResponsiveImages\ResponsiveReferenceUpdater;
use Statamic\Events\AssetDeleted;
use Statamic\Events\AssetSaved;
use Statamic\Listeners\Concerns\GetsItemsContainingData;

class UpdateResponsiveReferences implements ShouldQueue
{
use GetsItemsContainingData;

/**
* @param $events
* @return void
*/
public function subscribe($events)
{
if (config('statamic.system.update_references') === false) {
return;
}

$events->listen(AssetSaved::class, [self::class, 'handleSaved']);
$events->listen(AssetDeleted::class, [self::class, 'handleDeleted']);
}

/**
* Handle asset saved event.
*
* @param AssetSaved $event
*/
public function handleSaved(AssetSaved $event)
{
$asset = $event->asset;

$container = $asset->container()->handle();
$originalPath = $asset->getOriginal('path');
$newPath = $asset->path();

$this->replaceReferences($container, $originalPath, $newPath);
}

/**
* Handle asset deleted event.
*
* @param AssetDeleted $event
* @return void
*/
public function handleDeleted(AssetDeleted $event)
{
$asset = $event->asset;

$container = $asset->container()->handle();
$originalPath = $asset->getOriginal('path');
$newPath = null;

$this->replaceReferences($container, $originalPath, $newPath);
}

/**
* @param $container
* @param $originalPath
* @param $newPath
* @return void
*/
protected function replaceReferences($container, $originalPath, $newPath)
{
if (!$originalPath || $originalPath === $newPath) {
return;
}

$newValue = $newPath ? "{$container}::{$newPath}" : null;

$this->getItemsContainingData()->each(function ($item) use ($container, $originalPath, $newValue) {
ResponsiveReferenceUpdater::item($item)
->filterByContainer($container)
->updateReferences($container . '::' . $originalPath, $newValue);
});
}
}
116 changes: 116 additions & 0 deletions src/ResponsiveReferenceUpdater.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

namespace Spatie\ResponsiveImages;

use Statamic\Assets\AssetReferenceUpdater;
use Statamic\Support\Arr;

class ResponsiveReferenceUpdater extends AssetReferenceUpdater
{
/**
* Recursively update fields.
*
* @param \Illuminate\Support\Collection $fields
* @param null|string $dottedPrefix
*/
protected function recursivelyUpdateFields($fields, $dottedPrefix = null)
{
$this
->updateResponsiveFieldValues($fields, $dottedPrefix)
->updateNestedFieldValues($fields, $dottedPrefix);
}

/**
* Update assets field values.
*
* @param \Illuminate\Support\Collection $fields
* @param null|string $dottedPrefix
* @return $this
*/
protected function updateResponsiveFieldValues($fields, $dottedPrefix)
{
$fields
->filter(function ($field) {
return $field->type() === 'responsive'
&& $this->getConfiguredAssetsFieldContainer($field) === $this->container;
})
->each(function ($field) use ($dottedPrefix) {
$this->updateResponsiveValue($field, $dottedPrefix);
});

return $this;
}

/**
* Update responsive value on item.
*
* @see AssetReferenceUpdater::updateArrayValue()
* @param \Statamic\Fields\Field $field
* @param null|string $dottedPrefix
*/
protected function updateResponsiveValue($field, $dottedPrefix)
{
$data = $this->item->data()->all();

$dottedKey = $dottedPrefix.$field->handle();

$fieldData = collect(
Arr::get($data, $dottedKey, [])
);

$referencesUpdated = 0;

$fieldData->transform(function ($value, $key) use (&$referencesUpdated) {
if (!str_ends_with($key, 'src')) {
return $value;
}

// In content files, the src value can be either string or array.
// First handle the string value, and then handle the array value.
// Handle asset deletion, return null now for filtering later.
if ($value === $this->originalValue() && $this->isRemovingValue()) {
$referencesUpdated++;
return null;
}

if (is_string($value) && $value === $this->originalValue()) {
$referencesUpdated++;
return $this->newValue();
}

// Handle array value.
if (is_array($value) && in_array($this->originalValue(), $value)) {
$transformedFieldDataArray = array_map(function ($item) use (&$referencesUpdated) {
// Handle asset deletion, return null now for filtering.
if ($item === $this->originalValue() && $this->isRemovingValue()) {
$referencesUpdated++;
return null;
}

if ($item === $this->originalValue()) {
$referencesUpdated++;
return $this->newValue();
}

return $item;
}, $value);

return array_filter($transformedFieldDataArray, fn($item) => $item !== null);
}

return $value;
});

$fieldData = $fieldData->filter(fn($item) => $item !== null);

if ($referencesUpdated === 0) {
return;
}

Arr::set($data, $dottedKey, $fieldData->all());

$this->item->data($data);

$this->updated = true;
}
}
7 changes: 7 additions & 0 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
use Spatie\ResponsiveImages\GraphQL\ResponsiveFieldType as GraphQLResponsiveFieldType;
use Spatie\ResponsiveImages\Jobs\GenerateImageJob;
use Spatie\ResponsiveImages\Listeners\GenerateResponsiveVersions;
use Spatie\ResponsiveImages\Listeners\UpdateResponsiveReferences;
use Spatie\ResponsiveImages\Tags\ResponsiveTag;
use Statamic\Events\AssetUploaded;
use Statamic\Events\AssetSaved;
use Statamic\Facades\GraphQL;
use Statamic\Providers\AddonServiceProvider;

Expand Down Expand Up @@ -40,6 +42,10 @@ class ServiceProvider extends AddonServiceProvider
],
];

protected $subscribe = [
UpdateResponsiveReferences::class,
];

protected $commands = [
GenerateResponsiveVersionsCommand::class,
RegenerateResponsiveVersionsCommand::class,
Expand All @@ -50,6 +56,7 @@ public function boot()
parent::boot();

$this
->bootEvents()
->bootCommands()
->bootAddonViews()
->bootAddonConfig()
Expand Down
Loading