mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-10-12 02:01:37 +00:00
API: Added changelog support to page create/update API
Also changed the UI based forms to submit as changelog instead of summary to align with more sensible name used on the API. Added testing to cover. For #6162
This commit is contained in:
@@ -27,6 +27,7 @@ class PageApiController extends ApiController
|
||||
'markdown' => ['required_without:html', 'string'],
|
||||
'tags' => ['array'],
|
||||
'priority' => ['integer'],
|
||||
'changelog' => ['string', 'min:1', 'max:180'],
|
||||
],
|
||||
'update' => [
|
||||
'book_id' => ['integer'],
|
||||
@@ -36,6 +37,7 @@ class PageApiController extends ApiController
|
||||
'markdown' => ['string'],
|
||||
'tags' => ['array'],
|
||||
'priority' => ['integer'],
|
||||
'changelog' => ['string', 'min:1', 'max:180'],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -75,7 +77,7 @@ class PageApiController extends ApiController
|
||||
*/
|
||||
public function create(Request $request): JsonResponse
|
||||
{
|
||||
$this->validate($request, $this->rules['create']);
|
||||
$validated = $this->validate($request, $this->rules['create']);
|
||||
|
||||
if ($request->has('chapter_id')) {
|
||||
$parent = $this->entityQueries->chapters->findVisibleByIdOrFail(intval($request->input('chapter_id')));
|
||||
@@ -85,7 +87,7 @@ class PageApiController extends ApiController
|
||||
$this->checkOwnablePermission(Permission::PageCreate, $parent);
|
||||
|
||||
$draft = $this->pageRepo->getNewDraftPage($parent);
|
||||
$this->pageRepo->publishDraft($draft, $request->only(array_keys($this->rules['create'])));
|
||||
$this->pageRepo->publishDraft($draft, $validated);
|
||||
|
||||
return response()->json($draft->forJsonDisplay());
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ class PageRepo
|
||||
$draft = $this->baseRepo->update($draft, $input);
|
||||
$draft->rebuildPermissions();
|
||||
|
||||
$summary = trim($input['summary'] ?? '') ?: trans('entities.pages_initial_revision');
|
||||
$summary = trim($input['changelog'] ?? '') ?: trans('entities.pages_initial_revision');
|
||||
$this->revisionRepo->storeNewForPage($draft, $summary);
|
||||
$draft->refresh();
|
||||
|
||||
@@ -134,7 +134,7 @@ class PageRepo
|
||||
$this->revisionRepo->deleteDraftsForCurrentUser($page);
|
||||
|
||||
// Save a revision after updating
|
||||
$summary = trim($input['summary'] ?? '');
|
||||
$summary = trim($input['changelog'] ?? '');
|
||||
$htmlChanged = isset($input['html']) && $input['html'] !== $oldHtml;
|
||||
$nameChanged = isset($input['name']) && $input['name'] !== $oldName;
|
||||
$markdownChanged = isset($input['markdown']) && $input['markdown'] !== $oldMarkdown;
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
<p class="text-muted pb-s">{{ trans('entities.pages_edit_enter_changelog_desc') }}</p>
|
||||
<textarea
|
||||
refs="page-editor@changelogInput"
|
||||
name="summary"
|
||||
name="changelog"
|
||||
id="summary-input"
|
||||
rows="2"
|
||||
maxlength="180"
|
||||
|
||||
@@ -30,7 +30,7 @@ class WebhookFormatTesting extends TestCase
|
||||
public function test_page_create_and_update_events_show_revision_info()
|
||||
{
|
||||
$page = $this->entities->page();
|
||||
$this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
|
||||
$this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'changelog' => 'Update a']);
|
||||
|
||||
$data = $this->getWebhookData(ActivityType::PAGE_UPDATE, $page);
|
||||
$this->assertEquals($page->currentRevision->id, Arr::get($data, 'related_item.current_revision.id'));
|
||||
|
||||
@@ -128,6 +128,27 @@ class PagesApiTest extends TestCase
|
||||
$this->assertStringContainsString('href="https://example.com"', $respHtml);
|
||||
}
|
||||
|
||||
public function test_create_can_accept_a_changelog_message()
|
||||
{
|
||||
$this->actingAsApiEditor();
|
||||
$book = $this->entities->book();
|
||||
$details = [
|
||||
'name' => 'My updated API page',
|
||||
'html' => '<p>A page updated via the API</p>',
|
||||
'changelog' => 'This is a create changelog message via the API',
|
||||
'book_id' => $book->id,
|
||||
];
|
||||
|
||||
$resp = $this->postJson($this->baseEndpoint, $details);
|
||||
$resp->assertOk();
|
||||
|
||||
$pageId = $resp->json('id');
|
||||
$page = Page::query()->findOrFail($pageId);
|
||||
|
||||
$latestRevision = $page->revisions()->orderBy('id', 'desc')->first();
|
||||
$this->assertEquals('This is a create changelog message via the API', $latestRevision->summary);
|
||||
}
|
||||
|
||||
public function test_read_endpoint()
|
||||
{
|
||||
$this->actingAsApiEditor();
|
||||
@@ -338,6 +359,23 @@ class PagesApiTest extends TestCase
|
||||
$this->assertGreaterThan(Carbon::now()->subDay()->unix(), $page->updated_at->unix());
|
||||
}
|
||||
|
||||
public function test_update_can_accept_a_changelog_message()
|
||||
{
|
||||
$this->actingAsApiEditor();
|
||||
$page = $this->entities->page();
|
||||
$details = [
|
||||
'name' => 'My updated API page',
|
||||
'html' => '<p>A page updated via the API</p>',
|
||||
'changelog' => 'This is a changelog message via the API',
|
||||
];
|
||||
|
||||
$resp = $this->putJson($this->baseEndpoint . "/{$page->id}", $details);
|
||||
$resp->assertOk();
|
||||
|
||||
$latestRevision = $page->revisions()->orderBy('id', 'desc')->first();
|
||||
$this->assertEquals('This is a changelog message via the API', $latestRevision->summary);
|
||||
}
|
||||
|
||||
public function test_delete_endpoint()
|
||||
{
|
||||
$this->actingAsApiEditor();
|
||||
|
||||
@@ -14,8 +14,8 @@ class ClearRevisionsCommandTest extends TestCase
|
||||
$this->asEditor();
|
||||
$pageRepo = app(PageRepo::class);
|
||||
$page = Page::first();
|
||||
$pageRepo->update($page, ['name' => 'updated page', 'html' => '<p>new content</p>', 'summary' => 'page revision testing']);
|
||||
$pageRepo->updatePageDraft($page, ['name' => 'updated page', 'html' => '<p>new content in draft</p>', 'summary' => 'page revision testing']);
|
||||
$pageRepo->update($page, ['name' => 'updated page', 'html' => '<p>new content</p>', 'changelog' => 'page revision testing']);
|
||||
$pageRepo->updatePageDraft($page, ['name' => 'updated page', 'html' => '<p>new content in draft</p>', 'changelog' => 'page revision testing']);
|
||||
|
||||
$this->assertDatabaseHas('page_revisions', [
|
||||
'page_id' => $page->id,
|
||||
|
||||
@@ -48,7 +48,7 @@ class PageContentTest extends TestCase
|
||||
$includeTag = '{{@' . $secondPage->id . '}}';
|
||||
$page->html = '<p>' . $includeTag . '</p>';
|
||||
|
||||
$resp = $this->put($page->getUrl(), ['name' => $page->name, 'html' => $page->html, 'summary' => '']);
|
||||
$resp = $this->put($page->getUrl(), ['name' => $page->name, 'html' => $page->html, 'changelog' => '']);
|
||||
|
||||
$resp->assertStatus(302);
|
||||
|
||||
@@ -127,7 +127,7 @@ class PageContentTest extends TestCase
|
||||
$pageSave = $this->put($page->getUrl(), [
|
||||
'name' => $page->name,
|
||||
'html' => $content,
|
||||
'summary' => '',
|
||||
'changelog' => '',
|
||||
]);
|
||||
$pageSave->assertRedirect();
|
||||
|
||||
@@ -144,7 +144,7 @@ class PageContentTest extends TestCase
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name,
|
||||
'html' => $content,
|
||||
'summary' => '',
|
||||
'changelog' => '',
|
||||
]);
|
||||
|
||||
$updatedPage = Page::query()->where('id', '=', $page->id)->first();
|
||||
@@ -253,7 +253,7 @@ class PageContentTest extends TestCase
|
||||
| Paragraph | Text |';
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'markdown' => $content,
|
||||
'html' => '', 'summary' => '',
|
||||
'html' => '', 'changelog' => '',
|
||||
]);
|
||||
|
||||
$page->refresh();
|
||||
@@ -272,7 +272,7 @@ class PageContentTest extends TestCase
|
||||
- [x] Item b';
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'markdown' => $content,
|
||||
'html' => '', 'summary' => '',
|
||||
'html' => '', 'changelog' => '',
|
||||
]);
|
||||
|
||||
$page->refresh();
|
||||
@@ -292,7 +292,7 @@ class PageContentTest extends TestCase
|
||||
$content = '~~some crossed out text~~';
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'markdown' => $content,
|
||||
'html' => '', 'summary' => '',
|
||||
'html' => '', 'changelog' => '',
|
||||
]);
|
||||
|
||||
$page->refresh();
|
||||
@@ -311,7 +311,7 @@ class PageContentTest extends TestCase
|
||||
$content = '<!-- Test Comment -->';
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'markdown' => $content,
|
||||
'html' => '', 'summary' => '',
|
||||
'html' => '', 'changelog' => '',
|
||||
])->assertRedirect();
|
||||
|
||||
$page->refresh();
|
||||
@@ -328,7 +328,7 @@ class PageContentTest extends TestCase
|
||||
$page = $this->entities->page();
|
||||
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'summary' => '',
|
||||
'name' => $page->name, 'changelog' => '',
|
||||
'html' => '<p>test<img src="data:image/jpeg;base64,' . $this->base64Jpeg . '"/></p>',
|
||||
]);
|
||||
|
||||
@@ -352,7 +352,7 @@ class PageContentTest extends TestCase
|
||||
$base64PngWithWhitespace = "iVBORw0KGg\noAAAANSUhE\tUgAAAAEAAAA BCA YAAAAfFcSJAAA\n\t ACklEQVR4nGMAAQAABQAB";
|
||||
$base64PngWithoutWhitespace = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQAB';
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'summary' => '',
|
||||
'name' => $page->name, 'changelog' => '',
|
||||
'html' => '<p>test<img src="data:image/png;base64,' . $base64PngWithWhitespace . '"/></p>',
|
||||
]);
|
||||
|
||||
@@ -381,7 +381,7 @@ class PageContentTest extends TestCase
|
||||
$page = $this->entities->page();
|
||||
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'summary' => '',
|
||||
'name' => $page->name, 'changelog' => '',
|
||||
'html' => '<p>test<img src="data:image/' . $extension . ';base64,' . $this->base64Jpeg . '"/></p>',
|
||||
]);
|
||||
|
||||
@@ -425,7 +425,7 @@ class PageContentTest extends TestCase
|
||||
$page = $this->entities->page();
|
||||
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'summary' => '',
|
||||
'name' => $page->name, 'changelog' => '',
|
||||
'markdown' => 'test ',
|
||||
]);
|
||||
|
||||
@@ -456,7 +456,7 @@ class PageContentTest extends TestCase
|
||||
$base64Content = base64_encode($content);
|
||||
|
||||
$this->put($page->getUrl(), [
|
||||
'name' => $page->name, 'summary' => '',
|
||||
'name' => $page->name, 'changelog' => '',
|
||||
'markdown' => 'test  ',
|
||||
]);
|
||||
|
||||
@@ -479,7 +479,7 @@ class PageContentTest extends TestCase
|
||||
$page = $this->entities->page();
|
||||
|
||||
$this->asEditor()->put($page->getUrl(), [
|
||||
'name' => $page->name, 'summary' => '',
|
||||
'name' => $page->name, 'changelog' => '',
|
||||
'markdown' => 'test ',
|
||||
]);
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ class PageRevisionTest extends TestCase
|
||||
{
|
||||
$this->asEditor();
|
||||
$page = $this->entities->page();
|
||||
$this->createRevisions($page, 1, ['name' => 'updated page abc123', 'html' => '<p>new contente def456</p>', 'summary' => 'My first update']);
|
||||
$this->createRevisions($page, 1, ['name' => 'updated page abc123', 'html' => '<p>new contente def456</p>', 'changelog' => 'My first update']);
|
||||
$this->createRevisions($page, 1, ['html' => '<p>new content</p>']);
|
||||
$page->refresh();
|
||||
|
||||
@@ -327,7 +327,7 @@ class PageRevisionTest extends TestCase
|
||||
$user = user();
|
||||
|
||||
for ($i = 0; $i < $times; $i++) {
|
||||
$data = ['name' => 'Page update' . $i, 'summary' => 'Update entry' . $i];
|
||||
$data = ['name' => 'Page update' . $i, 'changelog' => 'Update entry' . $i];
|
||||
if (!isset($attrs['markdown'])) {
|
||||
$data['html'] = '<p>My update page</p>';
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ class PageTest extends TestCase
|
||||
$details = [
|
||||
'html' => '<h1>a title</h1>',
|
||||
'name' => 'My page with summary',
|
||||
'summary' => 'Here is my changelog message for a new page!',
|
||||
'changelog' => 'Here is my changelog message for a new page!',
|
||||
];
|
||||
$resp = $this->post($book->getUrl("/draft/{$draft->id}"), $details);
|
||||
$resp->assertRedirect();
|
||||
|
||||
@@ -819,7 +819,7 @@ class ImageTest extends TestCase
|
||||
$pageRepo->update($page, [
|
||||
'name' => $page->name,
|
||||
'html' => $page->html . "<img src=\"{$image->url}\">",
|
||||
'summary' => '',
|
||||
'changelog' => '',
|
||||
]);
|
||||
|
||||
// Ensure no images are reported as deletable
|
||||
@@ -831,7 +831,7 @@ class ImageTest extends TestCase
|
||||
$pageRepo->update($page, [
|
||||
'name' => $page->name,
|
||||
'html' => '<p>Hello</p>',
|
||||
'summary' => '',
|
||||
'changelog' => '',
|
||||
]);
|
||||
|
||||
// Ensure revision images are picked up okay
|
||||
|
||||
Reference in New Issue
Block a user