|
34 | 34 |
|
35 | 35 | /**
|
36 | 36 | * Class Entity
|
37 |
| - * The base class for book-like items such as pages, chapters & books. |
| 37 | + * The base class for book-like items such as pages, chapters and books. |
38 | 38 | * This is not a database model in itself but extended.
|
39 | 39 | *
|
40 | 40 | * @property int $id
|
|
49 | 49 | * @property int $owned_by
|
50 | 50 | * @property Collection $tags
|
51 | 51 | *
|
52 |
| - * @property ?EntityContainerData $containerData |
53 |
| - * |
54 | 52 | * @method static Entity|Builder visible()
|
55 | 53 | * @method static Builder withLastView()
|
56 | 54 | * @method static Builder withViewCount()
|
@@ -87,27 +85,48 @@ abstract class Entity extends Model implements
|
87 | 85 | protected $table = 'entities';
|
88 | 86 |
|
89 | 87 | /**
|
90 |
| - * Set global scopes to limit queries down to just the right type of entity. |
| 88 | + * Set a custom query builder for entities. |
91 | 89 | */
|
92 |
| - protected static function booted(): void |
93 |
| - { |
94 |
| - static::addGlobalScope('entity', new EntityScope()); |
95 |
| - } |
| 90 | + protected static string $builder = EntityQueryBuilder::class; |
| 91 | + |
| 92 | + protected static array $commonFields = [ |
| 93 | + 'id', |
| 94 | + 'type', |
| 95 | + 'name', |
| 96 | + 'slug', |
| 97 | + 'book_id', |
| 98 | + 'priority', |
| 99 | + 'created_at', |
| 100 | + 'updated_at', |
| 101 | + 'deleted_at', |
| 102 | + 'created_by', |
| 103 | + 'updated_by', |
| 104 | + 'owned_by', |
| 105 | + ]; |
96 | 106 |
|
97 |
| - public function shouldHaveContainerData(): bool |
| 107 | + public function newFromBuilder($attributes = [], $connection = null): static |
98 | 108 | {
|
99 |
| - return $this instanceof Bookshelf || |
100 |
| - $this instanceof Book || |
101 |
| - $this instanceof Chapter; |
| 109 | + $entityFields = array_intersect_key($attributes, array_flip(static::$commonFields)); |
| 110 | + $extraFields = array_diff_key($attributes, $entityFields); |
| 111 | + |
| 112 | + $instance = parent::newFromBuilder($entityFields, $connection); |
| 113 | + $data = $instance->relatedData()->newModelInstance()->newFromBuilder($extraFields, $connection); |
| 114 | + |
| 115 | + $instance->setRelation('contents', $data); |
| 116 | + |
| 117 | + return $instance; |
102 | 118 | }
|
103 | 119 |
|
| 120 | + // TODO - Move attribute usage to `->contents()->attr` calls |
| 121 | + |
104 | 122 | /**
|
105 |
| - * Get the container-specific data for this item. |
| 123 | + * Check if this item is a container item. |
106 | 124 | */
|
107 |
| - public function containerData(): HasOne |
| 125 | + public function isContainer(): bool |
108 | 126 | {
|
109 |
| - return $this->hasOne(EntityContainerData::class, 'id', 'entity_id') |
110 |
| - ->where('entity_type', '=', $this->getMorphClass()); |
| 127 | + return $this instanceof Bookshelf || |
| 128 | + $this instanceof Book || |
| 129 | + $this instanceof Chapter; |
111 | 130 | }
|
112 | 131 |
|
113 | 132 | /**
|
@@ -168,7 +187,7 @@ public function matchesOrContains(self $entity): bool
|
168 | 187 | }
|
169 | 188 |
|
170 | 189 | if ($entity instanceof Page && $this instanceof Chapter) {
|
171 |
| - return $entity->chapter_id === $this->id; |
| 190 | + return $entity->contents()->chapter_id === $this->id; |
172 | 191 | }
|
173 | 192 |
|
174 | 193 | return false;
|
@@ -412,4 +431,26 @@ public function logDescriptor(): string
|
412 | 431 | {
|
413 | 432 | return "({$this->id}) {$this->name}";
|
414 | 433 | }
|
| 434 | + |
| 435 | + /** |
| 436 | + * @return HasOne<EntityContainerContents|EntityPageContents, $this> |
| 437 | + */ |
| 438 | + abstract public function relatedData(): HasOne; |
| 439 | + |
| 440 | + /** |
| 441 | + * Get the contents of this entity. |
| 442 | + */ |
| 443 | + public function contents(): EntityContainerContents|EntityPageContents|null |
| 444 | + { |
| 445 | + if ($this->relationLoaded('contents')) { |
| 446 | + return $this->getRelation('contents'); |
| 447 | + } |
| 448 | + |
| 449 | + $relatedData = $this->relatedData()->first(); |
| 450 | + if ($relatedData) { |
| 451 | + return $relatedData; |
| 452 | + } |
| 453 | + |
| 454 | + return null; |
| 455 | + } |
415 | 456 | }
|
0 commit comments