将指向附件的正则表达式链接替换为指向文件的链接

时间:2012-07-27 作者:Simon

我试着自己做,但我真的很难用Regex(Regex是地狱,我只是不明白)。

无论如何,我认为这对一些人来说是有用的。上下文是我们使用插件在灯箱中显示post中的图像。只有当我们创建指向文件(图像)的链接而不是附件页时,它才起作用。

大多数时候,作者忘记了检查,灯箱没有弹出,每个人都很失望。

错误的HTML(请注意href 而且href 不会以结束。jpg):

 <p>
   <a href="http://domain.ru/uncategorized/208/e-poha-restavratsii/attachment/cyril_gassiline_photo" rel="attachment wp-att-209"><img class="alignnone size-large wp-image-209" title="cyril_gassiline_photo" src="http://domain.ru/wp-content/uploads/2012/07/cyril_gassiline_photo-615x409.jpg" alt="" width="615" height="409" /></a>
 </p>
所以我想我们可以这样做(在逻辑上):

function remove_bad_img_links($content) {
$matches = array();
$check_for_attachment_word = preg_match(\'/<a[\\s]+[^>]*href\\s*=\\s*(attachment)([\\"\\\']+)([^>]+?)(\\1|>)/i\', $content, $matches);
if ( $check_for_attachment ) {

       $image_url = preg_match(\'/<img[\\s]+[^>]*src\\s*=\\s*([\\"\\\']+)([^>]+?)(\\1|>)/i\', $content, $matches);

       preg_replace(\'/<a[\\s]+[^>]*href\\s*=\\s*(attachment)([\\"\\\']+)([^>]+?)(\\1|>)/i\', $content, $image_url);
     }
return $content;
}
add_filter( \'the_content\', \'remove_bad_img_links\' );
(我知道代码是错的,^^,我真的一点也不懂regex)

生成更正的HTML(中的值img src 已重新放置a href 这被检测为错误,因为它包含单词attachment(简单地一直这样做):

 <p>
   <a href="http://domain.ru/wp-content/uploads/2012/07/cyril_gassiline_photo-615x409.jpg" rel="attachment wp-att-209"><img class="alignnone size-large wp-image-209" title="cyril_gassiline_photo" src="http://domain.ru/wp-content/uploads/2012/07/cyril_gassiline_photo-615x409.jpg" alt="" width="615" height="409" /></a>
 </p>
但在写这篇文章时,我问自己,考虑到一篇文章可能会出现多次这样的链接,这是否真的有可能。。。

只是询问参考:是否可能,这是一个好主意,正则表达式是什么样子的?

我可以在JS中完成,但最好是在生成的代码中进行SEO。

编辑:

更多的研究告诉我“你不应该使用正则表达式来解析HTML”。更好的方法是使用DOM:https://stackoverflow.com/questions/3820666/grabbing-the-href-attribute-of-an-a-element

确切地说,我认为这是错误的,解析HTML非常糟糕:http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html. 我将尝试使用DOM,并会回来更新。

1 个回复
最合适的回答,由SO网友:Simon 整理而成

因此,我已经完成了一种方法来替换图像附件页面的链接,并将其替换为img 标记,但指向图像文件的大版本。

我没有使用regex,因为它是邪恶的,我不想让小猫死。

这对我来说很有用,所以我将其作为一个起点分享给那些想做同样事情的人(以及更多有才华的人可能做出的改进或纠正):

首先,我使用一个函数从文件的URL获取文件的ID(我在这里获取它:Turn a URL into an Attachment / Post ID)

// TOOL
// GET ATTACHMENT ID FROM GUID
function get_attachment_id( $url ) {

    $dir = wp_upload_dir();
    $dir = trailingslashit($dir[\'baseurl\']);

    if( false === strpos( $url, $dir ) )
        return false;

    $file = basename($url);

    $query = array(
        \'post_type\' => \'attachment\',
        \'fields\' => \'ids\',
        \'meta_query\' => array(
            array(
                \'value\' => $file,
                \'compare\' => \'LIKE\',
            )
        )
    );

    $query[\'meta_query\'][0][\'key\'] = \'_wp_attached_file\';
    $ids = get_posts( $query );

    foreach( $ids as $id )
        if( $url == array_shift( wp_get_attachment_image_src($id, \'full\') ) )
            return $id;

    $query[\'meta_query\'][0][\'key\'] = \'_wp_attachment_metadata\';
    $ids = get_posts( $query );

    foreach( $ids as $id ) {

        $meta = wp_get_attachment_metadata($id);

        foreach( $meta[\'sizes\'] as $size => $values )
            if( $values[\'file\'] == $file && $url == array_shift( wp_get_attachment_image_src($id, $size) ) ) {

                return $id;
            }
    }

    return false;
}
然后,我使用此函数返回<a> 我将找到的节点(在此处找到https://stackoverflow.com/questions/2087103/innerhtml-in-phps-domdocument ) :

// 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; 
} 
现在,将作为过滤器添加到的实际函数the_content :

function remove_bad_img_links($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);
            // EXTRACT IMG AND GET SRC OF IT
            // ASSUMING THERE IS ONLY ONE IMAGE ...
        foreach ( $dom_node->getElementsByTagName(\'img\') as $img_node ) {
            $img_node_link = $img_node->getAttribute( \'src\' );
        }
            // CHECK IF THE WORD attachment IS IN HREF
        preg_match(\'/attachment/\', $link_href, $matches);
            // IF SO...
        if ( $matches ) {
                    // GET ID OF THE IMAGE VIA CUSTOM FUNCTION
            $img_id = get_attachment_id( $img_node_link );
                    // GET ARRAY OF THE IMAGE VIA BUILTIN FUNCTION
            $img_array = wp_get_attachment_image_src( $img_id, \'large\' );
                    // REPLACE HREF WITH NEW SOURCE
                    if ( ! empty ( $img_id ) ) {
            $node->setAttribute(\'href\', $img_array[0] );
                    } else {
                    // FALLBACK IF CUSTOM FUNCTION DONT RETURN URL
            $node->setAttribute(\'href\', $img_node_link );
                    }
        }
    // RETURN MODIFIED DOM
    if ( $matches ) $content = $dom->saveHTML();
    }
    // RETURN CONTENT
    return $content;
}
// APPLY FILTER
add_filter( \'the_content\', \'remove_bad_img_links\' );
我在没有图片的帖子上进行了测试,测试了几个图片,目前没有任何问题。所有图像都具有正确的href 目的地,如果可能href 指向文件的大版本。

结束

相关推荐

从帖子内容中提取信息(使用regex?)

在保存帖子之前,我正在尝试替换内容中的一些自定义字符串。我得到了$data[“post\\u content”],其中包括像%replaceContent:{type}这样的字符串。现在我需要提取该字符串,读取{type},然后根据{type}的内部内容替换该字符串。我想这最好用regex来完成,不幸的是我真的不知道该怎么做。想法?