WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.39k stars 4.15k forks source link

FSE - post-content is empty when used in attachment template #29887

Open Sandstromer opened 3 years ago

Sandstromer commented 3 years ago

Description

When using the <!-- wp:post-content /--> block in the attachment.html template, the post content - in this case the media/image - is rendered empty on frontend.

Step-by-step reproduction instructions

In a FSE theme, create an attachment.html template containing the following blocks;

<!-- wp:post-title /-->
<!-- wp:post-author /-->
<!-- wp:post-date /-->
<!-- wp:post-content /-->

Expected behaviour

The <!-- wp:post-content /--> block should render the single media attachment.

Actual behaviour

The <!-- wp:post-content /--> block is empty.

The same block placed in the single.html template does display the single media attachment correctly, but not in the attachment.html template.

Screenshots or screen recording (optional)

Code snippet (optional)

WordPress information

Device information

bobbingwide commented 3 years ago

In my thisis theme I created an attachment template. I found that the post-content block didn't display the attachment. I made a temporary change to the Description adding the permalink for the image into it. This then displayed the image. I believe this was due to autoembed logic.

But it wasn't what I wanted. I wanted to be able to display the full size image followed by the other fields.

I had hoped that post-featured-image would have done the job. But that would only be any good for an image. It would appear to me that there should be a new block to display the attached file.

In my template the solution is to use a template part called attachment image, so that I can use one of my shortcodes.

<!-- wp:post-title {"level": 1 } /-->
<!-- wp:html -->
<div class="featured">
[bw_field featured]
</div>
<!-- /wp:html -->

<!-- wp:html -->
[bw_fields file_size ]
[bw_fields dimensions ]
<!-- /wp:html -->

featured, file_size and dimensions are all virtual fields. The shortcode knows it's an attachment so uses the correct post ID to obtain the file information.

In my opinion post-content shouldn't display the attached file unless it's instructed to. There should be a separate block.

carolinan commented 3 years ago

If there is no attachment template, attachments still needs to work, so if this was a separate block, that block would have to be added to all templates that are after the attachment template in the template hierarchy.

bobbingwide commented 3 years ago

Well that's a surprise. With Gutenberg 10.5, I tried viewing an attachment using my Fizzie theme, which doesn't have attachment.html but does have single.html. I discovered that when the attached image has a non-empty description then the post-content block displays the image and the text.

Then I tested on my live site, with 10.4.0 and discovered that the results are different. The image is always displayed.

Attachment has description? Gutenberg version View attachment using single.html
Y 10.4.1 Displays image and description
Y 10.5.2 Displays image and description
N 10.4.1 Displays image
N 10.5.2 No image displayed

The results I got for post-content when using the attachment.html template are:

Attachment has description? Gutenberg version View attachment using attachment.html
Y 10.4.1 No image displayed. Just the description text
Y 10.5.2 No image displayed. Just the description text
N 10.4.1 No image. Empty description - See below
N 10.5.2 No image. No div for the descrption
<div class="entry-content wp-block-post-content"></div>

My interpretation of these results is that there should be a separate block to display the attached file, primarily for use on the Media related templates.

BTW. I haven't looked at the post-content rendering code.

carolinan commented 3 years ago

It can't be a separate block. Attachments are not displayed in the editor in this form. They are displayed as an embed (like with pdf), file block, or for example a gallery.

What happened between 10.4 and 10.5 is that the block does not output anything if there is no content. This was to avoid an empty HTML wrapper to be output.

justintadlock commented 3 years ago

The template loader in core removes the prepend_attachment filter on the_content when an attachment is present. It expects that, because the theme is handling the attachment* template, it is outputting the media.

Ideally, the Post Featured Image block would handle this for image attachments. We could always let the prepend_attachment filter run and let theme authors unhook it if needed.

Long term, we need more attachment/media blocks or to somehow repurpose those we already have to pull media from the Post ID.

aristath commented 3 years ago

I'll say this and then run as fast as I can... (personal opinion) Templates for attachments never should have existed. The fact that they exist is a mishap, and ideally, they will be removed/deprecated :runner: :runner: :runner:

justintadlock commented 3 years ago

I'll say this and then run as fast as I can... (personal opinion) Templates for attachments never should have existed. The fact that they exist is a mishap, and ideally, they will be removed/deprecated 🏃 🏃 🏃

Start running. Running fast. :)

I think one of the primary use cases, especially early on, was to build sites with WordPress that behaved similarly to Coppermine Gallery. I don't think it's updated anymore, but it was a pretty successful photo gallery CMS way back when. There was a good several-year stretch where every other blog/site I visited used it.

Anyway, I have several theme users who rely heavily on attachment pages for similar photo gallery sites. There are more than you'd believe. Honestly, I may have them all because I am one of the few theme authors who actually works on attachment pages. :) You could say I've maintained a loyal user base of folks looking for that functionality.

I've managed to get this working with a filter on the_content for my block theme. My work thus far:

attachments-block-theme

I still need to add in navigation, but it'd be nice to see some attachment-related blocks for prev/next image links, back to parent post link, and displaying media metadata. I doubt the last item will ever happen -- I've been maintaining a script for doing it all these years because core has never addressed it.

carolinan commented 3 years ago

I've managed to get this working with a filter on the_content for my block theme.

I think the solutions I tried in the PR is unnecessary complicated, but I ran into so many (for me) unexpected scenarios. Any feedback? https://github.com/WordPress/gutenberg/pull/29927#issuecomment-831283586

justintadlock commented 3 years ago

I've managed to get this working with a filter on the_content for my block theme.

I think the solutions I tried in the PR is unnecessary complicated, but I ran into so many (for me) unexpected scenarios. Any feedback? #29927 (comment)

A couple of notes:

  1. I would check against 'attachement' === $post->post_type.

  2. And, check if viewing the specific attachment page via is_attachment( $post->ID ) (we don't know what other attachment posts might be showing on a page via some other query).

$post = get_post( $block->context['postId'] );

if ( 'attachment' === $post->post_type && is_attachment( $post->ID ) ) {
    // prepend media to content.
}

I pushed the code to my repo so you could see what I'm doing (everything is unpolished, but is working). It's more that what we should do for core, but the general idea is there.

Filter: https://github.com/justintadlock/exhale/blob/6f87e55576e6fded003f3677b7ee7d0dcb3d9a07/app/functions-filters.php#L234-L280

Before attachment post content: https://github.com/justintadlock/exhale/blob/6f87e55576e6fded003f3677b7ee7d0dcb3d9a07/block-template-parts-php/attachment-image-media.php

After attachment post content: https://github.com/justintadlock/exhale/blob/6f87e55576e6fded003f3677b7ee7d0dcb3d9a07/block-template-parts-php/attachment-image-meta.php

kathrynwp commented 2 years ago

This was also reported by a user unable to create a custom attachment page in https://wordpress.org/support/topic/template-attachments/

jordesign commented 1 year ago

Whilst #39353 allows new attachment templates to be added - it seems it doesn't affect the original issue reported here.

colorful-tones commented 1 year ago

Whilst https://github.com/WordPress/gutenberg/pull/39353 allows new attachment templates to be added - it seems it doesn't affect the original issue reported here.

Correct, attachment was at first a part of https://github.com/WordPress/gutenberg/pull/39353 , but then it was removed before being merged:

Agreed, we should exclude Media / Attachment for now.

https://github.com/WordPress/gutenberg/pull/39353#issuecomment-1066118889

and then:

Done in https://github.com/WordPress/gutenberg/commit/9ec45b6504da944e9df736ea717eaf63e6c025d6

So, there is more work to be done here. 👍

https://github.com/WordPress/gutenberg/pull/39353#issuecomment-1066570760

colorful-tones commented 1 year ago

For what it is worth - the single.html seems to be the next best thing in template hierarchy as a work around (for the time being).

justintadlock commented 1 year ago

I have a solution that I've been using more recently (what I posted above was from a while back).

This solution looks for PHP-based attachment "template partials" in the /public/partials folder with the name of attachment-media-{$type}.php filename in a theme to handle the necessary dynamic data. Of course, these can be renamed.

It does this by filtering render_block and overwriting the core/post-content block on single attachment views.

Here's the PHP filter your need:

<?php 
add_filter( 'render_block', function( $block_content, $block, $instance ) {
    // Bail early if not post content block or there's no post ID.
    if ( 'core/post-content' !== $block['blockName'] || empty( $instance->context['postId'] ) ) {
        return $block_content;
    }

    // Get the post object.
    $post = get_post( $instance->context['postId'] );

    // Bail if we're not specifically viewing the attachment page
    // for this specific post.
    if ( 'attachment' !== $post->post_type || ! is_attachment( $post->ID ) ) {
        return $block_content;
    }

    // Set up some default variables.
    $filename = 'file';
    $html     = '';

    // Checks if the attachment is one of supported types and sets
    // the filename based on that type.
    foreach ( [ 'image', 'video', 'audio'] as $type ) {
        if ( wp_attachment_is( $type, $post ) ) {
            $filename = $type;
            break;
        }
    }

    // Gets a partial (essentially a dynamic pattern) based on the
    // attachment type. Must be valid block content.
    ob_start();
    include get_parent_theme_file_path( "public/partials/attachment-media-{$filename}.php" );
    $media = ob_get_clean();

    // Parse and render the blocks.
    foreach ( parse_blocks( $media ) as $media_block ) {
        $html .= render_block( $media_block );
    }

    return $html . $block_content;
}, 10, 3 );

Here are some example PHP template partials for various media types: https://github.com/x3p0-dev/x3p0-ideas/tree/907512a942081e4251ba55f1f975012c331bfc2d/public/partials

Note that these partials must return valid block markup.

There are many ways to go about this, but I like this method of creating template partials.

colorful-tones commented 1 year ago

That is quite helpful. Thanks for sharing @justintadlock 👍