Skip to content

Commit d014e11

Browse files
feat!: urlParser for resolvePermalinks
1 parent d4cd07b commit d014e11

File tree

3 files changed

+71
-47
lines changed

3 files changed

+71
-47
lines changed

README.md

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,21 +271,38 @@ A middleware checks if a `Authentication` header is set, which is not the case i
271271

272272
### `resolvePermalinks()`
273273

274-
This field method resolves page and file permalinks to their respective URLs. It is primarily intended for usage with KQL queries, because the value of `writer` fields contain permalink URLs like `/@/page/nDvVIAwDBph4uOpm`. But the method works with any field that contains permalinks in `href` attributes.
274+
This field method resolves page and file permalinks to their respective URLs. It is primarily intended for usage with KQL queries, because the value of `writer` fields contain permalink URLs like `/@/page/nDvVIAwDBph4uOpm`. But the method works with any field values that contains permalinks in `href` or `src` attributes.
275275

276-
In multilanguage setups, you may want to remove a language prefix like `/de` from the URL. You can do so by defining a custom path parser in your `config.php`:
276+
For headless usage, you may want to remove the origin from the URL and just return the path. You can do so by defining a custom URL parser in your `config.php`:
277277

278278
```php
279279
# /site/config/config.php
280280
return [
281281
'permalinksResolver' => [
282-
// Strip the language code prefix from the URL for German
283-
'pathParser' => function (string $path, \Kirby\Cms\App $kirby) {
282+
// Strip the origin from the URL
283+
'urlParser' => function (string $url, \Kirby\Cms\App $kirby) {
284+
$path = parse_url($url, PHP_URL_PATH);
285+
return $path;
286+
}
287+
]
288+
];
289+
```
290+
291+
Or in multilanguage setups, you may want to remove a language prefix like `/de` from the URL:
292+
293+
```php
294+
# /site/config/config.php
295+
return [
296+
'permalinksResolver' => [
297+
// Strip the language code prefix from German URLs
298+
'urlParser' => function (string $url, \Kirby\Cms\App $kirby) {
299+
$path = parse_url($url, PHP_URL_PATH);
300+
284301
if (str_starts_with($path, '/de')) {
285302
return substr($path, 3);
286303
}
287304
288-
return '';
305+
return $path;
289306
}
290307
]
291308
];

composer.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/extensions/fieldMethods.php

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
<?php
22

3-
$filesFieldResolver = function (\Kirby\Cms\Block $block) {
3+
use Kirby\Cms\Block;
4+
use Kirby\Content\Field;
5+
use Kirby\Toolkit\A;
6+
use Kirby\Toolkit\Dom;
7+
use Kirby\Uuid\Uuid;
8+
9+
$filesFieldResolver = function (Block $block) {
410
$kirby = $block->kirby();
511
$blocks = $kirby->option('blocksResolver.files', ['image' => 'image']);
612

@@ -48,7 +54,7 @@
4854
return $block;
4955
};
5056

51-
$pagesFieldResolver = function (\Kirby\Cms\Block $block) {
57+
$pagesFieldResolver = function (Block $block) {
5258
$kirby = $block->kirby();
5359
$blocks = $kirby->option('blocksResolver.pages', []);
5460

@@ -94,7 +100,7 @@
94100
};
95101

96102
// Support any field type
97-
$customFieldResolver = function (\Kirby\Cms\Block $block) {
103+
$customFieldResolver = function (Block $block) {
98104
$kirby = $block->kirby();
99105
$resolvers = $kirby->option('blocksResolver.resolvers', []);
100106

@@ -118,14 +124,13 @@
118124
return $block;
119125
};
120126

121-
$nestedBlocksFieldResolver = function (\Kirby\Cms\Block $block) use ($filesFieldResolver) {
122-
/** @var \Kirby\Cms\Block $block */
127+
$nestedBlocksFieldResolver = function (Block $block) use ($filesFieldResolver) {
128+
/** @var Block $block */
123129
$kirby = $block->kirby();
124130
$nestedBlocks = $kirby->option('blocksResolver.nested', ['prose']);
125131
$blocksKeys = array_intersect($block->content()->keys(), $nestedBlocks);
126132

127133
foreach ($blocksKeys as $key) {
128-
/** @var \Kirby\Content\Field $ktField */
129134
$field = $block->content()->get($key);
130135

131136
$block->content()->update([
@@ -142,31 +147,33 @@
142147
*
143148
* @kql-allowed
144149
*/
145-
'resolvePermalinks' => function (\Kirby\Content\Field $field) {
150+
'resolvePermalinks' => function (Field $field) {
146151
$kirby = $field->parent()->kirby();
147-
$pathParser = $kirby->option('permalinksResolver.pathParser', fn (string $path) => $path);
148-
149-
if (!is_string($field->value)) {
150-
return $field;
151-
}
152-
153-
$field->value = preg_replace_callback(
154-
'!href="\/@\/(page|file)\/([^"]+)"!',
155-
function ($matches) use ($kirby, $pathParser) {
156-
$type = $matches[1]; // Either `page` or `file`
157-
$id = $matches[2]; // The UUID
158-
159-
// Resolve the UUID to the actual model URL
160-
if ($model = \Kirby\Uuid\Uuid::for($type . '://' . $id)?->model()) {
161-
$parsedUrl = parse_url($model->url());
162-
return 'href="' . $pathParser($parsedUrl['path'] ?? '/', $kirby) . '"';
152+
$urlParser = $kirby->option('permalinksResolver.urlParser', fn (string $url, \Kirby\Cms\App $kirby) => $url);
153+
154+
if ($field->isNotEmpty()) {
155+
$dom = new Dom($field->value);
156+
$attributes = ['href', 'src'];
157+
$elements = $dom->query('//*[' . implode(' | ', A::map($attributes, fn ($attribute) => '@' . $attribute)) . ']');
158+
159+
foreach ($elements as $element) {
160+
foreach ($attributes as $attribute) {
161+
if ($element->hasAttribute($attribute) && $url = $element->getAttribute($attribute)) {
162+
try {
163+
if ($uuid = Uuid::for($url)) {
164+
$url = $uuid->model()?->url();
165+
$parsedUrl = $url ? $urlParser($url, $kirby) : null;
166+
$element->setAttribute($attribute, $parsedUrl);
167+
}
168+
} catch (InvalidArgumentException) {
169+
// Ignore anything else than permalinks
170+
}
171+
}
163172
}
173+
}
164174

165-
// If not resolvable, return the original match
166-
return $matches[0];
167-
},
168-
$field->value
169-
);
175+
$field->value = $dom->toString();
176+
}
170177

171178
return $field;
172179
},
@@ -176,7 +183,7 @@ function ($matches) use ($kirby, $pathParser) {
176183
*
177184
* @kql-allowed
178185
*/
179-
'toResolvedBlocks' => function (\Kirby\Content\Field $field) use ($pagesFieldResolver, $filesFieldResolver, $customFieldResolver, $nestedBlocksFieldResolver) {
186+
'toResolvedBlocks' => function (Field $field) use ($pagesFieldResolver, $filesFieldResolver, $customFieldResolver, $nestedBlocksFieldResolver) {
180187
return $field
181188
->toBlocks()
182189
->map($nestedBlocksFieldResolver)
@@ -190,7 +197,7 @@ function ($matches) use ($kirby, $pathParser) {
190197
*
191198
* @kql-allowed
192199
*/
193-
'toResolvedLayouts' => function (\Kirby\Content\Field $field) use ($filesFieldResolver, $pagesFieldResolver, $customFieldResolver) {
200+
'toResolvedLayouts' => function (Field $field) use ($filesFieldResolver, $pagesFieldResolver, $customFieldResolver) {
194201
return $field
195202
->toLayouts()
196203
->map(function (\Kirby\Cms\Layout $layout) use ($filesFieldResolver, $pagesFieldResolver, $customFieldResolver) {

0 commit comments

Comments
 (0)