Skip to content

Commit

Permalink
Rolled out reference link updating logic usage
Browse files Browse the repository at this point in the history
Added test to cover updating of content on reference url change
  • Loading branch information
ssddanbrown committed Aug 21, 2022
1 parent 0dbf084 commit b86ee6d
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 15 deletions.
7 changes: 7 additions & 0 deletions app/Entities/Models/BookChild.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace BookStack\Entities\Models;

use BookStack\References\ReferenceUpdater;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

Expand Down Expand Up @@ -57,9 +58,15 @@ public function book(): BelongsTo
*/
public function changeBook(int $newBookId): Entity
{
$oldUrl = $this->getUrl();
$this->book_id = $newBookId;
$this->refreshSlug();
$this->save();

if ($oldUrl !== $this->getUrl()) {
app()->make(ReferenceUpdater::class)->updateEntityPageReferences($this, $oldUrl);
}

$this->refresh();

// Update all child pages if a chapter
Expand Down
11 changes: 10 additions & 1 deletion app/Entities/Repos/BaseRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\HasCoverImage;
use BookStack\Exceptions\ImageUploadException;
use BookStack\References\ReferenceUpdater;
use BookStack\Uploads\ImageRepo;
use Illuminate\Http\UploadedFile;

class BaseRepo
{
protected TagRepo $tagRepo;
protected ImageRepo $imageRepo;
protected ReferenceUpdater $referenceUpdater;

public function __construct(TagRepo $tagRepo, ImageRepo $imageRepo)
public function __construct(TagRepo $tagRepo, ImageRepo $imageRepo, ReferenceUpdater $referenceUpdater)
{
$this->tagRepo = $tagRepo;
$this->imageRepo = $imageRepo;
$this->referenceUpdater = $referenceUpdater;
}

/**
Expand Down Expand Up @@ -48,6 +51,8 @@ public function create(Entity $entity, array $input)
*/
public function update(Entity $entity, array $input)
{
$oldUrl = $entity->getUrl();

$entity->fill($input);
$entity->updated_by = user()->id;

Expand All @@ -64,6 +69,10 @@ public function update(Entity $entity, array $input)

$entity->rebuildPermissions();
$entity->indexForSearch();

if ($oldUrl !== $entity->getUrl()) {
$this->referenceUpdater->updateEntityPageReferences($entity, $oldUrl);
}
}

/**
Expand Down
33 changes: 22 additions & 11 deletions app/Entities/Repos/PageRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,31 @@
use BookStack\Exceptions\PermissionsException;
use BookStack\Facades\Activity;
use BookStack\References\ReferenceStore;
use BookStack\References\ReferenceUpdater;
use Exception;
use Illuminate\Pagination\LengthAwarePaginator;

class PageRepo
{
protected BaseRepo $baseRepo;
protected RevisionRepo $revisionRepo;
protected ReferenceStore $references;
protected ReferenceStore $referenceStore;
protected ReferenceUpdater $referenceUpdater;

/**
* PageRepo constructor.
*/
public function __construct(BaseRepo $baseRepo, RevisionRepo $revisionRepo, ReferenceStore $references)
public function __construct(
BaseRepo $baseRepo,
RevisionRepo $revisionRepo,
ReferenceStore $referenceStore,
ReferenceUpdater $referenceUpdater
)
{
$this->baseRepo = $baseRepo;
$this->revisionRepo = $revisionRepo;
$this->references = $references;
$this->referenceStore = $referenceStore;
$this->referenceUpdater = $referenceUpdater;
}

/**
Expand Down Expand Up @@ -127,11 +135,11 @@ public function getUserDraft(Page $page): ?PageRevision
public function getNewDraftPage(Entity $parent)
{
$page = (new Page())->forceFill([
'name' => trans('entities.pages_initial_name'),
'name' => trans('entities.pages_initial_name'),
'created_by' => user()->id,
'owned_by' => user()->id,
'owned_by' => user()->id,
'updated_by' => user()->id,
'draft' => true,
'draft' => true,
]);

if ($parent instanceof Chapter) {
Expand All @@ -158,12 +166,10 @@ public function publishDraft(Page $draft, array $input): Page
$draft->draft = false;
$draft->revision_count = 1;
$draft->priority = $this->getNewPriority($draft);
$draft->refreshSlug();
$draft->save();

$this->revisionRepo->storeNewForPage($draft, trans('entities.pages_initial_revision'));
$draft->indexForSearch();
$this->references->updateForPage($draft);
$this->referenceStore->updateForPage($draft);
$draft->refresh();

Activity::add(ActivityType::PAGE_CREATE, $draft);
Expand All @@ -183,7 +189,7 @@ public function update(Page $page, array $input): Page

$this->updateTemplateStatusAndContentFromInput($page, $input);
$this->baseRepo->update($page, $input);
$this->references->updateForPage($page);
$this->referenceStore->updateForPage($page);

// Update with new details
$page->revision_count++;
Expand Down Expand Up @@ -283,6 +289,7 @@ public function destroy(Page $page)
*/
public function restoreRevision(Page $page, int $revisionId): Page
{
$oldUrl = $page->getUrl();
$page->revision_count++;

/** @var PageRevision $revision */
Expand All @@ -301,11 +308,15 @@ public function restoreRevision(Page $page, int $revisionId): Page
$page->refreshSlug();
$page->save();
$page->indexForSearch();
$this->references->updateForPage($page);
$this->referenceStore->updateForPage($page);

$summary = trans('entities.pages_revision_restored_from', ['id' => strval($revisionId), 'summary' => $revision->summary]);
$this->revisionRepo->storeNewForPage($page, $summary);

if ($oldUrl !== $page->getUrl()) {
$this->referenceUpdater->updateEntityPageReferences($page, $oldUrl);
}

Activity::add(ActivityType::PAGE_RESTORE, $page);
Activity::add(ActivityType::REVISION_RESTORE, $revision);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use DOMDocument;
use DOMXPath;

class CrossLinkReplacer
class ReferenceUpdater
{
protected ReferenceFetcher $referenceFetcher;
protected RevisionRepo $revisionRepo;
Expand Down Expand Up @@ -53,10 +53,10 @@ protected function updateLinksInMarkdown(string $markdown, string $oldLink, stri
return $markdown;
}

$commonLinkRegex = '/(\[.*?\]\()' . preg_quote($oldLink) . '(.*?\))/i';
$commonLinkRegex = '/(\[.*?\]\()' . preg_quote($oldLink, '/') . '(.*?\))/i';
$markdown = preg_replace($commonLinkRegex, '$1' . $newLink . '$2', $markdown);

$referenceLinkRegex = '/(\[.*?\]:\s?)' . preg_quote($oldLink) . '(.*?)($|\s)/i';
$referenceLinkRegex = '/(\[.*?\]:\s?)' . preg_quote($oldLink, '/') . '(.*?)($|\s)/i';
$markdown = preg_replace($referenceLinkRegex, '$1' . $newLink . '$2$3', $markdown);

return $markdown;
Expand Down
59 changes: 59 additions & 0 deletions tests/References/ReferencesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Tests\References;

use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Entities\Tools\TrashCan;
Expand Down Expand Up @@ -116,6 +117,64 @@ public function test_reference_page_shows_empty_state_with_no_references()
->assertSee('There are no tracked references');
}

public function test_pages_leading_to_entity_updated_on_url_change()
{
/** @var Page $pageA */
/** @var Page $pageB */
/** @var Book $book */
$pageA = Page::query()->first();
$pageB = Page::query()->where('id', '!=', $pageA->id)->first();
$book = Book::query()->first();

foreach ([$pageA, $pageB] as $page) {
$page->html = '<a href="' . $book->getUrl() . '">Link</a>';
$page->save();
$this->createReference($page, $book);
}

$this->asEditor()->put($book->getUrl(), [
'name' => 'my updated book slugaroo',
]);

foreach ([$pageA, $pageB] as $page) {
$page->refresh();
$this->assertStringContainsString('href="http://localhost/books/my-updated-book-slugaroo"', $page->html);
$this->assertDatabaseHas('page_revisions', [
'page_id' => $page->id,
'summary' => 'System auto-update of internal links'
]);
}
}

public function test_markdown_links_leading_to_entity_updated_on_url_change()
{
/** @var Page $page */
/** @var Book $book */
$page = Page::query()->first();
$book = Book::query()->first();

$bookUrl = $book->getUrl();
$markdown = '
[An awesome link](' . $bookUrl . ')
[An awesome link with query & hash](' . $bookUrl . '?test=yes#cats)
[An awesome link with path](' . $bookUrl . '/an/extra/trail)
[An awesome link with title](' . $bookUrl . ' "title")
[ref]: ' . $bookUrl . '?test=yes#dogs
[ref_without_space]:' . $bookUrl . '
[ref_with_title]: ' . $bookUrl . ' "title"';
$page->markdown = $markdown;
$page->save();
$this->createReference($page, $book);

$this->asEditor()->put($book->getUrl(), [
'name' => 'my updated book slugadoo',
]);

$page->refresh();
$expected = str_replace($bookUrl, 'http://localhost/books/my-updated-book-slugadoo', $markdown);
$this->assertEquals($expected, $page->markdown);
}

protected function createReference(Model $from, Model $to)
{
(new Reference())->forceFill([
Expand Down

0 comments on commit b86ee6d

Please sign in to comment.