Cover image + template switch breaks cover image

I have two almost identical templates built out of the starter kit.
album.yml and album.hero.yml they are identical except a few additional fields.

Cover field is a copy of starter kit. site/blueprints/fields/cover.yml

type: files
multiple: false
query: page.images.template('image')
uploads:
  template: image

Both templates have a reference “images” field for cover to reference.

          images:
            type: files
            layout: cards
            template: image
            info: "{{ file.dimensions }}"
            image:
              ratio: 5/4
              cover: true
            min: 1
            size: small

After initiating an album page with the album.yml template and then switching the template to a album.hero.yml template : the cover image breaks.

Cover is referenced in the content folder in both files:
album.txt and album.hero.txt

Cover: - 'file://M4WbrmDPUBYyHbRJ'

I’m struggling to debug this and figure out where the break is.

Additional : I forgot to add the pages models. These come straight out of the Starter Kit.

/models/album.php

class AlbumPage extends Page
{
    public function cover()
    {
        return $this->content()->get('cover')->toFile() ?? $this->image();
    }
}

and /models/album.hero.php

class AlbumHeroPage extends Page
{
    public function cover()
    {
        return $this->content()->get('cover')->toFile() ?? $this->image();
    }
}

What do you mean by “it breaks”?

Is the issue happening in the panel (you’re not seeing the fields you expect in the panel for that page, or a field shows an error message), or when rendering the page in a template, or both?

If it’s an issue when rendering the page in a template, can you check:

  • That the page object you’re working with is a AlbumHeroPage instance (var_dump($page) should show that).
  • What $this->content()->get('cover') and $this->content()->get('cover')->toPage() resolve to?

I will test. It breaks means that the the image no longer appears in indexes and front end.
No error, silently fails to appear. In backend lists or fronted writes.

Updates:

Using the cover() function in related template model fixes front end issues. The model above is correct. Currently only the cover query for panel image representation fails.

I don’t understand this part. It would be helpful if you post the complete blueprints.

Hi Texnixe,

Page template album =


title: Album

icon: 🖼
status:
  draft: true
  listed: true
  unlisted: true
options:
  changeTemplate:
    - album.image
    - album.hero
    - album.video
    - album
tabs:
  content:
    columns:
      - width: 2/3
        fields:
          cover: fields/cover
          headline:
            type: text
            placeholder: "{{ page.title }}"
            help: Leave empty to use the title as headline
          subheadline:
            type: text
          layout:
            label: layout
            type: layout
            layouts:
              - "1/1"
              - "1/2,1/2"
              - "1/3,1/3,1/3"
              - "1/4,1/4,1/4,1/4"
          text:
            type: writer
          tags: true
      - width: 1/3
        sections:
          content:
            type: fields
            fields:
              info:
                label: Info
                type: info
                text: |
                  This is the album page yml template
              color:
                type: color
                help: Theme colours are at the bottom of the picker -> red is default.
                default: "#ff4a4d"
                options:
                  - "#ff4a4d"
                  - "#dfb128"
                  - "#79b9e2"
                  - "#ec852b"
                  - "#a46f58"
                width: 1/2
          images:
            type: files
            layout: cards
            template: image
            info: "{{ file.dimensions }}"
            image:
              ratio: 5/4
              cover: true
            min: 1
            size: small

  seo: seo/page
  

and page template album.hero =

title: Album Hero

icon: 🖼
# image:
#   query: page.image.findBy("name", "cover")
#   cover: true
#   ratio: 1/1
#   back: black
status:
  draft: true
  listed: true
  unlisted: true

options:
  changeTemplate:
    - album.image
    - album.hero
    - album.video
    - album
tabs:
  content:
    columns:
      - width: 2/3
        fields:
          cover: fields/cover
          headline:
            type: text
            placeholder: "{{ page.title }}"
            help: Leave empty to use the title as headline
          subheadline:
            type: text
          layout:
            label: layout
            type: layout
            layouts:
              - "1/1"
              - "1/2,1/2"
              - "1/3,1/3,1/3"
              - "1/4,1/4,1/4,1/4"
          text:
            type: writer
          tags: true
      - width: 1/3
        sections:
          content:
            type: fields
            fields:
              info:
                label: Info
                type: info
                text: |
                  This is the album page yml template
              color:
                type: color
                help: Theme colours are at the bottom of the picker -> red is default.
                default: "#ff4a4d"
                options:
                  - "#ff4a4d"
                  - "#dfb128"
                  - "#79b9e2"
                  - "#ec852b"
                  - "#a46f58"
                width: 1/2
          hero:
            type: files
            label: HERO Image ⚡️
            help: Used in art directed areas. Page top or side.
            layout: list
            max: 1
            uploads:
              template: image
          images:
            type: files
            layout: cards
            template: image
            info: "{{ file.dimensions }}"
            image:
              ratio: 5/4
              cover: true
            min: 1
            size: small

  seo: seo/page
  
  

Pictured → “Unbecoming” uses the album.hero template. I have commented out the non working image query. If i switch template back to album.yml it previews.

Thanks

Is the parent blueprint still photography.yml and did you make any changes there or in the album section blueprint that is used there? If so, please post those blueprints.

image:
  query: page.image.findBy("name", "cover")

Hmm, page.image.findBy seems wrong.

  • $page->image() returns a Kirby\Cms\File object which doesn’t have a findBy method, or null.
  • $page->images() returns a Kirby\Cms\Files object, which does have a findBy method.

So you probably want:

image:
  query: page.images.findBy("name", "cover")

Provided that images actually have a name field to filter on. I think you can filter on filename, but not sure about name.

I had a similar use case in a site I built, where several page blueprints have a “cover image”, and I created:

  • a site/blueprints/files/cover.yml file blueprint
  • a reusable site/blueprints/sections/cover.yml defining a Files section, which lists files belonging to the page which have the 'cover' template, and assigns the 'cover' template to any file uploaded through that section

Then a page could define its preview image like this:

# in site/blueprints/pages/some-page-template.yml
image:
  query: "page.images.filterBy('template', 'cover').first"

In your case, it looks like you’re not using a Files section (which lists all child files of a page, optionally filtered), but a Files field (which saves data in the page’s text file, resulting in something like Cover: - file://some-uuid-number). So you would need a query that uses the value of that field:

# in site/blueprints/pages/some-page-template.yml
image:
  query: "page.content.get('cover').toFiles.first"

@texnixe If query: page.image.findBy("name", "cover") is faulty, I think this documentation page needs to be fixed, because it seems to comes from there:

This paragraph seems wrong too:

The (preview) image blueprint option defines how any page with this blueprint will be presented, e.g. in a files section.

It should be “any file with this blueprint”, not “any page with this blueprint”.

No, this is correct, provided you have an image with name ‘cover’, but for the current purpose, this does of course not make sense.

I think, however, the problem is somewhere else. The image to display for the section preview images here is most certainly defined in the section, and therefore it all depends what is defined in this section.

The icon prop can remain there as a fallback for cases when there is no image, so no need to define an image in the page blueprint in this case.

If all is left the same in the original parent blueprint, everything should work as expected. So I guess the issue here is changes made to the sections in the parent page.

I can see what you are getting to there as this is the page throwing an error.. Will do some tests there.

Thanks i’ll look into these.

Sorry, you are tight, I think I didn’t read this correctly. Something is wrong there, but wonder what it is supposed to be. findBy() cannot be used on page.image but only on page.images, so that is definitely wrong. But then again, that query in the context of a file blueprint doesn’t really make any sense either. For once, you don’t have access to page in this context. And hy would I want to display another image preview for a given image? :thinking:

While this is interesting and i will get into this later on…

image:
  query: page.images.findBy("name", "cover")

It’s not being used. And i shouldn’t need it…
I think there are issues with the photography.yml template as @texnixe has queried.

Photography.yml

title: Photos
icon: 🖼
tabs:
  content:
    columns:
      - width: 1/2
        sections:
          intro:
            type: fields
            label: Additional info for Indexicals
            fields:
              info:
                label: Info- I am the Photography page template
                type: info
                text: |
                  This is the photography page yml template
              intro:
                type: textarea
                label: Intro
                size: small
                help: This text will be shown on the index page.
      - width: 1/2
        sections:
          drafts:
            extends: sections/albums
            label: Drafts
            status: draft
          listed:
            extends: sections/albums
            label: Published Albums
            status: listed
  seo: seo/page

And sections/albums.yml

type: pages
label: Works
parent: kirby.page("works")
size: small
info: "{{ page.images.count }} image(s)"
layout: cards
template:
  - album
  - album.hero

# I'm assuming that referencing the .hero 
# catches the switched template.

empty: No albums yet
image:
  query: page.cover
  cover: true
  ratio: 5/4

# I'm assuming that image:
# should work as the query "should" be identical
# the image section is identical for both 
# [ album.yml , album.hero.yml ]. 🤔

Lets stick to this problem for a moment.

To rephrase the WHOLE Question.

WHY does

    #/pages/album.hero.yml
    cover: fields/cover

break / not appear in

extends: sections/albums

Should this be written as an array ?

extends: 
  - sections/albums
  - sections/albums.hero

Thankyou @texnixe and @fvsch .
@fvsch i will go over your # 13h : image:query statements later.
They are interesting.

Happy Easter :rabbit:

I tried to copy your blueprints as posted here into my starterkit and it is all working fine. Maybe you can provide a download link of your project via PM (using dropbox or a similar service), and I’ll take a look, it’s getting a bit messy here.

image:
  query: page.cover
  cover: true
  ratio: 5/4

My understanding from the blueprints you posted is that the query page.cover is equivalent to the PHP $page->cover(), which will return a Kirby\Content\Field object, not a file object.

This field would look like this in the .txt file for the page:

Cover:
- file://some-uuid

Which is a YAML value containing a list of 1 string (file://some-uuid). You can transform that value to a file object with the toFiles() method, and probably need to pick the first one from the resulting collection:

image:
  query: 'page.cover.toFiles.first'
  cover: true
  ratio: 5/4

No, because the cover method in the Album/AlbumHero page model (see first post) returns a file object (or null, if no image exists).

This is all similar to how it is in the Starterkit, with the difference of a changed page name and more templates/blueprints to choose from. I guess there is a small mistake somewhere, but hard to spot with just the bits and pieces.

I’m assuming the cover method is still present in the AlbumHeroPage model as shown in the first post, otherwise that would explain the missing image.

I’ve changed the text and example and added an explanation regarding the query option in this context. However, @oyster did not use the image option in a files blueprint but in a page blueprint, so this example has nothing to do with the usage here.

There is, however, also an image property in a page blueprint, the docs are here: Page blueprint | Kirby CMS. With this option, you define how a page is previewed in a pages section or field.

But this setting is overwritten, when the pages section contains its own image query.

1 Like