Site logo

Archived topic

How to link certain Posts to uploaded file?

11 replies · Started by William on April 7, 2023

Viewing posts 1–12 of 12

I've added a file upload field using ACF Pro for Posts. We have Generate Blocks Pro installed

Client wants to mix content, so a GB query loop shows the Post Title, Post Date, and Post Excerpt

Some posts will be for content entered into the editor... many posts however will just be links to a PDF.

They would like the Post Title to link to the uploaded PDF (if it exists), otherwise link to the normal post content.

Is this possible?

Many thanks in advance!

Hi William,

There isn't a built-in function which can achieve this, however, you can use this filter and something like this.

1. Add an additional CSS class to the headline block (title) in the query loop, eg.title-download-link.

2. Add below code, switch pdf with your custom field slug.

add_filter('generateblocks_dynamic_url_output', function($url, $attributes) {
    if (!empty($attributes['className']) && strpos($attributes['className'], 'title-download-link') !== false) {
        $download_file = get_field("pdf");
        if ($download_file) {
            $url = $download_file;
        }
    }
    return $url;
}, 10, 2);

I assume this would be a function, with a check to see if( get_field('post_pdf') ): isset and !empty then link post title to file, else link to post?

I'm surprised I can't find a plugin for this, I can't be the first to need a Post to link to a file instead of Post content, right?

Please check my previous reply :)

Thank you very much for the help and quick reply!

I don't need to use GB, in fact I'd love for this to be site-wide functionality, for any Post if a file was uploaded (ACF field = post_pdf) then link to that file instead of the normal post content... but if no file was uploaded, then link to the normal post content.

Does that help/ make sense?

Hi there,

so anywhere theres a link to a Post, if that post has an ACF Field of X then the link should be replaced with a Download ?

Is that correct ?

David, yes, but only link to the file (ACF field = post_pdf) if the file exists for that Post, else the link should go to the regular Post content.

I'm saying this because this ACF field is now available for any/ all Posts.

I assume this would be a function (in functions.php), with a check to see if( get_field('post_pdf') ): isset and !empty then link post title to file, else link to post?

Many thanks for any and all help, it's greatly appreciated!

-Will

This will be out of scope as it's not a theme specific request.

However, you can give this code a try:

add_filter('the_content', 'replace_links_with_meta_value');

function replace_links_with_meta_value($content) {
    $post_id = get_the_ID();
    $dom = new DOMDocument();
    @$dom->loadHTML($content);

    $anchors = $dom->getElementsByTagName('a');
    foreach ($anchors as $anchor) {
        $href = $anchor->getAttribute('href');
        if (strpos($href, home_url()) === false) {
            continue;
        }

        $post_id = url_to_postid($href);
        if (!$post_id) {
            continue;
        }

        $meta_value = get_field('post_pdf', $post_id);
        if ($meta_value) {
            $anchor->setAttribute('href', $meta_value);
        }
    }

    return $dom->saveHTML();
}

Ying, thank you very much for this function!

Unfortunately it is throwing an error: There has been a critical error on this website.

When debugging it says: Fatal error: Uncaught Error: DOMDocument::loadHTML(): Argument #1 ($source) must not be empty

I think I fixed the error by adding lines 6-9:

// Link Posts Titles to uploaded file, if exists, ACF field = post_pdf
add_filter('the_content', 'replace_links_with_meta_value', 100, 3 );
function replace_links_with_meta_value($content) {
    $post_id = get_the_ID();
	
    // Bail if there is no content to work with.
    if ( ! $content ) {
        return $content;
    }
	
    $dom = new DOMDocument();
    @$dom->loadHTML($content);

    $anchors = $dom->getElementsByTagName('a');
    foreach ($anchors as $anchor) {
        $href = $anchor->getAttribute('href');
        if (strpos($href, home_url()) === false) {
            continue;
        }

        $post_id = url_to_postid($href);
        if (!$post_id) {
            continue;
        }

        $meta_value = get_field('post_pdf', $post_id);
        if ($meta_value) {
            $anchor->setAttribute('href', $meta_value);
        }
    }

    return $dom->saveHTML();
}

Nice, glad you got it to work :)

In case anyone else needs this... slight update as DOMDocument loadHTML was not encoding UTF-8 correctly. Also added attributes to open the link in a new window and adding a class for 'pdf'.

// Link Posts Titles to uploaded file, if exists, ACF field = post_pdf
add_filter('the_content', 'replace_links_with_meta_value', 100, 3 );
function replace_links_with_meta_value($content) {
    $post_id = get_the_ID();
	
    // Bail if there is no content to work with.
    if ( ! $content ) {
        return $content;
    }
	
    $dom = new DOMDocument();
    @$dom->loadHTML('<?xml encoding="utf-8" ?>' . $content);

    $anchors = $dom->getElementsByTagName('a');
    foreach ($anchors as $anchor) {
        $href = $anchor->getAttribute('href');
        if (strpos($href, home_url()) === false) {
            continue;
        }

        $post_id = url_to_postid($href);
        if (!$post_id) {
            continue;
        }

        $meta_value = get_field('post_pdf', $post_id);
        if ($meta_value) {
            $anchor->setAttribute('href', $meta_value);
			$anchor->setAttribute('target', '_blank');
			$anchor->setAttribute('class', 'pdf');
        }
    }

    return $dom->saveHTML();
}
This archived topic is closed to new replies.