Yes, don’t use regex for parsing HTML but use DOM instead.
This is how I would work it out :
In your toolbox, a function to get innerDOM of a node :
// GET INNER HTML OF A NODE
function DOMinnerHTML($element)
{
$innerHTML = "";
$children = $element->childNodes;
foreach ($children as $child)
{
$tmp_dom = new DOMDocument();
$tmp_dom->appendChild($tmp_dom->importNode($child, true));
$innerHTML.=trim($tmp_dom->saveHTML());
}
return $innerHTML;
}
Then a filter to apply a custom function :
function change_destination_links_for_images( $content ) {
$dom = new DOMDocument();
// THIS IS HACK TO LOAD STRING WITH CORRECT ENCODING
// JUST OUTPUT <--?xml encoding="UTF-8"--> IN HTML SO NO HARM
$dom->loadHTML( '<?xml encoding="UTF-8">' . $content );
// GET ALL <a> NODE
foreach ( $dom->getElementsByTagName('a') as $node ) {
// GET HREF
$link_href = $node->getAttribute( 'href' );
// USE INNER OF THIS <a> NODE AS NEW DOC TO EXTRACT IMG
$dom_node = new DOMDocument();
$inner = DOMinnerHTML($node);
$dom_node->loadHTML($inner);
// CHECK IF IMAGE INSIDE THE LINK
if ( $dom_node->getElementsByTagName('img') {
// IF SO REPLACE HREF
$node->setAttribute('href', get_permalink() );
// RETURN MODIFIED DOM
$content = $dom->saveHTML();
}
}
// RETURN CONTENT
return $content;
}
// APPLY FILTER
add_filter( 'the_content', 'change_destination_links_for_images' );
This is a quick adaptation of a working job I have done for another purpose so it may have errors in it. Hope this helps.