Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4f21e54

Browse files
committed
Entities: Moved entity description/covers to own non-model classes
Added back some interfaces.
1 parent 06ec914 commit 4f21e54

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+376
-156
lines changed

app/Entities/Controllers/BookApiController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ protected function forJsonDisplay(Book $book): Book
124124

125125
$book->load(['tags']);
126126
$book->makeVisible(['cover', 'description_html'])
127-
->setAttribute('description_html', $book->contents()->getDescriptionHtml())
128-
->setAttribute('cover', $book->contents()->cover);
127+
->setAttribute('description_html', $book->description()->getHtml())
128+
->setAttribute('cover', $book->cover()->getImage());
129129

130130
return $book;
131131
}

app/Entities/Controllers/BookshelfApiController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ protected function forJsonDisplay(Bookshelf $shelf): Bookshelf
118118

119119
$shelf->load(['tags']);
120120
$shelf->makeVisible(['cover', 'description_html'])
121-
->setAttribute('description_html', $shelf->contents()->getDescriptionHtml())
122-
->setAttribute('cover', $shelf->contents()->cover);
121+
->setAttribute('description_html', $shelf->description()->getHtml())
122+
->setAttribute('cover', $shelf->cover()->getImage());
123123

124124
return $shelf;
125125
}

app/Entities/Controllers/ChapterApiController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ protected function forJsonDisplay(Chapter $chapter): Chapter
144144

145145
$chapter->load(['tags']);
146146
$chapter->makeVisible('description_html');
147-
$chapter->setAttribute('description_html', $chapter->contents()->getDescriptionHtml());
147+
$chapter->setAttribute('description_html', $chapter->description()->getHtml());
148148

149149
/** @var Book $book */
150150
$book = $chapter->book()->first();

app/Entities/Models/Book.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22

33
namespace BookStack\Entities\Models;
44

5+
use BookStack\Entities\Tools\EntityCover;
56
use BookStack\Sorting\SortRule;
67
use BookStack\Uploads\Image;
78
use Illuminate\Database\Eloquent\Factories\HasFactory;
89
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
910
use Illuminate\Database\Eloquent\Relations\HasMany;
10-
use Illuminate\Database\Eloquent\Relations\HasOne;
1111
use Illuminate\Support\Collection;
1212

1313
/**
1414
* Class Book.
1515
*
1616
* @property string $description
17+
* @property string $description_html
1718
* @property int $image_id
1819
* @property ?int $default_template_id
1920
* @property ?int $sort_rule_id
@@ -25,14 +26,14 @@
2526
* @property ?Page $defaultTemplate
2627
* @property ?SortRule $sortRule
2728
*/
28-
class Book extends Entity
29+
class Book extends Entity implements DescriptionInterface, CoverInterface
2930
{
3031
use HasFactory;
3132
use ContainerTrait;
3233

3334
public float $searchFactor = 1.2;
3435

35-
protected $hidden = ['pivot', 'image_id', 'deleted_at', 'description_html'];
36+
protected $hidden = ['pivot', 'deleted_at'];
3637

3738
/**
3839
* Get the url for this book.
@@ -44,12 +45,18 @@ public function getUrl(string $path = ''): string
4445

4546
/**
4647
* Returns a book cover image URL or a default URL if no cover image set.
48+
* TODO - Delete
4749
*/
4850
public function getCover(int $width = 440, int $height = 250): string
4951
{
5052
return $this->contents()->getCoverUrl($width, $height);
5153
}
5254

55+
public function cover(): EntityCover
56+
{
57+
return new EntityCover($this);
58+
}
59+
5360
/**
5461
* Get all pages within this book.
5562
* @return HasMany<Page, $this>

app/Entities/Models/Bookshelf.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33
namespace BookStack\Entities\Models;
44

5+
use BookStack\Entities\Tools\EntityCover;
56
use Illuminate\Database\Eloquent\Factories\HasFactory;
67
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
78

8-
class Bookshelf extends Entity
9+
/**
10+
* @property string $description
11+
* @property string $description_html
12+
*/
13+
class Bookshelf extends Entity implements DescriptionInterface, CoverInterface
914
{
1015
use HasFactory;
1116
use ContainerTrait;
@@ -61,4 +66,9 @@ public function appendBook(Book $book): void
6166
$maxOrder = $this->books()->max('order');
6267
$this->books()->attach($book->id, ['order' => $maxOrder + 1]);
6368
}
69+
70+
public function cover(): EntityCover
71+
{
72+
return new EntityCover($this);
73+
}
6474
}

app/Entities/Models/Chapter.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
* @property Collection<Page> $pages
1111
* @property ?int $default_template_id
1212
* @property ?Page $defaultTemplate
13+
* @property string $description
14+
* @property string $description_html
1315
*/
14-
class Chapter extends BookChild
16+
class Chapter extends BookChild implements DescriptionInterface
1517
{
1618
use HasFactory;
1719
use ContainerTrait;

app/Entities/Models/ContainerTrait.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22

33
namespace BookStack\Entities\Models;
44

5+
use BookStack\Entities\Tools\EntityHtmlDescription;
56
use Illuminate\Database\Eloquent\Relations\HasOne;
67

78
/**
89
* @mixin Entity
910
*/
1011
trait ContainerTrait
1112
{
13+
public function description(): EntityHtmlDescription
14+
{
15+
return new EntityHtmlDescription($this);
16+
}
17+
1218
/**
1319
* @return HasOne<EntityContainerContents, $this>
1420
*/
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace BookStack\Entities\Models;
4+
5+
use BookStack\Entities\Tools\EntityCover;
6+
7+
interface CoverInterface
8+
{
9+
public function cover(): EntityCover;
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace BookStack\Entities\Models;
4+
5+
use BookStack\Entities\Tools\EntityHtmlDescription;
6+
7+
interface DescriptionInterface
8+
{
9+
public function description(): EntityHtmlDescription;
10+
}

app/Entities/Models/Entity.php

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,35 @@ abstract class Entity extends Model implements
104104
'owned_by',
105105
];
106106

107-
public function newFromBuilder($attributes = [], $connection = null): static
107+
// TODO - To Remove, reduce contents/relatedData to just one of them.
108+
// TODO - Update/remove existing usages of contents/relatedData
109+
// TODO - Review usages of query-time update or mass insert of entity model data since those will still need to consider the multi-table layout.
110+
111+
/**
112+
* Override the save method to also save the contents for convenience.
113+
*/
114+
public function save(array $options = []): bool
108115
{
109-
$entityFields = array_intersect_key($attributes, array_flip(static::$commonFields));
110-
$extraFields = array_diff_key($attributes, $entityFields);
116+
$contents = $this->relatedData()->firstOrNew();
117+
$contentFields = $this->getContentsAttributes();
111118

112-
$instance = parent::newFromBuilder($entityFields, $connection);
113-
$data = $instance->relatedData()->newModelInstance()->newFromBuilder($extraFields, $connection);
119+
foreach ($contentFields as $key => $value) {
120+
$contents->setAttribute($key, $value);
121+
unset($this->attributes[$key]);
122+
}
114123

115-
$instance->setRelation('contents', $data);
124+
$result = parent::save($options);
125+
$contentsResult = true;
116126

117-
return $instance;
118-
}
127+
if ($result && $contents->isDirty()) {
128+
$contentsResult = $contents->save();
129+
$this->touch();
130+
}
119131

120-
// TODO - Move attribute usage to `->contents()->attr` calls
132+
$this->forceFill($contentFields);
133+
134+
return $result && $contentsResult;
135+
}
121136

122137
/**
123138
* Check if this item is a container item.
@@ -187,7 +202,7 @@ public function matchesOrContains(self $entity): bool
187202
}
188203

189204
if ($entity instanceof Page && $this instanceof Chapter) {
190-
return $entity->contents()->chapter_id === $this->id;
205+
return $entity->chapter_id === $this->id;
191206
}
192207

193208
return false;
@@ -438,19 +453,36 @@ public function logDescriptor(): string
438453
abstract public function relatedData(): HasOne;
439454

440455
/**
441-
* Get the contents of this entity.
456+
* Get the attributes that are intended for the related contents model.
457+
* @return array<string, mixed>
442458
*/
443-
public function contents(): EntityContainerContents|EntityPageContents|null
459+
protected function getContentsAttributes(): array
444460
{
445-
if ($this->relationLoaded('contents')) {
446-
return $this->getRelation('contents');
447-
}
461+
$contentFields = [];
448462

449-
$relatedData = $this->relatedData()->first();
450-
if ($relatedData) {
451-
return $relatedData;
463+
foreach ($this->attributes as $key => $value) {
464+
if (!in_array($key, static::$commonFields)) {
465+
$contentFields[$key] = $value;
466+
}
452467
}
453468

454-
return null;
469+
return $contentFields;
470+
}
471+
472+
/**
473+
* Get the contents model of this entity.
474+
* Should only really be used if accessing the methods of the contents model
475+
* since the properties would already be part of the fetched entity model.
476+
*/
477+
public function contents(): EntityContainerContents|EntityPageContents
478+
{
479+
$contentsData = $this->getContentsAttributes();
480+
481+
/**
482+
* @var EntityContainerContents|EntityPageContents $instance
483+
*/
484+
$instance = $this->relatedData()->newModelInstance()->newFromBuilder($contentsData, $this->getConnection());
485+
486+
return $instance;
455487
}
456488
}

0 commit comments

Comments
 (0)