getkirby/editor

Image Block (<figure>-Tag) references old Image-URL after URL/SLUG change of Page

Closed this issue ยท 9 comments

Describtion
If you have a page with an editor field. In which you have some Text Blocks and an Image Block. And you change the slug of the page. The figure tag still points to the image with the old slug -> which is of course not present. So the Image will not be displayed.

Reproduce

  1. Add an editor field and add some text and an Image to it
  2. Click on pageSettings/Chenge URL
  3. change the url
  4. view the page -> Image disappears.

Expected behavior
If I change the the URL/Slug of a page, I expect the Image in the editor field to link to the right URL

Kirby Version
Kirby 3.3.4
Editor 1.0.2

That's because the Editor stores the GUID of the image, e.g:

/pages/blog+my-article/files/the-file.png

When you change the slug, that my-article part is outdated and it no longer works.


Since the Editor image select allows you to select only files in the current page, couldn't it store just the filenames? That would solve the problem.

This is driving me crazy :-/ One of my clients calls me twice a week because their site is broken. Everytime I have to manually fix the image urls in the txt's. I don't want to tell them not to change their slugs, that would be like owning a car and to never touch the AC ๐Ÿค“

IMHO images shouldn't reference their path, only their filename. This is the usual paradigm when referencing images in templates outside of this editor.

As a workaround, this is my custom image snippet :

site/snippets/editor/image.php
<?php if ($block->isNotEmpty()): ?>

+ <?php
+  // Get the $image object via the $page as usual using its filename
+  $filename = basename($attrs->id());
+  if ($image = $page->image($filename)) : 
+ ?>

<figure<?= attr(['class' => $attrs->css()->value()], ' ') ?>>
  <?php if ($attrs->link()->isNotEmpty()): ?>
  <a href="<?= $attrs->link()->toUrl() ?>">
-  <img src="<?= $src ?>" alt="<?= $attrs->alt() ?>">
+  <img src="<?= $image->url() ?>" alt="<?= $attrs->alt() ?>">
  </a>
  <?php else: ?>
-  <img src="<?= $src ?>" alt="<?= $attrs->alt() ?>">
+  <img src="<?= $image->url() ?>" alt="<?= $attrs->alt() ?>">
  <?php endif ?>

  <?php if ($attrs->caption()->isNotEmpty()): ?>
  <figcaption>
    <?= $attrs->caption() ?>
  </figcaption>
  <?php endif ?>
</figure>

+ <?php endif ?>
<?php endif ?>

This may not work as intended so use it with caution.

IMHO images shouldn't reference their path, only their filename. This is the usual paradigm when referencing images in templates outside of this editor.

As a workaround, this is my re-implementation of the image snippet :

How did you overwrite the image snippet? Seems like you have to overwrite the image block with a differently named image block and disable the original image block using allowed in the blueprint. Not ideal, but changing the plugin files is not future-proof at all.

How did you overwrite the image snippet? Seems like you have to overwrite the image block with a differently named image block and disable the original image block using allowed in the blueprint. Not ideal, but changing the plugin files is not future-proof at all.

You dont have to change the plugin files, just create a custom snippet in site/snippets/editor/image.php.

I edited my previous comment to reflect that.

@arnaudjuracek Thanks for the link, I somehow didn't see this in the docs.

The workaround works flawlessly in the frontend.
It does not change the behaviour in the backend though:

image

I agree with @RobertCordes โ€” this issue is making the editor almost unusable for client projects. You don't even have to change the slug. My client simply duplicated a page. While the files are being copied over, the images are still pointing to the other page.

For now I solved this issue by manually editing the plugin as follow :

editor/lib/ImageBlock.php:18
public function image()
    {
        try {
-            return $this->kirby()->api()->parent($this->attrs()->guid()->value());
+            return $this->parent()->image(basename($this->attrs()->guid()->value()));
        } catch (Throwable $e) {
            return null;
        }

This is merely a hack, and may not be robust enough for specific applications or untested edge cases, thus I have decided not to create a PR for it.
I will however use this (plus the custom snippet mentioned above) in a production environment, and get back to this thread if further problems occur.

@arnaudjuracek Did the two changes solve the issue for you? It seems like a good solution.
I think Bastian is currently focused on 3.4 โ€” a PR would be great ๐Ÿ‘

EDIT: I'm blind ๐Ÿ‘† ๐Ÿคฆโ€โ™‚๏ธ

โœ