Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Page create dialog: add form validation #5687

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions config/areas/site/dialogs.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Kirby\Cms\App;
use Kirby\Cms\Find;
use Kirby\Cms\Page;
use Kirby\Cms\PageRules;
use Kirby\Cms\Response;
use Kirby\Exception\Exception;
use Kirby\Exception\InvalidArgumentException;
Expand Down Expand Up @@ -236,17 +237,8 @@
$slug = trim($request->get('slug', ''));

// basic input validation before we move on
if (Str::length($title) === 0) {
throw new InvalidArgumentException([
'key' => 'page.changeTitle.empty'
]);
}

if (Str::length($slug) === 0) {
throw new InvalidArgumentException([
'key' => 'page.slug.invalid'
]);
}
PageRules::validateTitleLength($title);
PageRules::validateSlugLength($slug);

// nothing changed
if ($page->title()->value() === $title && $page->slug() === $slug) {
Expand Down
22 changes: 16 additions & 6 deletions src/Cms/PageRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,7 @@ public static function changeTitle(Page $page, string $title): bool
]);
}

if (Str::length($title) === 0) {
throw new InvalidArgumentException([
'key' => 'page.changeTitle.empty',
]);
}
static::validateTitleLength($title);

return true;
}
Expand Down Expand Up @@ -452,7 +448,7 @@ public static function update(Page $page, array $content = []): bool
*
* @throws \Kirby\Exception\InvalidArgumentException If the slug is empty or too long
*/
protected static function validateSlugLength(string $slug): void
public static function validateSlugLength(string $slug): void
{
$slugLength = Str::length($slug);

Expand Down Expand Up @@ -505,4 +501,18 @@ protected static function validateSlugProtectedPaths(
}
}
}

/**
* Ensures that the page title is not empty
*
* @throws \Kirby\Exception\InvalidArgumentException If the title is empty
*/
public static function validateTitleLength(string $title): void
{
if (Str::length($title) === 0) {
throw new InvalidArgumentException([
'key' => 'page.changeTitle.empty',
]);
}
}
}
32 changes: 22 additions & 10 deletions src/Panel/PageCreateDialog.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
use Kirby\Cms\Find;
use Kirby\Cms\Page;
use Kirby\Cms\PageBlueprint;
use Kirby\Cms\PageRules;
use Kirby\Cms\Site;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Form\Form;
use Kirby\Toolkit\A;
use Kirby\Toolkit\I18n;
use Kirby\Toolkit\Str;

/**
* Manages the Panel dialog to create new pages
Expand Down Expand Up @@ -248,12 +248,13 @@ public function sanitize(array $input): array
*/
public function submit(array $input): array
{
$input = $this->sanitize($input);
$input = $this->sanitize($input);
$status = $this->blueprint()->create()['status'] ?? 'draft';

$this->validate($input);
// validate the input before creating the page
$this->validate($input, $status);

$page = $this->parent->createChild($input);
$status = $this->blueprint()->create()['status'] ?? 'draft';
$page = $this->parent->createChild($input);

if ($status !== 'draft') {
// grant all permissions as the status is set in the blueprint and
Expand All @@ -276,12 +277,23 @@ public function submit(array $input): array
return $payload;
}

public function validate(array $input): bool
public function validate(array $input, string $status = 'draft'): bool
{
if (Str::length($input['content']['title']) === 0) {
throw new InvalidArgumentException([
'key' => 'page.changeTitle.empty'
]);
// basic validation
PageRules::validateTitleLength($input['content']['title']);
PageRules::validateSlugLength($input['slug']);

// if the page is supposed to be published directly,
// ensure that all field validations are met
if ($status !== 'draft') {
// create temporary form to validate the input
$form = Form::for($this->model(), ['values' => $input['content']]);

if ($form->isInvalid() === true) {
throw new InvalidArgumentException([
'key' => 'page.changeStatus.incomplete'
]);
}
}

return true;
Expand Down
145 changes: 145 additions & 0 deletions tests/Panel/Areas/PageCreateDialogTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

namespace Kirby\Panel\Areas;

use Kirby\Exception\InvalidArgumentException;
use Kirby\Panel\PageCreateDialog;

/**
* @coversDefaultClass \Kirby\Panel\Areas\PageCreateDialog
*/
class PageCreateDialogTest extends AreaTestCase
{
public function setUp(): void
{
parent::setUp();
$this->install();
$this->login();
}

/**
* @covers ::coreFields
*/
public function testCoreFields(): void
{
$dialog = new PageCreateDialog(
null,
null,
'test',
null
);

$fields = $dialog->coreFields();

$this->assertSame('Title', $fields['title']['label']);
$this->assertSame('/', $fields['slug']['path']);
}

/**
* @covers ::validate
*/
public function testValidateInvalidTitle(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionCode('error.page.changeTitle.empty');

$dialog = new PageCreateDialog(
null,
null,
'test',
null
);

$dialog->validate(['content' => ['title' => '']]);
}

/**
* @covers ::validate
*/
public function testValidateInvalidSlug(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionCode('error.page.slug.invalid');

$dialog = new PageCreateDialog(
null,
null,
'test',
null
);

$dialog->validate([
'slug' => '',
'content' => ['title' => 'Foo']
]);
}

/**
* @covers ::validate
*/
public function testValidateInvalidFields(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionCode('error.page.changeStatus.incomplete');

$this->app([
'blueprints' => [
'pages/test' => [
'fields' => [
'foo' => [
'type' => 'text',
'required' => true
]
]
]
]
]);


$dialog = new PageCreateDialog(
null,
null,
'test',
null
);

$dialog->validate([
'slug' => 'foo',
'content' => ['title' => 'Foo']
], 'listed');
}

/**
* @covers ::validate
*/
public function testValidateValidFields(): void
{
$this->app([
'blueprints' => [
'pages/test' => [
'fields' => [
'foo' => [
'type' => 'text',
'required' => true
]
]
]
]
]);


$dialog = new PageCreateDialog(
null,
null,
'test',
null
);

$valid = $dialog->validate([
'slug' => 'foo',
'content' => ['title' => 'Foo', 'foo' => 'bar']
], 'listed');

$this->assertTrue($valid);
}
}