1

For design/functionality reasons, I would like to change the output of the core/image block on the frontend. I know could do it like this, but it a little bit heavy:

PHP:

// add my own render function for the core/image-block
register_block_type( 'core/image', [
    'render_callback' => 'myCustomImageOutput'
] );

function myCustomImageOutput( $attributes, $content ) {
    // thankfully, the ID is saved in $attributes
    $id = $attributes[ 'id' ];

    // all the other information is saved in $content as HTML
    // so one possible solution would be to parse it with DomDocument
    // and get all the values
    $dom = new DomDocument();

    // create custom image html

    // return custom image html
    return $customImageHtml;
}

Is there a better way to get all attributes?

  • Is this working for you? Did you ever find a better solution? I'd like to see your final working example. – RiddleMeThis Jan 18 at 14:07
  • @RiddleMeThis: Added an answer below – uruk Jan 19 at 16:49
1

As an answer to @RiddleMeThis, here is a working solution by parsing the default output from the core/image-Block with DOMDocument:

In the init-Hook, register your custom output function:

register_block_type( 'core/image', [
    'render_callback' => 'myImageOutput'
] );

Define your custom output function:

In this function render the default output ($content) which is passed as the second argument. Sadly, the first argument (being the block's $attributes) lacks the required information (except the attachment's ID and the link's destination).

function myImageOutput( $attributes, $content ) {
    // $content contains e.g.
    // <!-- wp:image {"id":123,"linkDestination":"custom"} -->
    // <figure class="wp-block-image"><a href="https://www.example.com"><img src="path/to/my/image.jpg" alt="Alternative text here" class="wp-image-123"/></a><figcaption>Caption goes here</figcaption></figure>
    // <!-- /wp:image -->

    // prepare array for all info. Note: alignment and customized 
    // size are ignored here since it was not required in this case
    $info = [
        'title' => '',
        'imagUrl' => '',
        'blank' => FALSE,
        'url' => '',
        'caption' => '',
    ];

    // Fortunately, the attachment id is saved in $attributes, so 
    // we can get the image's url
    $infos[ 'imageUrl' ] = wp_get_attachment_image_src( $attributes[ 'id' ], 'your-size' )[ 0 ];

    // we get the remaining info by loading the html via DOMDocument
    libxml_use_internal_errors( TRUE );
    $dom = new DOMDocument();
    $dom->preserveWhiteSpace = FALSE;
    $dom->loadHtml( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ) );

    // get the figure element       
    $figure = $dom->getElementsByTagName( 'figure' )[ 0 ];

    // alternatively, get the image title or description etc. 
    // by querying it from the database
    $infos[ 'title' ] = $figure->getElementsByTagName( 'img' )[ 0 ]->getAttribute( 'alt' );

    // if we have a custom url on the image
    if ( isset( $attributes[ 'linkDestination' ] ) && $attributes[ 'linkDestination' ] == 'custom' ) {
        $a = $figure->getElementsByTagName( 'a' )[ 0 ];
        $infos[ 'url' ] = $a->getAttribute( 'href' );
        $infos[ 'blank' ] = strpos( $infos[ 'url' ], get_home_url() ) !== 0;
    }

    // caption, also see https://stackoverflow.com/a/2087136/1107529
    // because the caption can contain html
    $figCaption = $figure->getElementsByTagName( 'figcaption' );
    if ( count( $figCaption ) ) {
        $caption = '';
        foreach ( $figCaption[ 0 ]->childNodes as $child ) {
            $caption .= $dom->saveHTML( $child );
        }
        $infos[ 'caption' ] = $caption;
    }

    // create your custom html output here. In my case, I passed the 
    // info to a vue component
    $html = sprintf( '<my-custom-vue-component :info="%s"></my-custom-vue-component>', 
                esc_attr( json_encode( $info ) ) );

    return $html;
}

This solutions works for me. I am sure, there will be a better way to do this one day, possibly when the gutenberg ecosystem gets more mature. But for the moments, it works without problems.

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.