Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions src/Assets/AssetReferenceUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

use Statamic\Data\DataReferenceUpdater;
use Statamic\Facades\AssetContainer;
use Statamic\Fieldtypes\Sets;
use Statamic\Support\Arr;
use Statamic\Support\Str;
use Statamic\Tags\Set;

class AssetReferenceUpdater extends DataReferenceUpdater
{
Expand Down Expand Up @@ -333,4 +336,69 @@ private function updateStatamicUrlsInLinkNodes($field, $dottedPrefix)

$this->updated = true;
}

/**
* Update fields in blueprints and fieldsets.
*
* @return void
*/
protected function updateBlueprintFields()
{
if (
! Sets::previewImageConfig()
|| ! Str::startsWith($this->originalValue, Sets::previewImageConfig()['folder'].'/')
) {
return;
}

$contents = $this->item->contents();

$fieldPaths = $this->findFieldsInBlueprintContents($contents, fieldtypes: ['bard', 'replicator']);

foreach ($fieldPaths as $fieldPath) {
$fieldContents = Arr::get($contents, $fieldPath);

if (! isset($fieldContents['sets'])) {
continue;
}

$fieldContents['sets'] = collect($fieldContents['sets'])
->map(function ($setGroup) {
if (! isset($setGroup['sets'])) {
return $setGroup;
}

$setGroup['sets'] = collect($setGroup['sets'])
->map(function ($set) {
if (isset($set['image'])) {
$fullPath = Sets::previewImageConfig()['folder'].'/'.$set['image'];

if ($fullPath !== $this->originalValue) {
return $set;
}

if (Str::startsWith($this->newValue, Sets::previewImageConfig()['folder'].'/')) {
$set['image'] = Str::after($this->newValue, Sets::previewImageConfig()['folder'].'/');
} else {
unset($set['image']);
}

$this->updated = true;
}

return $set;
})
->all();

return $setGroup;
})
->all();

Arr::set($contents, $fieldPath, $fieldContents);
}

if ($this->updated) {
$this->item->setContents($contents);
}
}
}
41 changes: 40 additions & 1 deletion src/Data/DataReferenceUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace Statamic\Data;

use Statamic\Fields\Blueprint;
use Statamic\Fields\Fields;
use Statamic\Fields\Fieldset;
use Statamic\Git\Subscriber as GitSubscriber;
use Statamic\Support\Arr;

Expand Down Expand Up @@ -60,7 +62,11 @@ public function updateReferences($originalValue, $newValue)
$this->originalValue = $originalValue;
$this->newValue = $newValue;

$this->recursivelyUpdateFields($this->getTopLevelFields());
if ($this->item instanceof Blueprint || $this->item instanceof Fieldset) {
$this->updateBlueprintFields();
} else {
$this->recursivelyUpdateFields($this->getTopLevelFields());
}

if ($this->updated) {
$this->saveItem();
Expand Down Expand Up @@ -317,6 +323,39 @@ protected function updateArrayValue($field, $dottedPrefix)
$this->updated = true;
}

/**
* Update fields in blueprints and fieldsets.
*
* @return void
*/
abstract protected function updateBlueprintFields();

/**
* Finds fields of a given type in the contents of a blueprint.
* Returns dot-notation paths to the fields.
*
* @param array $array
* @param array $fieldtypes
* @param string|null $dottedPrefix
* @param array $fieldPaths
* @return array
*/
protected function findFieldsInBlueprintContents($array, $fieldtypes, $dottedPrefix = '', &$fieldPaths = [])
{
foreach ($array as $key => $value) {
if (is_array($value)) {
$fieldPath = $dottedPrefix ? "$dottedPrefix.$key" : $key;
$this->findFieldsInBlueprintContents($value, $fieldtypes, $fieldPath, $fieldPaths);
}

if (is_string($value) && $key === 'type' && in_array($value, $fieldtypes)) {
$fieldPaths[] = $dottedPrefix;
}
}

return $fieldPaths;
}

/**
* Save item without triggering individual git commits, as these should be batched into one larger commit.
*/
Expand Down
15 changes: 14 additions & 1 deletion src/Fields/BlueprintRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Exception;
use Illuminate\Support\Collection;
use Statamic\Exceptions\BlueprintNotFoundException;
use Statamic\Facades;
use Statamic\Facades\Blink;
use Statamic\Facades\File;
use Statamic\Facades\Path;
Expand All @@ -23,6 +24,18 @@ class BlueprintRepository
protected $fallbacks = [];
protected $additionalNamespaces = [];

public function all()
{
$namespaces = [
...Facades\Collection::all()->map(fn ($collection) => "collections/{$collection->handle()}")->all(),
...Facades\Taxonomy::all()->map(fn ($taxonomy) => "taxonomies/{$taxonomy->handle()}")->all(),
'navigation', 'assets', 'globals', 'forms',
...$this->getAdditionalNamespaces()->keys()->all(),
];

return collect($namespaces)->flatMap(fn ($namespace) => $this->in($namespace)->values());
}

public function setDirectories(string|array $directories)
{
if (is_string($directories)) {
Expand Down Expand Up @@ -334,7 +347,7 @@ protected function makeBlueprintFromFile($path, $namespace = null)
->setInitialPath($path)
->setNamespace($namespace ?? null)
->setContents($contents);
});
})->setParent(null);
}

protected function getNamespaceAndHandle($blueprint)
Expand Down
4 changes: 4 additions & 0 deletions src/Fields/FieldsetRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ public function save(Fieldset $fieldset)
"{$directory}/{$handle}.yaml",
YAML::dump($fieldset->contents())
);

$this->fieldsets[$fieldset->handle()] = $fieldset;
}

public function delete(Fieldset $fieldset)
Expand All @@ -181,6 +183,8 @@ public function delete(Fieldset $fieldset)
}

File::delete($fieldset->path());

unset($this->fieldsets[$fieldset->handle()]);
}

public function reset(Fieldset $fieldset)
Expand Down
22 changes: 22 additions & 0 deletions src/Listeners/UpdateAssetReferences.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Statamic\Events\AssetReplaced;
use Statamic\Events\AssetSaved;
use Statamic\Events\Subscriber;
use Statamic\Facades\Blueprint;
use Statamic\Facades\Fieldset;

class UpdateAssetReferences extends Subscriber implements ShouldQueue
{
Expand Down Expand Up @@ -99,6 +101,26 @@ protected function replaceReferences($asset, $originalPath, $newPath)
}
});

Blueprint::all()
->each(function ($blueprint) use ($originalPath, $newPath, &$hasUpdatedItems) {
$updated = AssetReferenceUpdater::item($blueprint)
->updateReferences($originalPath, $newPath);

if ($updated) {
$hasUpdatedItems = true;
}
});

Fieldset::all()
->each(function ($fieldset) use ($originalPath, $newPath, &$hasUpdatedItems) {
$updated = AssetReferenceUpdater::item($fieldset)
->updateReferences($originalPath, $newPath);

if ($updated) {
$hasUpdatedItems = true;
}
});

if ($hasUpdatedItems) {
AssetReferencesUpdated::dispatch($asset);
}
Expand Down
10 changes: 10 additions & 0 deletions src/Taxonomies/TermReferenceUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,14 @@ protected function newValue()
{
return $this->scope.$this->newValue;
}

/**
* Update fields in blueprints and fieldsets.
*
* @return void
*/
protected function updateBlueprintFields()
{
//
}
}
1 change: 1 addition & 0 deletions tests/Assets/AssetFolderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,7 @@ private function containerWithDisk()
Storage::fake('local');

$container = Facades\AssetContainer::make('test')->disk('local');
Facades\AssetContainer::shouldReceive('find')->with('assets')->andReturn(null);
Facades\AssetContainer::shouldReceive('findByHandle')->with('test')->andReturn($container);
Facades\AssetContainer::shouldReceive('save')->with($container);

Expand Down
3 changes: 3 additions & 0 deletions tests/Assets/AssetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,7 @@ public function it_can_be_moved_to_another_folder_with_a_new_filename()
$disk->put('old/asset.txt', 'The asset contents');
$container = Facades\AssetContainer::make('test')->disk('local');
Facades\AssetContainer::shouldReceive('save')->with($container);
Facades\AssetContainer::shouldReceive('find')->with('assets')->andReturnNull();
Facades\AssetContainer::shouldReceive('findByHandle')->with('test')->andReturn($container);
$asset = $container->makeAsset('old/asset.txt')->data(['foo' => 'bar']);
$asset->save();
Expand Down Expand Up @@ -1202,6 +1203,7 @@ public function it_lowercases_when_moving_to_another_folder_with_a_new_filename(
$disk->put('old/asset.txt', 'The asset contents');
$container = Facades\AssetContainer::make('test')->disk('local');
Facades\AssetContainer::shouldReceive('save')->with($container);
Facades\AssetContainer::shouldReceive('find')->with('assets')->andReturnNull();
Facades\AssetContainer::shouldReceive('findByHandle')->with('test')->andReturn($container);
$asset = $container->makeAsset('old/asset.txt');
$asset->save();
Expand All @@ -1225,6 +1227,7 @@ public function it_doesnt_lowercase_moved_files_when_configured()
$disk->put('old/asset.txt', 'The asset contents');
$container = Facades\AssetContainer::make('test')->disk('local');
Facades\AssetContainer::shouldReceive('save')->with($container);
Facades\AssetContainer::shouldReceive('find')->with('assets')->andReturnNull();
Facades\AssetContainer::shouldReceive('findByHandle')->with('test')->andReturn($container);
$asset = $container->makeAsset('old/asset.txt');
$asset->save();
Expand Down
39 changes: 39 additions & 0 deletions tests/Fields/BlueprintRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
use Statamic\Fields\Blueprint;
use Statamic\Fields\BlueprintRepository;
use Statamic\Support\FileCollection;
use Tests\PreventSavingStacheItemsToDisk;
use Tests\TestCase;

class BlueprintRepositoryTest extends TestCase
{
use PreventSavingStacheItemsToDisk;

private $repo;

public function setUp(): void
Expand All @@ -26,6 +29,42 @@ public function setUp(): void
Facades\Blueprint::swap($this->repo);
}

#[Test]
public function it_gets_all_blueprints()
{
$this->repo->setDirectories($this->fakeStacheDirectory.'/dev-null/blueprints');

$collection = tap(Facades\Collection::make('test'))->save();
$collection->entryBlueprint()->save();

$taxonomy = tap(Facades\Taxonomy::make('test'))->save();
$taxonomy->termBlueprint()->save();

$nav = tap(Facades\Nav::make('test'))->save();
$nav->blueprint()->save();

$assetContainer = tap(Facades\AssetContainer::make('test'))->save();
$assetContainer->blueprint()->save();

Facades\GlobalSet::make('test')->save();
$this->repo->make('test')->setNamespace('globals')->save();

$form = tap(Facades\Form::make('test'))->save();
$form->blueprint()->save();

$all = $this->repo->all();

$this->assertEveryItemIsInstanceOf(Blueprint::class, $all);
$this->assertEquals([
'collections.test.test',
'taxonomies.test.test',
'navigation.test',
'assets.test',
'globals.test',
'forms.test',
], $all->map->fullyQualifiedHandle()->all());
}

#[Test]
public function it_gets_a_blueprint()
{
Expand Down
1 change: 1 addition & 0 deletions tests/Git/GitEventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ public function it_batches_asset_references_changes_into_one_commit()
],
]);

BlueprintRepository::shouldReceive('all')->andReturn(collect([$blueprint]));
BlueprintRepository::shouldReceive('in')->with('collections/pages')->andReturn(collect([$blueprint]));

foreach (range(1, 3) as $i) {
Expand Down
Loading