1. 论坛系统升级为Xenforo,欢迎大家测试!
    排除公告

为 WordPress 增加 RSS Reader 功能

本帖由 Function2007-01-12 发布。版面名称:源码讨论

  1. Function

    Function New Member

    注册:
    2006-03-24
    帖子:
    3,884
    赞:
    5
    留意到 WordPress 的后台默认会调用几个 RSS 地址,通过分析得知其使用了 MagpieRSS, 核心文件为 wp-includes/rss-functions.php 。我们增加链接的时候,可以同时提供 RSS 地址,那么我们完全可以通过这个 RSS 地址在我们的日志上直接阅读 RSS 内容。这里有一段理论性的代码,请参考后面的 get_list_of_rss() 函数。


    另外,MagpieRSS 只是 RSS 分析器,本身并不提供 RSS 发掘功能,在应用了该分析器的诸多开源程序中,注意到有 Gregarius, 一款很不错的 RSS 聚合程序。如果用过这套聚合程序,就知道在后台添加频道的时候,可以仅提供网址来自动发掘可用的 RSS 地址清单,所以利用这部分程序,我们在没有提供链接的 RSS 地址的情况下,也可以自动分析出 RSS 地址,然后调用 get_list_of_rss() 函数。MagpieRSS 中该部分代码在 util.php 中,主要是 getUrl() 和 extractFeeds() 两个函数。我将其放到 WordPress 下的 rss-functions.php 文件中使用。

    getUrl() 和 extractFeeds()

    PHP:
    /********************************************/
    /********************************************/
    /**
     * Fetches a remote URL and returns the content
     */
    function getUrl($url$maxlen 0) {
        
    //Bug: in windows, scheme returned by parse_url contains the drive letter
        //of the file so a test like !isset(scheme) does not work
        //maybe it would be better to only use is_file() which only detect
        //local files?
        
    $urlParts parse_url($url);
        if (@
    is_file($url) || (!isset($urlParts['scheme']) && !isset($urlParts['host'])) ) {
            
    //local file!
            
    $c "";
            
    $h = @fopen($url"r");
            if (
    $h) {
                while (!
    feof($h)) {
                    
    $c .= @fread($h8192);
                }
            }
            @
    fclose($h);
            return 
    $c;
        }

        
    $client = new Snoopy();
        
    $client->agent MAGPIE_USER_AGENT;
        
    $client->use_gzip MAGPIE_USE_GZIP;

        if (
    $maxlen) {
            
    $client->maxlength $maxlen;
        }
        @ 
    $client->fetch($url);
        return 
    $client->results;
    }

    /**
     * Feed Autodiscovery 
     * 
     * returns an array of all (hopefully) rss/atom/rdf feeds in the document,
     * pointed by $url. 
     * See http://diveintomark.org/archives/2002/06/02/important_change_to_the_link_tag
     *
     * @param string $url URL of a web document containing <link> elements
     * @return array Array of feed URLs
     */
    function extractFeeds($url) {
        
    $cnt getUrl($url);
        
    $ret = array ();
        
    //find all link tags
        
    if (preg_match_all('|<link\s+\w*=["\'][^"\']+["\']+[^>]*>|Uis'$cnt$res)) {
            while (list (
    $id$match) = each($res[0])) {
                
    // we only want '<link alternate=...'
                
    if (strpos(strtolower($match), 'alternate') &&
                        !
    strpos(strtolower($match), 'stylesheet')  && // extract the attributes
                        
    preg_match_all('|([a-zA-Z]*)=["\']([^"\']*)|'$match$res2PREG_SET_ORDER)) {
                    
    $tmp = array ();
                    
    //populate the return array: attr_name => attr_value
                    
    while (list ($id2$match2) = each($res2)) {
                        
    $attr strtolower(trim($match2[1]));
                        
    $val trim($match2[2]);
                        
    // make sure we have absolute URI's
                        
    if (($attr == "href") && strcasecmp(substr($val04), "http") != 0) {
                            
    // Check to see if the relative url starts with "//"
                            
    if(substr($val,0,2) == "//") {
                                
    $val preg_replace('/\/\/.*/'$val$url);
                            } else {
                                
    $urlParts parse_url($url);
                                if (
    $urlParts && is_array($urlParts) && strlen($val)) {
                                    if (
    $val[0] != '/') {
                                        
    $val '/'.$val;
                                    }
                                    
    $val $urlParts['scheme'] . '://'
                                           
    .$urlParts['host'] . $val;
                                } else {
                                    
    $val = ($url.$val);
                                }
                            }
                        }
                        
    $tmp[$attr] = $val;
                    }
                    
    $ret[] = $tmp;
                }
            }
        }
        return 
    $ret;
    }
    使用方式(显示列表)

    PHP:
    $url 'http://ulysses.cn/';
    $feeds extractFeeds($url);

    if (!
    is_array($feeds) || sizeof($feeds) == 0) {
    } else {
        
    //if (is_array($feeds) && sizeof($feeds) == 1 && array_key_exists('href',$feeds[0])) {
            //echo $feeds[0]['href'] . '<br />';
        //} else {
            
    $cnt 0;
            while(list(
    $id$feedarr) = each($feeds)) {
                
    // we need an URL
                
    if (!array_key_exists('href'$feedarr)) {
                    continue;
                } else {
                    
    $href $feedarr['href'];
                }

                if (
    array_key_exists('type'$feedarr)) {
                    
    $typeLbl " [<a href=\"$href\">" $feedarr['type'] . "</a>]";
                }

                
    $cnt++;

                if (
    array_key_exists('title'$feedarr)) {
                    
    $lbl $feedarr['title'];
                } elseif (
    array_key_exists('type'$feedarr)) {
                    
    $lbl $feedarr['type'];
                    
    $typeLbl "";
                } elseif (
    array_key_exists('href'$feedarr)) {
                    
    $lbl $feedarr['href'];
                } else {
                     
    $lbl "Resource $cnt";
                }

                echo 
    "<p>\n\t<input class=\"indent\" type=\"radio\" id=\"fd_$cnt\" name=\"new_channel\" "
                       
    ." value=\"$href\" />\n"
                       
    ."\t<label for=\"fd_$cnt\">$lbl $typeLbl</label>\n"
                       
    ."</p>\n";
            
    //}
        
    }
    }
    get_list_of_rss()

    PHP:
    function get_list_of_rss($link_id) {
        global $wpdb;

        $feed = $wpdb->get_row("SELECT link_name, link_url, link_description, link_updated, link_rss FROM `$wpdb->links` WHERE link_id = '$link_id'");

        if (!$feed) {
            return;
        } else {
            $link_rss = $feed->link_rss;
            $link_name = $feed->link_name;
            _e('<h2 class="pagetitle">' . $link_name . '</h2>');
        }

        $rss = @fetch_rss($link_rss);
        if ( isset($rss->items) && 0 != count($rss->items) ) {

            _e('<div class="post">');

            $rss->items = array_slice($rss->items, 0, count($rss->items));
            foreach ($rss->items as $item ) {
    ?>
            <h4><a href='<?php echo wp_filter_kses($item['link']); ?>'><?php echo wp_specialchars($item['title']); ?></a> — <?php printf(__('%s ago'), human_time_diff(strtotime($item['pubdate'], time() ) ) ); ?></h4>
            <p><?php echo $item['description']; ?></p>
    <?php
            
    }

            
    _e('</div>');
        }
    }
    使用

    PHP:
    $link_id = (int) $_GET['link_id'];

    get_list_of_rss($link_id);
    能力所限,这里用到的两部分代码,我并没有很好地将其结合在一起,有兴趣的可以考虑实现。

    ==============================
    原创文章:http://www.purewhite.cn/?p=78
    ==============================
     
  2. sluke

    sluke New Member

    注册:
    2005-09-04
    帖子:
    4,550
    赞:
    13
    技术帖~:lovely:
     
  3. fen

    fen New Member

    注册:
    2005-12-18
    帖子:
    3,050
    赞:
    25
    up! up!:eek:
     
  4. Function

    Function New Member

    注册:
    2006-03-24
    帖子:
    3,884
    赞:
    5
    补充说明一下:

    get_list_of_rss() 中的 SQL 语句读取字段较多,本来是想在显示列表的时候同时显示该链接的一些相关信息。

    PHP:
    $feed $wpdb->get_row("SELECT link_name, link_url, link_description, link_updated, link_rss FROM `$wpdb->links` WHERE link_id = '$link_id'");
     
  5. 蓝色的信封

    蓝色的信封 New Member

    注册:
    2006-10-07
    帖子:
    252
    赞:
    3
    虽然本人技术不行,但是很佩服自己发掘代码的人。:lovely: