How do I create a query to list all images used on a page (in the backend)? In the .txt, the images are located in different areas, e.g. layouts, blocks, structures… These also have completely different field names. I don’t want to list all images that are in the page folder, because not all of them are used.
I would like to automate my current solution, as currently all images are selected manually. This is time consuming and error prone.
This similar post is for Kirby 2 and the link is no longer available.
Thanks for the solution approach. When my PHP knowledge deepens, I will be able to write the code. However, I am still a leap year away from that.
Is there a comparable solution here on the forum or in the cookbook that I can use as a basis? I don’t expect a copy-and-paste solution, as I also want to understand and learn what I’m doing.
Yes, all images have a UUID, so I would have a concrete search scheme.
Not sure, definitely not in the cookbook, but this should get you going:
// read the raw file content into the $content variable
$content = F::read($page->contentFile());
// regex pattern for file UUIDs
$regex = '/file:\/\/[A-Za-z0-9]+/i';
// do a preg_match_all, $matches returns the matches
preg_match_all($regex, $content, $matches);
// $matches[0] contains all full matches
$fileUuids = $matches[0];
// loop through file uuids and try to get a file object from the page
foreach ($fileUuids as $uuid) {
if ($file = $page->file($uuid)) {
echo $file->filename();
}
}
If the file can be anywhere in the site instead of in the current page only, you need to use $site->index()->files() instead.
In your case, you don’t want to echo the files, so collect them into a new files collection instead:
$files = new Kirby\Cms\Files();
foreach ($matches[0] as $uuid) {
if ($file = $page->file($uuid)) {
$files->add($file);
}
}
dump($files);
Now you’ve already told me a copy-and-paste solution
That worked like a charm, I didn’t expect that. Thanks!
Only the image names where output, but I will still manage the output of thumbnails. The basic framework works.
But I could still need a little push: It will also output the cover: - file://qOikm2TXiOvHjcmL
(only serves as a preview image for the panel). Sure, it is also in the .txt. file. So you still need to integrate a filter that excludes the cover.
Well, if you simply exclude the cover and image used in the cover field is also used in the rest of the content, then it gets more complex, and you need to loop through all fields but the cover field separately.
Yes, I also noticed earlier that it will be difficult. But the start was so easy.
The output of the thumbnails also worked great.
Then I noticed that some images appear 3x in the list. This is because occasionally an image is used as a cover, in the article and as a meta image. Fortunately, I was able to solve that. But the problem with the individual filter leads me back to my original solution of selecting the images manually.
But I learned something and will keep the new snippet well.
Not difficult, just more complicated, so here you go:
<?php
// get fields from blueprint, exclude the one you don't want
$fields = array_filter($page->blueprint()->fields(), fn($field) => $field !== 'cover', ARRAY_FILTER_USE_KEY);
$regex = '/file:\/\/[A-Za-z0-9]+/i';
$fileUuids = [];
// loop through the field and fetch value from page
foreach ($fields as $field) {
$value = $page->{$field['name']}()->value();
preg_match_all($regex, $value ?? '', $matches);
$fileUuids = array_merge($fileUuids, $matches[0]);
}
$files = new Kirby\Cms\Files();
// only unique file uuids
foreach (array_unique($fileUuids) as $uuid) {
if ($file = $page->file($uuid)) {
$files->add($file);
}
}
dump($files);
You took my slip of the tongue too literally, because you presented me again a working copy-and-paste solution.
The output of the image names does not show cover images anymore. I will still add additional filters, as sometimes the meta-image and other unneccessary images still shows up.
I am VERY satisfied and have learned something new! Thank you!