Added reference handling on page actions

Page update/create/restore/clone/delete.
Added a couple of tests to cover a couple of those.
This commit is contained in:
Dan Brown 2022-08-17 17:37:27 +01:00
parent 3290ab3ac9
commit bbe504c559
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
4 changed files with 81 additions and 3 deletions

View File

@ -16,20 +16,23 @@ use BookStack\Exceptions\MoveOperationException;
use BookStack\Exceptions\NotFoundException;
use BookStack\Exceptions\PermissionsException;
use BookStack\Facades\Activity;
use BookStack\References\ReferenceService;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;
class PageRepo
{
protected $baseRepo;
protected BaseRepo $baseRepo;
protected ReferenceService $references;
/**
* PageRepo constructor.
*/
public function __construct(BaseRepo $baseRepo)
public function __construct(BaseRepo $baseRepo, ReferenceService $references)
{
$this->baseRepo = $baseRepo;
$this->references = $references;
}
/**
@ -112,7 +115,7 @@ class PageRepo
public function getParentFromSlugs(string $bookSlug, string $chapterSlug = null): Entity
{
if ($chapterSlug !== null) {
return $chapter = Chapter::visible()->whereSlugs($bookSlug, $chapterSlug)->firstOrFail();
return Chapter::visible()->whereSlugs($bookSlug, $chapterSlug)->firstOrFail();
}
return Book::visible()->where('slug', '=', $bookSlug)->firstOrFail();
@ -170,6 +173,7 @@ class PageRepo
$this->savePageRevision($draft, trans('entities.pages_initial_revision'));
$draft->indexForSearch();
$this->references->updateForPage($draft);
$draft->refresh();
Activity::add(ActivityType::PAGE_CREATE, $draft);
@ -189,6 +193,7 @@ class PageRepo
$this->updateTemplateStatusAndContentFromInput($page, $input);
$this->baseRepo->update($page, $input);
$this->references->updateForPage($page);
// Update with new details
$page->revision_count++;
@ -332,6 +337,7 @@ class PageRepo
$page->refreshSlug();
$page->save();
$page->indexForSearch();
$this->references->updateForPage($page);
$summary = trans('entities.pages_revision_restored_from', ['id' => strval($revisionId), 'summary' => $revision->summary]);
$this->savePageRevision($page, $summary);
@ -430,6 +436,7 @@ class PageRepo
->skip(intval($revisionLimit))
->take(10)
->get(['id']);
if ($revisionsToDelete->count() > 0) {
PageRevision::query()->whereIn('id', $revisionsToDelete->pluck('id'))->delete();
}

View File

@ -376,6 +376,8 @@ class TrashCan
$entity->searchTerms()->delete();
$entity->deletions()->delete();
$entity->favourites()->delete();
$entity->referencesTo()->delete();
$entity->referencesFrom()->delete();
if ($entity instanceof HasCoverImage && $entity->cover()->exists()) {
$imageService = app()->make(ImageService::class);

View File

@ -14,6 +14,8 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
*/
class Reference extends Model
{
public $timestamps = false;
public function from(): MorphTo
{
return $this->morphTo('from');

View File

@ -0,0 +1,67 @@
<?php
namespace Tests\References;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Entities\Tools\TrashCan;
use BookStack\Model;
use BookStack\References\Reference;
use Tests\TestCase;
class ReferencesTest extends TestCase
{
public function test_references_created_on_page_update()
{
/** @var Page $pageA */
/** @var Page $pageB */
$pageA = Page::query()->first();
$pageB = Page::query()->where('id', '!=', $pageA->id)->first();
$this->assertDatabaseMissing('references', ['from_id' => $pageA->id, 'from_type' => $pageA->getMorphClass()]);
$this->asEditor()->put($pageA->getUrl(), [
'name' => 'Reference test',
'html' => '<a href="' . $pageB->getUrl() . '">Testing</a>'
]);
$this->assertDatabaseHas('references', [
'from_id' => $pageA->id,
'from_type' => $pageA->getMorphClass(),
'to_id' => $pageB->id,
'to_type' => $pageB->getMorphClass(),
]);
}
public function test_references_deleted_on_entity_delete()
{
/** @var Page $pageA */
/** @var Page $pageB */
$pageA = Page::query()->first();
$pageB = Page::query()->where('id', '!=', $pageA->id)->first();
$this->createReference($pageA, $pageB);
$this->createReference($pageB, $pageA);
$this->assertDatabaseHas('references', ['from_id' => $pageA->id, 'from_type' => $pageA->getMorphClass()]);
$this->assertDatabaseHas('references', ['to_id' => $pageA->id, 'to_type' => $pageA->getMorphClass()]);
app(PageRepo::class)->destroy($pageA);
app(TrashCan::class)->empty();
$this->assertDatabaseMissing('references', ['from_id' => $pageA->id, 'from_type' => $pageA->getMorphClass()]);
$this->assertDatabaseMissing('references', ['to_id' => $pageA->id, 'to_type' => $pageA->getMorphClass()]);
}
protected function createReference(Model $from, Model $to)
{
(new Reference())->forceFill([
'from_type' => $from->getMorphClass(),
'from_id' => $from->id,
'to_type' => $to->getMorphClass(),
'to_id' => $to->id,
])->save();
}
}