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

[5.x] Ability to have a custom Entry class per collection #11203

Open
wants to merge 16 commits into
base: 5.x
Choose a base branch
from
8 changes: 8 additions & 0 deletions src/Entries/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class Collection implements Arrayable, ArrayAccess, AugmentableContract, Contrac
protected $autosave;
protected $withEvents = true;

protected $class;

public function __construct()
{
$this->cascade = collect();
Expand Down Expand Up @@ -115,6 +117,11 @@ public function requiresSlugs($require = null)
return $this->fluentlyGetOrSet('requiresSlugs')->args(func_get_args());
}

public function class($class = null)
{
return $this->fluentlyGetOrSet('class')->args(func_get_args());
}

public function titleFormats($formats = null)
{
return $this
Expand Down Expand Up @@ -569,6 +576,7 @@ public function fileData()
'revisions' => $this->revisions,
'title_format' => $this->titleFormats,
'autosave' => $this->autosave,
'class' => $this->class,
];

$array = Arr::except($formerlyToArray, [
Expand Down
33 changes: 31 additions & 2 deletions src/Entries/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,38 @@ public function collection($collection = null)
}

$this->computedCallbackCache = null;
$this->collection = $collection instanceof \Statamic\Contracts\Entries\Collection ? $collection->handle() : $collection;

return $this;
if ($collection instanceof \Statamic\Contracts\Entries\Collection) {
$this->collection = $collection->handle();
$customClass = $collection->class();
} else {
$this->collection = $collection;
$customClass = Collection::findByHandle($this->collection)->class();
}

if (is_null($customClass)) {
return $this;
}

if ($this instanceof $customClass) {
return $this;
}

$entry = app($customClass)
->blueprint($this->blueprint())
->collection($this->collection())
->data($this->data())
->id($this->id())
->origin($this->origin())
->locale($this->site())
->published($this->published())
->slug($this->slug());

if ($this->hasDate()) {
$entry->date($this->date());
}

return $entry;
}

public function blueprint($blueprint = null)
Expand Down
3 changes: 2 additions & 1 deletion src/Stache/Stores/CollectionsStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ public function makeItemFromFile($path, $contents)
->taxonomies(Arr::get($data, 'taxonomies'))
->propagate(Arr::get($data, 'propagate'))
->previewTargets($this->normalizePreviewTargets(Arr::get($data, 'preview_targets', [])))
->autosaveInterval(Arr::get($data, 'autosave'));
->autosaveInterval(Arr::get($data, 'autosave'))
->class(Arr::get($data, 'class'));

if ($dateBehavior = Arr::get($data, 'date_behavior')) {
$collection
Expand Down
21 changes: 19 additions & 2 deletions tests/Data/Entries/EntryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1253,11 +1253,12 @@ public function it_gets_the_default_collection_blueprint_when_undefined()
#[Test]
public function the_blueprint_is_blinked_when_getting_and_flushed_when_setting()
{
$entry = (new Entry)->collection('blog');
$collection = Mockery::mock(Collection::make('blog'));
Collection::shouldReceive('findByHandle')->with('blog')->andReturn($collection);

$entry = (new Entry)->collection('blog');
$collection->shouldReceive('entryBlueprint')->with(null, $entry)->once()->andReturn('the old blueprint');
$collection->shouldReceive('entryBlueprint')->with('new', $entry)->once()->andReturn('the new blueprint');
Collection::shouldReceive('findByHandle')->with('blog')->andReturn($collection);

$this->assertEquals('the old blueprint', $entry->blueprint());
$this->assertEquals('the old blueprint', $entry->blueprint());
Expand Down Expand Up @@ -2572,4 +2573,20 @@ public function initially_saved_entry_gets_put_into_events()
['7', '7'],
], $events->map(fn ($event) => [$event->entry->id(), $event->initiator->id()])->all());
}

#[Test]
public function creates_custom_entry_class()
{
$collection = tap(Collection::make('custom')->class(CustomEntry::class))->save();

$one = Facades\Entry::make()->slug('one')->collection($collection);
$two = Facades\Entry::make()->collection($collection)->slug('two');

$this->assertInstanceOf(CustomEntry::class, $one);
$this->assertInstanceOf(CustomEntry::class, $two);
}
}

class CustomEntry extends Entry
{
}
5 changes: 4 additions & 1 deletion tests/Fields/BlueprintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Statamic\Events\BlueprintSaved;
use Statamic\Events\BlueprintSaving;
use Statamic\Facades;
use Statamic\Facades\Collection as StatamicCollection;
use Statamic\Facades\Fieldset as FieldsetRepository;
use Statamic\Fields\Blueprint;
use Statamic\Fields\Field;
Expand All @@ -30,6 +31,8 @@

class BlueprintTest extends TestCase
{
use \Tests\PreventSavingStacheItemsToDisk;

#[Test]
public function it_gets_the_handle()
{
Expand Down Expand Up @@ -817,7 +820,7 @@ public function it_can_add_fields_multiple_times()
->setHandle('blueprint_one');

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

$blueprint->setParent($entry);
Expand Down
2 changes: 1 addition & 1 deletion tests/Stache/FeatureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function setUp(): void
#[Test]
public function it_gets_all_collections()
{
$this->assertEquals(4, Collection::all()->count());
$this->assertEquals(5, Collection::all()->count());
}

#[Test]
Expand Down
6 changes: 3 additions & 3 deletions tests/Stache/Repositories/CollectionRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ public function it_gets_all_collections()
$collections = $this->repo->all();

$this->assertInstanceOf(IlluminateCollection::class, $collections);
$this->assertCount(4, $collections);
$this->assertCount(5, $collections);
$this->assertEveryItemIsInstanceOf(Collection::class, $collections);

$ordered = $collections->sortBy->handle()->values();
$this->assertEquals(['alphabetical', 'blog', 'numeric', 'pages'], $ordered->map->handle()->all());
$this->assertEquals(['Alphabetical', 'Blog', 'Numeric', 'Pages'], $ordered->map->title()->all());
$this->assertEquals(['alphabetical', 'blog', 'custom_class', 'numeric', 'pages'], $ordered->map->handle()->all());
$this->assertEquals(['Alphabetical', 'Blog', 'Custom Class', 'Numeric', 'Pages'], $ordered->map->title()->all());
}

#[Test]
Expand Down
18 changes: 18 additions & 0 deletions tests/Stache/Repositories/EntryRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,22 @@ public function it_can_delete()
$this->assertNull($item = $this->repo->find('test-blog-entry'));
$this->assertFileDoesNotExist($path);
}

#[Test]
public function it_gets_custom_entry_class()
{
$temp = EntryAPI::make()
->id('custom')
->collection(Collection::findByHandle('custom_class'))
->slug('custom');

$this->repo->save($temp);
$entry = $this->repo->find('custom');

$this->assertInstanceOf(CustomEntry::class, $entry);
}
}

class CustomEntry extends \Statamic\Entries\Entry
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Custom Class
route: 'custom-class/{slug}'
class: Tests\Stache\Repositories\CustomEntry
Loading