Skip to content
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
10 changes: 9 additions & 1 deletion src/Fields/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,15 @@ public function setParent($parent)
{
$this->parent = $parent;

$this->resetBlueprintCache()->resetFieldsCache();
$this->resetFieldsCache();

// The cache survives when the new parent uses the same blueprint. Give the new
// parent copies of the fields, so fields handed out earlier keep their parent.
if ($this->fieldsCache) {
$this->fieldsCache = $this->fieldsCache->newInstance()
->setFields($this->fieldsCache->all()->map(fn ($field) => clone $field))
->setParent($parent);
}

return $this;
}
Expand Down
34 changes: 34 additions & 0 deletions tests/Data/Entries/EntryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use BadMethodCallException;
use Facades\Statamic\Fields\BlueprintRepository;
use Facades\Statamic\Fields\FieldRepository;
use Facades\Statamic\Stache\Repositories\CollectionTreeRepository;
use Facades\Tests\Factories\EntryFactory;
use Illuminate\Contracts\Support\Arrayable;
Expand Down Expand Up @@ -32,6 +33,7 @@
use Statamic\Facades;
use Statamic\Facades\Blink;
use Statamic\Fields\Blueprint;
use Statamic\Fields\Field;
use Statamic\Fields\Fieldtype;
use Statamic\Fields\Value;
use Statamic\Sites\Site;
Expand Down Expand Up @@ -1273,6 +1275,38 @@ public function it_gets_and_sets_the_published_state()
$this->assertFalse($entry->published());
}

#[Test]
public function entries_with_the_same_blueprint_resolve_its_fields_once()
{
$finds = 0;
FieldRepository::shouldReceive('find')
->with('fieldset_one.field_one')
->andReturnUsing(function () use (&$finds) {
$finds++;

return new Field('field_one', ['type' => 'text']);
});

BlueprintRepository::shouldReceive('in')->with('collections/blog')->andReturn(collect([
'article' => (new Blueprint)->setHandle('article')->setContents([
'fields' => [['handle' => 'one', 'field' => 'fieldset_one.field_one']],
]),
]));
Collection::make('blog')->dated(true)->save();

// Setting the date reads the blueprint's date field, as it happens for every entry loaded from storage.
$makeEntry = fn ($i) => (new Entry)->id("entry-{$i}")->collection('blog')->blueprint('article')->date("2024-01-0{$i}");

$this->assertSame($entry = $makeEntry(1), $entry->blueprint()->field('one')->parent());
$findsForOneBuild = $finds;

foreach (range(2, 5) as $i) {
$this->assertSame($entry = $makeEntry($i), $entry->blueprint()->field('one')->parent());
}

$this->assertSame($findsForOneBuild, $finds);
}

#[Test]
public function it_gets_the_blueprint_when_defined_on_itself()
{
Expand Down
34 changes: 34 additions & 0 deletions tests/Feature/Entries/EntryRevisionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Statamic\Events\EntryDeleted;
use Statamic\Events\EntryDeleting;
Expand Down Expand Up @@ -326,6 +327,39 @@ public function it_unpublishes_an_entry()
$this->assertEquals('unpublish', $revision->action());
}

#[Test]
#[DataProvider('workingCopyActionsProvider')]
public function blueprint_fields_point_to_the_new_entry_after_publishing_or_unpublishing_a_working_copy($method)
{
$this->setTestBlueprint('test', ['foo' => ['type' => 'text']]);

$entry = EntryFactory::id('1')
->slug('test')
->collection('blog')
->published($method === 'unpublishWorkingCopy')
->date('2010-12-25')
->data(['blueprint' => 'test', 'title' => 'Title', 'foo' => 'bar'])
->create();

$entry->makeWorkingCopy()->save();

$this->assertSame($entry, $entry->blueprint()->setParent($entry)->field('foo')->parent());

$published = $entry->{$method}();

$this->assertNotSame($entry, $published);
$this->assertSame($published, $published->blueprint()->field('foo')->parent());
$this->assertSame($published, $published->blueprint()->parent());
}

public static function workingCopyActionsProvider()
{
return [
'publish' => ['publishWorkingCopy'],
'unpublish' => ['unpublishWorkingCopy'],
];
}

#[Test]
public function it_denies_creating_a_revision_without_permission_to_edit_entry()
{
Expand Down
50 changes: 50 additions & 0 deletions tests/Fields/BlueprintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,56 @@ public function it_can_add_fields_multiple_times()

}

#[Test]
public function it_keeps_the_fields_when_the_parent_changes_to_one_with_the_same_blueprint()
{
$finds = 0;
FieldRepository::shouldReceive('find')
->with('fieldset_one.field_one')
->andReturnUsing(function () use (&$finds) {
$finds++;

return new Field('field_one', ['type' => 'text']);
});

$blueprint = (new Blueprint)
->setNamespace('collections/collection_one')
->setHandle('blueprint_one')
->setContents(['fields' => [['handle' => 'one', 'field' => 'fieldset_one.field_one']]]);

$collection = tap(StatamicCollection::make('collection_one'))->save();
$entryA = (new Entry)->collection($collection)->blueprint('blueprint_one');
$entryB = (new Entry)->collection($collection)->blueprint('blueprint_one');

$this->assertSame($entryA, $blueprint->setParent($entryA)->field('one')->parent());
$findsForOneBuild = $finds;

foreach ([$entryB, $entryA, $entryB] as $entry) {
$this->assertSame($entry, $blueprint->setParent($entry)->field('one')->parent());
}

$this->assertSame($findsForOneBuild, $finds);
}

#[Test]
public function fields_keep_their_parent_when_the_blueprint_moves_to_another_parent()
{
$blueprint = (new Blueprint)
->setNamespace('collections/collection_one')
->setHandle('blueprint_one')
->setContents(['fields' => [['handle' => 'one', 'field' => ['type' => 'text']]]]);

$collection = tap(StatamicCollection::make('collection_one'))->save();
$entryA = (new Entry)->collection($collection)->blueprint('blueprint_one');
$entryB = (new Entry)->collection($collection)->blueprint('blueprint_one');

$fieldA = $blueprint->setParent($entryA)->field('one');
$fieldB = $blueprint->setParent($entryB)->field('one');

$this->assertSame($entryA, $fieldA->parent());
$this->assertSame($entryB, $fieldB->parent());
}

#[Test]
public function it_ensures_a_field_has_config()
{
Expand Down
Loading