Esempio n. 1
0
/**
 * Refresh the specified feeds and returns an array with URLs in error
 *
 * @param $feeds should be an array of associative arrays ('id', 'url', 'post'} as values. post is a JSON array of post parameters to send with the URL.
 * @param $update_feeds_infos should be true to update the feed infos from values in the RSS / ATOM
 * @todo assert(false)
 */
function refresh_feeds($feeds, $check_favicons = false, $verbose = true)
{
    global $dbh, $config;
    // TODO: Import tag from feeds
    // Download the feeds
    $download = curl_downloader($feeds, true, $verbose);
    $errors = array();
    $favicons_to_check = array();
    foreach ($download['status_codes'] as $url => $status_code) {
        // Keep the errors to return them and display them to the user
        if ($status_code != 200) {
            $errors[] = array('url' => $url, 'msg' => 'Feed page not found (http status: ' . $status_code . ')');
            unset($download['results'][$url]);
        } elseif (!startswith($download['content_types'][$url], 'application/xml') && !startswith($download['content_types'][$url], 'text/xml') && !startswith($download['content_types'][$url], 'application/rss+xml') && !startswith($download['content_types'][$url], 'application/atom+xml')) {
            $errors[] = array('url' => $url, 'msg' => 'Unable to find a feed at the address ' . $url);
            unset($download['results'][$url]);
        }
    }
    $updated_feeds = $download['results'];
    // Put everything in a transaction to make it faster
    $dbh->beginTransaction();
    // Delete old tags which were not user added
    delete_auto_added_tags();
    // Query to update feeds table with latest infos in the RSS / ATOM
    $query_feeds = $dbh->prepare('UPDATE feeds SET title=(CASE WHEN has_user_title=1 THEN title ELSE :title END), links=:links, description=:description, ttl=(CASE WHEN has_user_ttl=1 THEN ttl ELSE :ttl END), image=:image WHERE url=:old_url');
    $query_feeds->bindParam(':title', $feed_title);
    $query_feeds->bindParam(':links', $feed_links);
    $query_feeds->bindParam(':description', $feed_description);
    $query_feeds->bindParam(':ttl', $feed_ttl, PDO::PARAM_INT);
    $query_feeds->bindParam(':image', $image);
    $query_feeds->bindParam(':old_url', $url);
    // Two queries, to upsert (update OR insert) entries : update the existing entry and insert a new one if the update errorred
    $query_entries = $dbh->prepare('UPDATE entries SET authors=:authors, title=:title, links=:links, description=:description, content=:content, enclosures=:enclosures, comments=:comments, pubDate=:pubDate, lastUpdate=:lastUpdate WHERE guid=:guid');
    $query_entries->bindParam(':authors', $authors);
    $query_entries->bindParam(':title', $title);
    $query_entries->bindParam(':links', $links);
    $query_entries->bindParam(':description', $description);
    $query_entries->bindParam(':content', $content);
    $query_entries->bindParam(':enclosures', $enclosures);
    $query_entries->bindParam(':comments', $comments);
    $query_entries->bindParam(':guid', $guid);
    $query_entries->bindParam(':pubDate', $pubDate, PDO::PARAM_INT);
    $query_entries->bindParam(':lastUpdate', $last_update, PDO::PARAM_INT);
    $query_entries_fail = $dbh->prepare('INSERT INTO entries(feed_id, authors, title, links, description, content, enclosures, comments, pubDate, lastUpdate, guid) VALUES(:feed_id, :authors, :title, :links, :description, :content, :enclosures, :comments, :pubDate, :lastUpdate, :guid)');
    $query_entries_fail->bindParam(':feed_id', $feed_id);
    $query_entries_fail->bindParam(':authors', $authors);
    $query_entries_fail->bindParam(':title', $title);
    $query_entries_fail->bindParam(':links', $links);
    $query_entries_fail->bindParam(':description', $description);
    $query_entries_fail->bindParam(':content', $content);
    $query_entries_fail->bindParam(':enclosures', $enclosures);
    $query_entries_fail->bindParam(':comments', $comments);
    $query_entries_fail->bindParam(':guid', $guid);
    $query_entries_fail->bindParam(':pubDate', $pubDate, PDO::PARAM_INT);
    $query_entries_fail->bindParam(':lastUpdate', $last_update, PDO::PARAM_INT);
    // Query to insert tags if not already existing
    $query_insert_tag = $dbh->prepare('INSERT OR IGNORE INTO tags(name) VALUES(:name)');
    $query_insert_tag->bindParam(':name', $tag_name);
    // Register the tags of the feed
    $query_feeds_tags = $dbh->prepare('INSERT OR IGNORE INTO tags_feeds(tag_id, feed_id, auto_added_tag) VALUES((SELECT id FROM tags WHERE name=:name), :feed_id, 1)');
    $query_feeds_tags->bindParam(':name', $tag_name);
    $query_feeds_tags->bindParam(':feed_id', $feed_id);
    // Finally, query to register the tags of the entry
    $query_tags = $dbh->prepare('INSERT OR IGNORE INTO tags_entries(tag_id, entry_id, auto_added_tag) VALUES((SELECT id FROM tags WHERE name=:name), (SELECT id FROM entries WHERE guid=:entry_guid), 1)');
    $query_tags->bindParam(':name', $tag_name);
    $query_tags->bindParam(':entry_guid', $guid);
    foreach ($updated_feeds as $url => $feed) {
        $array_feed_id = multiarray_search_key('url', $url, $feeds);
        if ($feed_id === -1) {
            assert(false);
            // TODO
            exit;
        }
        $feed_id = $feeds[$array_feed_id]['id'];
        // Parse feed
        $parsed = @feed2array($feed);
        // If an error has occurred, keep a trace of it
        if ($parsed === false || empty($parsed['infos']) || empty($parsed['items'])) {
            $errors[] = array('url' => $url, 'msg' => 'Unable to parse feed file');
            continue;
        }
        // Define feed params
        $feed_title = isset($parsed['infos']['title']) ? $parsed['infos']['title'] : '';
        $feed_links = isset($parsed['infos']['links']) ? json_encode(multiarray_filter('rel', 'self', $parsed['infos']['links'])) : '';
        $feed_description = isset($parsed['infos']['description']) ? $parsed['infos']['description'] : '';
        $feed_ttl = isset($parsed['infos']['ttl']) ? $parsed['infos']['ttl'] : 0;
        $feed_image = isset($parsed['infos']['image']) ? json_encode($parsed['infos']['image']) : '';
        if ($check_favicons && empty($feed_image)) {
            $favicons_to_check[] = array('url' => $url);
        }
        $query_feeds->execute();
        // Feeds tags
        if ($feeds[$array_feed_id]['import_tags_from_feed']) {
            if (!empty($parsed['infos']['categories'])) {
                foreach ($parsed['infos']['categories'] as $tag_name) {
                    // Create tags if needed, get their id and add bind the articles to these tags
                    $query_insert_tag->execute();
                    $query_feeds_tags->execute();
                }
            }
        }
        // Insert / Update entries
        $items = $parsed['items'];
        foreach ($items as $event) {
            $authors = isset($event['authors']) ? json_encode($event['authors']) : '';
            $title = isset($event['title']) ? $event['title'] : '';
            $links = isset($event['links']) ? json_encode(multiarray_filter('rel', 'self', $event['links'])) : '';
            $description = isset($event['description']) ? $event['description'] : '';
            $content = isset($event['content']) ? $event['content'] : '';
            $enclosures = isset($event['enclosures']) ? json_encode($event['enclosures']) : '';
            if (isset($event['comments'])) {
                $comments = $event['comments'];
            } else {
                if (isset($event['links'])) {
                    $tmp = multiarray_search('rel', 'replies', $event['links'], array('href' => ''));
                    $comments = $tmp['href'];
                } else {
                    $comments = '';
                }
            }
            $guid = isset($event['guid']) ? $event['guid'] : '';
            $pubDate = isset($event['pubDate']) ? $event['pubDate'] : '';
            $last_update = isset($event['updated']) ? $event['updated'] : '';
            $query_entries->execute();
            if ($query_entries->rowCount() == 0) {
                $query_entries_fail->execute();
            }
            if ($feeds[$array_feed_id]['import_tags_from_feed']) {
                if (!empty($event['categories'])) {
                    foreach ($event['categories'] as $tag_name) {
                        // Create tags if needed, get their id and add bind the articles to these tags
                        $query_insert_tag->execute();
                        $query_tags->execute();
                    }
                }
            }
            if (!empty($event['enclosures'])) {
                foreach ($event['enclosures'] as $enclosure) {
                    $tag_name = '_type_' . get_category_mime_type($enclosure['type']);
                    if ($tag_name !== false) {
                        $query_tags->execute();
                    }
                }
            }
        }
    }
    // Check favicons
    if ($check_favicons && !empty($favicons_to_check)) {
        $favicons = get_favicon($favicons_to_check);
        $favicons = $favicons['favicons'];
        $query_favicon = $dbh->prepare('UPDATE feeds SET image=:image WHERE url=:url');
        $query_favicon->bindParam(':url', $url);
        $query_favicon->bindParam(':image', $image);
        foreach ($favicons as $url => $favicon) {
            if (!empty($favicon[0]['favicon_url'])) {
                $image = $favicon[0]['favicon_url'];
                $query_favicon->execute();
            }
        }
    }
    $dbh->commit();
    delete_old_entries();
    return $errors;
}
Esempio n. 2
0
/**
 * Parse an OPML file.
 *
 * @return An array of associative array for each feed with URL, title and associated tags.
 * @copyright Heavily based on a function from FreshRSS.
 */
function opml_import($xml)
{
    $opml = simplexml_load_string($xml);
    if (!$opml) {
        return false;
    }
    $categories = array();
    $feeds = array();
    foreach ($opml->body->outline as $outline) {
        if (!isset($outline['xmlUrl'])) {
            // Folder
            $tag = '';
            if (isset($outline['text'])) {
                $tag = (string) $outline['text'];
            } elseif (isset($outline['title'])) {
                $tag = (string) $outline['title'];
            }
            if ($tag) {
                foreach ($outline->outline as $feed) {
                    if (!isset($feed['xmlUrl'])) {
                        continue;
                    }
                    $search = multiarray_search_key('url', (string) $feed['xmlUrl'], $feeds);
                    if ($search === -1) {
                        // Feed was not yet encountered, so add it first
                        if (isset($feed['title'])) {
                            $feed_title = (string) $feed['title'];
                        } elseif (isset($feed['text'])) {
                            $feed_title = (string) $feed['text'];
                        } else {
                            $feed_title = '';
                        }
                        $feeds[] = array('url' => (string) $feed['xmlUrl'], 'title' => $feed_title, 'tags' => array(), 'post' => '');
                        $search = count($feeds) - 1;
                    }
                    $feeds[$search]['tags'][] = $tag;
                }
            }
        } else {
            // This is a RSS feed without any folder
            if (isset($outline['title'])) {
                $title = (string) $outline['title'];
            } elseif (isset($outline['text'])) {
                $title = (string) $outline['text'];
            } else {
                $title = '';
            }
            if (multiarray_search_key('url', (string) $outline['xmlUrl'], $feeds) !== -1) {
                $feeds[] = array('url' => (string) $outline['xmlUrl'], 'title' => $title, 'tags' => array(), 'post' => '');
            }
        }
    }
    return $feeds;
}