Url Component effect on Panel preview Url

I have the following custom url component in Kirby 5.

<?php // site/plugins/example/index.php
//...
'components' => [
    'url' => function ($kirby, $path, $options) {
        $path ??= '';
        $original = $kirby->nativeComponent('url');
        $shortPath = ltrim(str_replace('https://www.example.com', '', $path), '/');

        // www.example.com/subdomain(/{path}) => subdomain.example.com/subdomain(/{path})
        if (Str::startsWith($shortPath, 'subdomain/') || $shortPath === 'subdomain') {
            return 'https://subdomain.example.com/'.$shortPath;
        }
        
        return $original($kirby, $path, $options);
    },

the frontend correctly ouputs the modified url. but I also expected the panel preview url to change accordingly, but it does not. even calling the url method explicitly does not help.

# site/blueprints/pages/subdomain.yml
title: Subdomain

options:
  preview: "{{ page.url }}" # yields www.* but I expected subdomain.*

since the real implementation of my url component is way more complex I can not simply do a page method with the same code and use that as preview url. i need a reliable way to call the url component where the preview url is generated.

Not sure why this would not work. This is the code responsible for the preview URLs: kirby/src/Content/Version.php at main · getkirby/kirby · GitHub

This still does use the $page->url() method in constructing the preview URL.

“it does not” = it shows the URL as if your custom URL component does not exist? Or something different?

the panel is running on the www domain and all the preview links in the panel like for the content page of that subdomain are scoped to the www domain as well. like as if the url component is not running at all.

i have a check for css/js assets as well as tel/mailto links but those do not kick in for the panel preview url.

the code you linked confused me as it did seem to call itself on model→url() when no custom preview was set. i can not follow how that would resolve a models url to a human readable string.

the url component it seems to be called here kirby/src/Cms/Url.php at c9708e5c648fbc3ee381114ceae8876d4ca4f9a1 · getkirby/kirby · GitHub

the panel is running on the www domain and all the preview links in the panel like for the content page of that subdomain are scoped to the www domain as well. like as if the url component is not running at all.

i have a check for css/js assets as well as tel/mailto links but those do not kick in for the panel preview url.

the code you linked confused me as it did seem to call itself on model→url() when no custom preview was set. i can not follow how that would resolve a models url to a human readable string.

the url component it seems to be called here kirby/src/Cms/Url.php at c9708e5c648fbc3ee381114ceae8876d4ca4f9a1 · getkirby/kirby · GitHub

and that would only be called if there are $options for an url… unsure where they might come from when using the preview url via the panel, but maybe (still debugging this) kirby/src/Cms/Page.php at c9708e5c648fbc3ee381114ceae8876d4ca4f9a1 · getkirby/kirby · GitHub

preview: "{{ page.url([]) }}" works :sweat_smile:

some closing context: the issue had come up when using the magnificient SEO Audit plugin by Johann Schopplich but it could not run the audit for pages that where mapped to another subdomain via the url component. with the preview: "{{ page.url([]) }}" that now works flawlessly.

I would’ve thought that for “no options” the component kicks in somewhere down the road from here: kirby/src/Cms/Page.php at c9708e5c648fbc3ee381114ceae8876d4ca4f9a1 · getkirby/kirby · GitHub

But indeed it doesn’t look like it. @lukasbestle do you have a better understanding why the url core component doesn’t play a role in this, as it seems? Wouldn’t we have to wrap also the later returns in Page::url() with Url::to() as we do when $options isn’t null?

Looks like we didn’t think about the use case of rewriting model URLs to external domains via the url component.

However we cannot just call Url::to() from $page->url(), otherwise we will have a cyclic dependency as the default url component also calls $page->url() internally.

I’d say the more robust implementation would be to include the custom URL logic in a page model (overriding $page->url()) instead of in the url component.

1 Like