Hook page.create:before, how to edit user input?

When creating a page in a pages section I’d like to intercept user input and change e.g. slug to something else.

How would I do that with a page.create:before hook? What would I return?

'page.create:before' => function ($parent, $input) {
      $input['slug'] = 'randomslug';
      // return ...?
}

When I change the slug in the page.create:after hook, the panel redirects to the wrong url (the old slug).

'page.create:after' => function ($page) {
    $page->changeSlug('randomslug');
}

I’m not sure, but I don’t think this can be achieved with a before hook. I see two options:

  • A page.create:after hook that changes the slug and redirects to the new URL
  • A custom pages section with its own page create logic

hm…I am not able to change the page.id that is sent back to the panel. All Objects are protected…so an own redirect seems impossible.

A custom pages section is an option I want to consider as last resort.

The only way I found was to intercept the request before it was processed by Kirby. So back to the route:before hook.

'route:before' => function ($route, $path, $method) {
    if ($method === "POST") {
        if (preg_match('/pages\/.*\/children$/', $path) === 1) {
            if($request = json_decode(file_get_contents('php://input'), true)) {
                $request['slug'] = "mynewslug";
                $_POST = $request;
            }
        }
    }
}

You could also overwrite the create() method of the parent page in a custom page model.


class ParentPage extends Page
{
    /**
     * Creates and stores a new page
     *
     * @param array $props
     * @return Page
     */
    public static function create(array $props): Page
    {
        $props['slug'] = 'mynewslug';
        
        return parent::create($props);
    }
}

7 Likes

A very elegant solution!

Hi,
i’d like to use this for overwriting the url with a random string for newly added content.
So i added this code to site/model/event.php and changed the class name to EventPage. I also added a page blueprint (event.yml) with custom fields to site/blueprints/pages. After clicking “Create draft” in the panel the new create function is not getting called and so the new content has still the same default url. Do you have any further information what i’m doing wrong?

Thanks

@daw Hey, Welcome to the Kirby forum.

Is the Event page your parent page?

Hi @texnixe, thanks for your fast reply. I’m new to Kirby so i’m not really sure about that. But i used the Events sample in the docs. It’s almost the same, i only added some new fields.
https://getkirby.com/docs/reference/panel/samples/events

If your parent is the page with the events.yml blueprint like in the example, your model has to match that page, e.g. you would have to create an events.php model with the method above.

1 Like

Hi, I’d like to edit @lukaskleinschmidt solution so that the new slug will be “myTitle + thisYear.”

But I can’t get the filed title() from modal. Where am I making mistake? Thank you for your help.

Not tested but it should probably look something like this.

class ParentPage extends Page
{
    /**
     * Creates and stores a new page
     *
     * @param array $props
     * @return Page
     */
    public static function create(array $props): Page
    {
        $props['slug'] = $props['content']['title'] . '-' . date('Y');
        
        return parent::create($props);
    }
}

Thank you for the quick reply.

But for your solution, the panel writes the error: “Undefined index: title”.

I’m thinking, can modal give this value?

Just checked and it has to be $props['content']['title'] instead of $props['title']. I updated the answer above.

Great! Now it really works. @lukaskleinschmidt thank you very much for your help.