function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) { $this->url = $url; $this->timeout = $timeout; $this->redirects = $redirects; $this->headers = $headers; $this->useragent = $useragent; $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE; global $wpdb; global $fwp_credentials; if (preg_match('/^http(s)?:\\/\\//i', $url)) { $args = array('timeout' => $this->timeout, 'redirection' => $this->redirects); if (!empty($this->headers)) { $args['headers'] = $this->headers; } if (SIMPLEPIE_USERAGENT != $this->useragent) { //Use default WP user agent unless custom has been specified $args['user-agent'] = $this->useragent; } // This is ugly as hell, but communicating up and down the chain // in any other way is difficult. if (!is_null($fwp_credentials)) { $args['authentication'] = $fwp_credentials['authentication']; $args['username'] = $fwp_credentials['username']; $args['password'] = $fwp_credentials['password']; } else { $links = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->links} WHERE link_rss = '%s'", $url)); if ($links) { $source = new SyndicatedLink($links[0]); $args['authentication'] = $source->authentication_method(); $args['username'] = $source->username(); $args['password'] = $source->password(); } } $res = wp_remote_request($url, $args); if (is_wp_error($res)) { $this->error = 'WP HTTP Error: ' . $res->get_error_message(); $this->success = false; } else { $this->headers = wp_remote_retrieve_headers($res); $this->body = wp_remote_retrieve_body($res); $this->status_code = wp_remote_retrieve_response_code($res); } } else { if (!($this->body = file_get_contents($url))) { $this->error = 'file_get_contents could not read the file'; $this->success = false; } } // SimplePie makes a strongly typed check against integers with // this, but WordPress puts a string in. Which causes caching // to break and fall on its ass when SimplePie is getting a 304, // but doesn't realize it because this member is "304" instead. $this->status_code = (int) $this->status_code; }
/** * SyndicatedPost constructor: Given a feed item and the source from * which it was taken, prepare a post that can be inserted into the * WordPress database on request, or updated in place if it has already * been syndicated. * * @param array $item The item syndicated from the feed. * @param SyndicatedLink $source The feed it was syndicated from. */ function SyndicatedPost($item, &$source) { global $wpdb; if (empty($item) && empty($source)) { return; } if (is_array($item) and isset($item['simplepie']) and isset($item['magpie'])) { $this->entry = $item['simplepie']; $this->item = $item['magpie']; $item = $item['magpie']; } elseif (is_a($item, 'SimplePie_Item')) { $this->entry = $item; // convert to Magpie for compat purposes $mp = new MagpieFromSimplePie($source->simplepie, $this->entry); $this->item = $mp->get_item(); // done with conversion object $mp = NULL; unset($mp); } else { $this->item = $item; } $this->link =& $source; $this->feed = $source->magpie; $this->feedmeta = $source->settings; FeedWordPress::diagnostic('feed_items', 'Considering item [' . $this->guid() . '] "' . $this->entry->get_title() . '"'); # Dealing with namespaces can get so f*****g f****d. $this->xmlns['forward'] = $source->magpie->_XMLNS_FAMILIAR; $this->xmlns['reverse'] = array(); foreach ($this->xmlns['forward'] as $url => $ns) { if (!isset($this->xmlns['reverse'][$ns])) { $this->xmlns['reverse'][$ns] = array(); } $this->xmlns['reverse'][$ns][] = $url; } // F*****g SimplePie. $this->xmlns['reverse']['rss'][] = ''; # These globals were originally an ugly kludge around a bug in # apply_filters from WordPress 1.5. The bug was fixed in 1.5.1, # and I sure hope at this point that nobody writing filters for # FeedWordPress is still relying on them. # # Anyway, I hereby declare them DEPRECATED as of 8 February # 2010. I'll probably remove the globals within 1-2 releases in # the interests of code hygiene and memory usage. If you # currently use them in your filters, I advise you switch off to # accessing the public members SyndicatedPost::feed and # SyndicatedPost::feedmeta. global $fwp_channel, $fwp_feedmeta; $fwp_channel = $this->feed; $fwp_feedmeta = $this->feedmeta; // Trigger global syndicated_item filter. $changed = apply_filters('syndicated_item', $this->item, $this); $this->item = $changed; // Allow for feed-specific syndicated_item filters. $changed = apply_filters("syndicated_item_" . $source->uri(), $this->item, $this); $this->item = $changed; # Filters can halt further processing by returning NULL if (is_null($this->item)) { $this->post = NULL; } else { # Note that nothing is run through esc_sql() here. # That's deliberate. The escaping is done at the point # of insertion, not here, to avoid double-escaping and # to avoid screwing with syndicated_post filters $this->post['post_title'] = apply_filters('syndicated_item_title', $this->entry->get_title(), $this); $this->named['author'] = apply_filters('syndicated_item_author', $this->author(), $this); // This just gives us an alphanumeric name for the author. // We look up (or create) the numeric ID for the author // in SyndicatedPost::add(). $this->post['post_content'] = apply_filters('syndicated_item_content', $this->content(), $this); $excerpt = apply_filters('syndicated_item_excerpt', $this->excerpt(), $this); if (!empty($excerpt)) { $this->post['post_excerpt'] = $excerpt; } // Dealing with timestamps in WordPress is so f*****g f****d. $offset = (int) get_option('gmt_offset') * 60 * 60; $post_date_gmt = $this->published(array('default' => -1)); $post_modified_gmt = $this->updated(array('default' => -1)); $this->post['post_date_gmt'] = gmdate('Y-m-d H:i:s', $post_date_gmt); $this->post['post_date'] = gmdate('Y-m-d H:i:s', $post_date_gmt + $offset); $this->post['post_modified_gmt'] = gmdate('Y-m-d H:i:s', $post_modified_gmt); $this->post['post_modified'] = gmdate('Y-m-d H:i:s', $post_modified_gmt + $offset); // Use feed-level preferences or the global default. $this->post['post_status'] = $this->link->syndicated_status('post', 'publish'); $this->post['comment_status'] = $this->link->syndicated_status('comment', 'closed'); $this->post['ping_status'] = $this->link->syndicated_status('ping', 'closed'); // Unique ID (hopefully a unique tag: URI); failing that, the permalink $this->post['guid'] = apply_filters('syndicated_item_guid', $this->guid(), $this); // User-supplied custom settings to apply to each post. // Do first so that FWP-generated custom settings will // overwrite if necessary; thus preventing any munging. $postMetaIn = $this->link->postmeta(array("parsed" => true)); $postMetaOut = array(); foreach ($postMetaIn as $key => $meta) { $postMetaOut[$key] = $meta->do_substitutions($this); } foreach ($postMetaOut as $key => $values) { $this->post['meta'][$key] = array(); foreach ($values as $value) { $this->post['meta'][$key][] = apply_filters("syndicated_post_meta_{$key}", $value, $this); } } // RSS 2.0 / Atom 1.0 enclosure support $enclosures = $this->entry->get_enclosures(); if (is_array($enclosures)) { foreach ($enclosures as $enclosure) { $this->post['meta']['enclosure'][] = apply_filters('syndicated_item_enclosure_url', $enclosure->get_link(), $this) . "\n" . apply_filters('syndicated_item_enclosure_length', $enclosure->get_length(), $this) . "\n" . apply_filters('syndicated_item_enclosure_type', $enclosure->get_type(), $this); } } // In case you want to point back to the blog this was // syndicated from. $sourcemeta['syndication_source'] = apply_filters('syndicated_item_source_title', $this->link->name(), $this); $sourcemeta['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->link->homepage(), $this); $sourcemeta['syndication_source_id'] = apply_filters('syndicated_item_source_id', $this->link->guid(), $this); // Make use of atom:source data, if present in an aggregated feed $entry_source = $this->source(); if (!is_null($entry_source)) { foreach ($entry_source as $what => $value) { if (!is_null($value)) { if ($what == 'title') { $key = 'syndication_source'; } elseif ($what == 'feed') { $key = 'syndication_feed'; } else { $key = "syndication_source_{$what}"; } $sourcemeta["{$key}_original"] = apply_filters('syndicated_item_original_source_' . $what, $value, $this); } } } foreach ($sourcemeta as $meta_key => $value) { if (!is_null($value)) { $this->post['meta'][$meta_key] = $value; } } // Store information on human-readable and machine-readable comment URIs // Human-readable comment URI $commentLink = apply_filters('syndicated_item_comments', $this->comment_link(), $this); if (!is_null($commentLink)) { $this->post['meta']['rss:comments'] = $commentLink; } // Machine-readable content feed URI $commentFeed = apply_filters('syndicated_item_commentrss', $this->comment_feed(), $this); if (!is_null($commentFeed)) { $this->post['meta']['wfw:commentRSS'] = $commentFeed; } // Yeah, yeah, now I know that it's supposed to be // wfw:commentRss. Oh well. Path dependence, sucka. // Store information to identify the feed that this came from if (isset($this->feedmeta['link/uri'])) { $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri']; } if (isset($this->feedmeta['link/id'])) { $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id']; } if (isset($this->item['source_link_self'])) { $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self']; } // In case you want to know the external permalink... $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->permalink()); // Store a hash of the post content for checking whether something needs to be updated $this->post['meta']['syndication_item_hash'] = $this->update_hash(); // Categories: start with default categories, if any. $cats = array(); if ('no' != $this->link->setting('add/category', NULL, 'yes')) { $fc = get_option("feedwordpress_syndication_cats"); if ($fc) { $cats = array_merge($cats, explode("\n", $fc)); } } $fc = $this->link->setting('cats', NULL, array()); if (is_array($fc)) { $cats = array_merge($cats, $fc); } $this->preset_terms['category'] = $cats; // Now add categories from the post, if we have 'em $cats = array(); $post_cats = $this->entry->get_categories(); if (is_array($post_cats)) { foreach ($post_cats as $cat) { $cat_name = $cat->get_term(); if (!$cat_name) { $cat_name = $cat->get_label(); } if ($this->link->setting('cat_split', NULL, NULL)) { $pcre = "" . $this->feedmeta['cat_split'] . ""; $cats = array_merge($cats, preg_split($pcre, $cat_name, -1, PREG_SPLIT_NO_EMPTY)); } else { $cats[] = $cat_name; } } } $this->feed_terms['category'] = apply_filters('syndicated_item_categories', $cats, $this); // Tags: start with default tags, if any $tags = array(); if ('no' != $this->link->setting('add/post_tag', NULL, 'yes')) { $ft = get_option("feedwordpress_syndication_tags", NULL); $tags = is_null($ft) ? array() : explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft); } $ft = $this->link->setting('tags', NULL, array()); if (is_array($ft)) { $tags = array_merge($tags, $ft); } $this->preset_terms['post_tag'] = $tags; // Scan post for /a[@rel='tag'] and use as tags if present $tags = $this->inline_tags(); $this->feed_terms['post_tag'] = apply_filters('syndicated_item_tags', $tags, $this); $taxonomies = $this->link->taxonomies(); $feedTerms = $this->link->setting('terms', NULL, array()); $globalTerms = get_option('feedwordpress_syndication_terms', array()); $specials = array('category' => 'cats', 'post_tag' => 'tags'); foreach ($taxonomies as $tax) { if (!isset($specials[$tax])) { $terms = array(); // See if we should get the globals if ('no' != $this->link->setting("add/{$tax}", NULL, 'yes')) { if (isset($globalTerms[$tax])) { $terms = $globalTerms[$tax]; } } // Now merge in the locals if (isset($feedTerms[$tax])) { $terms = array_merge($terms, $feedTerms[$tax]); } // That's all, folks. $this->preset_terms[$tax] = $terms; } } $this->post['post_type'] = apply_filters('syndicated_post_type', $this->link->setting('syndicated post type', 'syndicated_post_type', 'post'), $this); } }
function fwp_switchfeed_page() { global $wpdb, $wp_db_version; global $fwp_post, $fwp_path; // If this is a POST, validate source and user credentials FeedWordPressCompatibility::validate_http_request('feedwordpress_switchfeed', 'manage_links'); $changed = false; if (!isset($fwp_post['Cancel'])) { if (isset($fwp_post['save_link_id']) and $fwp_post['save_link_id'] == '*') { $changed = true; $link_id = FeedWordPress::syndicate_link($fwp_post['feed_title'], $fwp_post['feed_link'], $fwp_post['feed']); if ($link_id) { $existingLink = new SyndicatedLink($link_id); ?> <div class="updated"><p><a href="<?php print $fwp_post['feed_link']; ?> "><?php print esc_html($fwp_post['feed_title']); ?> </a> has been added as a contributing site, using the feed at <<a href="<?php print $fwp_post['feed']; ?> "><?php print esc_html($fwp_post['feed']); ?> </a>>. | <a href="admin.php?page=<?php print $fwp_path; ?> /feeds-page.php&link_id=<?php print $link_id; ?> ">Configure settings</a>.</p></div> <?php } else { ?> <div class="updated"><p>There was a problem adding the feed. [SQL: <?php echo esc_html(mysql_error()); ?> ]</p></div> <?php } } elseif (isset($fwp_post['save_link_id'])) { $existingLink = new SyndicatedLink($fwp_post['save_link_id']); $changed = $existingLink->set_uri($fwp_post['feed']); if ($changed) { $home = $existingLink->homepage(false); $name = $existingLink->name(false); ?> <div class="updated"><p>Feed for <a href="<?php echo esc_html($home); ?> "><?php echo esc_html($name); ?> </a> updated to <<a href="<?php echo esc_html($fwp_post['feed']); ?> "><?php echo esc_html($fwp_post['feed']); ?> </a>>.</p></div> <?php } } } if (isset($existingLink)) { $auth = MyPHP::post('link_rss_auth_method'); if (!is_null($auth) and strlen($auth) > 0 and $auth != '-') { $existingLink->update_setting('http auth method', $auth); $existingLink->update_setting('http username', MyPHP::post('link_rss_username')); $existingLink->update_setting('http password', MyPHP::post('link_rss_password')); } else { $existingLink->update_setting('http auth method', NULL); $existingLink->update_setting('http username', NULL); $existingLink->update_setting('http password', NULL); } do_action('feedwordpress_admin_switchfeed', $fwp_post['feed'], $existingLink); $existingLink->save_settings(true); } if (!$changed) { ?> <div class="updated"><p>Nothing was changed.</p></div> <?php } return true; // Continue }
/** * SyndicatedPost constructor: Given a feed item and the source from * which it was taken, prepare a post that can be inserted into the * WordPress database on request, or updated in place if it has already * been syndicated. * * @param array $item The item syndicated from the feed. * @param SyndicatedLink $source The feed it was syndicated from. */ function __construct($item, &$source) { global $wpdb; if (empty($item) && empty($source)) { return; } if (is_array($item) and isset($item['simplepie']) and isset($item['magpie'])) { $this->entry = $item['simplepie']; $this->item = $item['magpie']; $item = $item['magpie']; } elseif (is_a($item, 'SimplePie_Item')) { $this->entry = $item; // convert to Magpie for compat purposes $mp = new MagpieFromSimplePie($source->simplepie, $this->entry); $this->item = $mp->get_item(); // done with conversion object $mp = NULL; unset($mp); } else { $this->item = $item; } $this->link =& $source; $this->feed = $source->magpie; $this->feedmeta = $source->settings; FeedWordPress::diagnostic('feed_items', 'Considering item [' . $this->guid() . '] "' . $this->entry->get_title() . '"'); # Dealing with namespaces can get so f*****g f****d. $this->xmlns['forward'] = $source->magpie->_XMLNS_FAMILIAR; $this->xmlns['reverse'] = array(); foreach ($this->xmlns['forward'] as $url => $ns) { if (!isset($this->xmlns['reverse'][$ns])) { $this->xmlns['reverse'][$ns] = array(); } $this->xmlns['reverse'][$ns][] = $url; } // F*****g SimplePie. $this->xmlns['reverse']['rss'][] = ''; // Trigger global syndicated_item filter. $changed = apply_filters('syndicated_item', $this->item, $this); $this->item = $changed; // Allow for feed-specific syndicated_item filters. $changed = apply_filters("syndicated_item_" . $source->uri(), $this->item, $this); $this->item = $changed; # Filters can halt further processing by returning NULL if (is_null($this->item)) { $this->post = NULL; } else { # Note that nothing is run through esc_sql() here. # That's deliberate. The escaping is done at the point # of insertion, not here, to avoid double-escaping and # to avoid screwing with syndicated_post filters $this->post['post_title'] = apply_filters('syndicated_item_title', $this->entry->get_title(), $this); $this->named['author'] = apply_filters('syndicated_item_author', $this->author(), $this); // This just gives us an alphanumeric name for the author. // We look up (or create) the numeric ID for the author // in SyndicatedPost::add(). $this->post['post_content'] = apply_filters('syndicated_item_content', $this->content(), $this); $excerpt = apply_filters('syndicated_item_excerpt', $this->excerpt(), $this); if (!empty($excerpt)) { $this->post['post_excerpt'] = $excerpt; } // Dealing with timestamps in WordPress is so f*****g f****d. $offset = (int) get_option('gmt_offset') * 60 * 60; $post_date_gmt = $this->published(array('default' => -1)); $post_modified_gmt = $this->updated(array('default' => -1)); $this->post['post_date_gmt'] = gmdate('Y-m-d H:i:s', $post_date_gmt); $this->post['post_date'] = gmdate('Y-m-d H:i:s', $post_date_gmt + $offset); $this->post['post_modified_gmt'] = gmdate('Y-m-d H:i:s', $post_modified_gmt); $this->post['post_modified'] = gmdate('Y-m-d H:i:s', $post_modified_gmt + $offset); // Use feed-level preferences or the global default. $this->post['post_status'] = $this->link->syndicated_status('post', 'publish'); $this->post['comment_status'] = $this->link->syndicated_status('comment', 'closed'); $this->post['ping_status'] = $this->link->syndicated_status('ping', 'closed'); // Unique ID (hopefully a unique tag: URI); failing that, the permalink $this->post['guid'] = apply_filters('syndicated_item_guid', $this->guid(), $this); // User-supplied custom settings to apply to each post. // Do first so that FWP-generated custom settings will // overwrite if necessary; thus preventing any munging. $postMetaIn = $this->link->postmeta(array("parsed" => true)); $postMetaOut = array(); foreach ($postMetaIn as $key => $meta) { $postMetaOut[$key] = $meta->do_substitutions($this); } foreach ($postMetaOut as $key => $values) { $this->post['meta'][$key] = array(); foreach ($values as $value) { $this->post['meta'][$key][] = apply_filters("syndicated_post_meta_{$key}", $value, $this); } } // RSS 2.0 / Atom 1.0 enclosure support $enclosures = $this->entry->get_enclosures(); if (is_array($enclosures)) { foreach ($enclosures as $enclosure) { $this->post['meta']['enclosure'][] = apply_filters('syndicated_item_enclosure_url', $enclosure->get_link(), $this) . "\n" . apply_filters('syndicated_item_enclosure_length', $enclosure->get_length(), $this) . "\n" . apply_filters('syndicated_item_enclosure_type', $enclosure->get_type(), $this); } } // In case you want to point back to the blog this was // syndicated from. $sourcemeta['syndication_source'] = apply_filters('syndicated_item_source_title', $this->link->name(), $this); $sourcemeta['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->link->homepage(), $this); $sourcemeta['syndication_source_id'] = apply_filters('syndicated_item_source_id', $this->link->guid(), $this); // Make use of atom:source data, if present in an aggregated feed $entry_source = $this->source(); if (!is_null($entry_source)) { foreach ($entry_source as $what => $value) { if (!is_null($value)) { if ($what == 'title') { $key = 'syndication_source'; } elseif ($what == 'feed') { $key = 'syndication_feed'; } else { $key = "syndication_source_{$what}"; } $sourcemeta["{$key}_original"] = apply_filters('syndicated_item_original_source_' . $what, $value, $this); } } } foreach ($sourcemeta as $meta_key => $value) { if (!is_null($value)) { $this->post['meta'][$meta_key] = $value; } } // Store information on human-readable and machine-readable comment URIs // Human-readable comment URI $commentLink = apply_filters('syndicated_item_comments', $this->comment_link(), $this); if (!is_null($commentLink)) { $this->post['meta']['rss:comments'] = $commentLink; } // Machine-readable content feed URI $commentFeed = apply_filters('syndicated_item_commentrss', $this->comment_feed(), $this); if (!is_null($commentFeed)) { $this->post['meta']['wfw:commentRSS'] = $commentFeed; } // Yeah, yeah, now I know that it's supposed to be // wfw:commentRss. Oh well. Path dependence, sucka. // Store information to identify the feed that this came from if (isset($this->feedmeta['link/uri'])) { $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri']; } if (isset($this->feedmeta['link/id'])) { $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id']; } if (isset($this->item['source_link_self'])) { $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self']; } // In case you want to know the external permalink... $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->permalink()); // Store a hash of the post content for checking whether something needs to be updated $this->post['meta']['syndication_item_hash'] = $this->update_hash(); // Categories, Tags, and other Terms: from settings assignments (global settings, subscription settings), // and from feed assignments (item metadata, post content) $this->preset_terms = apply_filters('syndicated_item_preset_terms', $this->get_terms_from_settings(), $this); $this->feed_terms = apply_filters('syndicated_item_feed_terms', $this->get_terms_from_feeds(), $this); $this->post['post_type'] = apply_filters('syndicated_post_type', $this->link->setting('syndicated post type', 'syndicated_post_type', 'post'), $this); } }
function needs_upgrade() { global $wpdb; $fwp_db_version = get_option('feedwordpress_version'); $ret = false; // innocent until proven guilty if (!$fwp_db_version or $fwp_db_version < FEEDWORDPRESS_VERSION) { // This is an older version or a fresh install. Does it // require a database upgrade or database initialization? if ($fwp_db_version <= 0.96) { // Yes. Check to see whether this is a fresh install or an upgrade. $syn = $wpdb->get_col("\n\t\t\t\tSELECT post_id\n\t\t\t\tFROM {$wpdb->postmeta}\n\t\t\t\tWHERE meta_key = 'syndication_feed'\n\t\t\t\t"); if (count($syn) > 0) { // contains at least one syndicated post $ret = true; } else { // fresh install; brand it as ours update_option('feedwordpress_version', FEEDWORDPRESS_VERSION); } } elseif ($fwp_db_version < 2009.0707) { // We need to clear out any busted AJAX crap $wpdb->query("\n\t\t\t\tDELETE FROM {$wpdb->usermeta}\n\t\t\t\tWHERE LOCATE('feedwordpress', meta_key)\n\t\t\t\tAND LOCATE('box', meta_key);\n\t\t\t\t"); update_option('feedwordpress_version', FEEDWORDPRESS_VERSION); } elseif ($fwp_db_version < 2010.0814) { // Change in terminology. if (get_option('feedwordpress_unfamiliar_category', 'create') == 'default') { update_option('feedwordpress_unfamiliar_category', 'null'); } foreach (FeedWordPress::syndicated_links() as $link) { $sub = new SyndicatedLink($link); $remap_uf = array('default' => 'null', 'filter' => 'null', 'create' => 'create:category', 'tag' => 'create:post_tag'); if (isset($sub->settings['unfamiliar category'])) { if ($sub->settings['unfamiliar category'] == 'filter') { $sub->settings['match/filter'] = array('category'); } foreach ($remap_uf as $from => $to) { if ($sub->settings['unfamiliar category'] == $from) { $sub->settings['unfamiliar category'] = $to; } } } if (isset($sub->settings['add global categories'])) { $sub->settings['add/category'] = $sub->settings['add global categories']; unset($sub->settings['add global categories']); } $sub->save_settings(true); } update_option('feedwordpress_version', FEEDWORDPRESS_VERSION); } else { // No. Just brand it with the new version. update_option('feedwordpress_version', FEEDWORDPRESS_VERSION); } } return $ret; }
function fwp_syndication_manage_page_links_table_rows($links, $page, $visible = 'Y') { $subscribed = 'Y' == strtoupper($visible); if ($subscribed or count($links) > 0) { ?> <table class="widefat<?php if (!$subscribed) { ?> unsubscribed<?php } ?> "> <thead> <tr> <th class="check-column" scope="col"><input type="checkbox" /></th> <th scope="col"><?php _e('Name'); ?> </th> <th scope="col"><?php _e('Feed'); ?> </th> <th scope="col"><?php _e('Updated'); ?> </th> </tr> </thead> <tbody> <?php $alt_row = true; if (count($links) > 0) { foreach ($links as $link) { $trClass = array(); // Prep: Get last updated timestamp $sLink = new SyndicatedLink($link->link_id); if (!is_null($sLink->setting('update/last'))) { $lastUpdated = 'Last checked ' . fwp_time_elapsed($sLink->setting('update/last')); } else { $lastUpdated = __('None yet'); } // Prep: get last error timestamp, if any $fileSizeLines = array(); if (is_null($sLink->setting('update/error'))) { $errorsSince = ''; if (!is_null($sLink->setting('link/item count'))) { $N = $sLink->setting('link/item count'); $fileSizeLines[] = sprintf($N == 1 ? __('%d item') : __('%d items'), $N); } if (!is_null($sLink->setting('link/filesize'))) { $fileSizeLines[] = size_format($sLink->setting('link/filesize')) . ' total'; } } else { $trClass[] = 'feed-error'; $theError = unserialize($sLink->setting('update/error')); $errorsSince = "<div class=\"returning-errors\">" . "<p><strong>Returning errors</strong> since " . fwp_time_elapsed($theError['since']) . "</p>" . "<p>Most recent (" . fwp_time_elapsed($theError['ts']) . "):<br/><code>" . implode("</code><br/><code>", $theError['object']->get_error_messages()) . "</code></p>" . "</div>\n"; } $nextUpdate = "<div style='max-width: 30.0em; font-size: 0.9em;'><div style='font-style:italic;'>"; $ttl = $sLink->setting('update/ttl'); if (is_numeric($ttl)) { $next = $sLink->setting('update/last') + $sLink->setting('update/fudge') + (int) $ttl * 60; if ('automatically' == $sLink->setting('update/timed')) { if ($next < time()) { $nextUpdate .= 'Ready and waiting to be updated since '; } else { $nextUpdate .= 'Scheduled for next update '; } $nextUpdate .= fwp_time_elapsed($next); if (FEEDWORDPRESS_DEBUG) { $nextUpdate .= " [" . ($next - time()) / 60 . " minutes]"; } } else { $lastUpdated .= " · Next "; if ($next < time()) { $lastUpdated .= 'ASAP'; } elseif ($next - time() < 60) { $lastUpdated .= fwp_time_elapsed($next); } elseif ($next - time() < 60 * 60 * 24) { $lastUpdated .= gmdate('g:ia', $next + get_option('gmt_offset') * 3600); } else { $lastUpdated .= gmdate('F j', $next + get_option('gmt_offset') * 3600); } $nextUpdate .= "Scheduled to be checked for updates every " . $ttl . " minute" . ($ttl != 1 ? "s" : "") . "</div><div style='size:0.9em; margin-top: 0.5em'>\tThis update schedule was requested by the feed provider"; if ($sLink->setting('update/xml')) { $nextUpdate .= " using a standard <code style=\"font-size: inherit; padding: 0; background: transparent\"><" . $sLink->setting('update/xml') . "></code> element"; } $nextUpdate .= "."; } } else { $nextUpdate .= "Scheduled for update as soon as possible"; } $nextUpdate .= "</div></div>"; $fileSize = ''; if (count($fileSizeLines) > 0) { $fileSize = '<div>' . implode(" / ", $fileSizeLines) . "</div>"; } unset($sLink); $alt_row = !$alt_row; if ($alt_row) { $trClass[] = 'alternate'; } ?> <tr<?php echo count($trClass) > 0 ? ' class="' . implode(" ", $trClass) . '"' : ''; ?> > <th class="check-column" scope="row"><input type="checkbox" name="link_ids[]" value="<?php echo $link->link_id; ?> " /></th> <?php $caption = strlen($link->link_rss) > 0 ? __('Switch Feed') : ($caption = __('Find Feed')); ?> <td> <strong><a href="<?php print $page->admin_page_href('feeds-page.php', array(), $link); ?> "><?php print esc_html($link->link_name); ?> </a></strong> <div class="row-actions"><?php if ($subscribed) { $page->display_feed_settings_page_links(array('before' => '<div><strong>Settings ></strong> ', 'after' => '</div>', 'subscription' => $link)); } ?> <div><strong>Actions ></strong> <?php if ($subscribed) { ?> <a href="<?php print $page->admin_page_href('syndication.php', array('action' => 'feedfinder'), $link); ?> "><?php echo $caption; ?> </a> <?php } else { ?> <a href="<?php print $page->admin_page_href('syndication.php', array('action' => FWP_RESUB_CHECKED), $link); ?> "><?php _e('Re-subscribe'); ?> </a> <?php } ?> | <a href="<?php print $page->admin_page_href('syndication.php', array('action' => 'Unsubscribe'), $link); ?> "><?php _e($subscribed ? 'Unsubscribe' : 'Delete permanently'); ?> </a> | <a href="<?php print esc_html($link->link_url); ?> "><?php _e('View'); ?> </a></div> </div> </td> <?php if (strlen($link->link_rss) > 0) { ?> <td><a href="<?php echo esc_html($link->link_rss); ?> "><?php echo esc_html(feedwordpress_display_url($link->link_rss, 32)); ?> </a></td> <?php } else { ?> <td class="feed-missing"><p><strong>no feed assigned</strong></p></td> <?php } ?> <td><div style="float: right; padding-left: 10px"> <input type="submit" class="button" name="update_uri[<?php print esc_html($link->link_rss); ?> ]" value="<?php _e('Update Now'); ?> " /> </div> <?php print $lastUpdated; ?> <?php print $fileSize; ?> <?php print $errorsSince; ?> <?php print $nextUpdate; ?> </td> </tr> <?php } } else { ?> <tr><td colspan="4"><p>There are no websites currently listed for syndication.</p></td></tr> <?php } ?> </tbody> </table> <?php } }
static function needs_upgrade() { global $wpdb; $fwp_db_version = get_option('feedwordpress_version', NULL); $ret = false; // innocent until proven guilty if (is_null($fwp_db_version) or $fwp_db_version < FEEDWORDPRESS_VERSION) { // This is an older version or a fresh install. Does it require a database // upgrade or database initialization? if (is_null($fwp_db_version)) { // Fresh install; brand it as ours. Or possibly a version of FWP // from before 0.96. But I'm no longer supporting upgrade paths // for versions from the previous decade. Sorry. update_option('feedwordpress_version', FEEDWORDPRESS_VERSION); } elseif ($fwp_db_version < 2010.0814) { // Change in terminology. if (get_option('feedwordpress_unfamiliar_category', 'create') == 'default') { update_option('feedwordpress_unfamiliar_category', 'null'); } foreach (FeedWordPress::syndicated_links() as $link) { $sub = new SyndicatedLink($link); $remap_uf = array('default' => 'null', 'filter' => 'null', 'create' => 'create:category', 'tag' => 'create:post_tag'); if (isset($sub->settings['unfamiliar category'])) { if ($sub->settings['unfamiliar category'] == 'filter') { $sub->settings['match/filter'] = array('category'); } foreach ($remap_uf as $from => $to) { if ($sub->settings['unfamiliar category'] == $from) { $sub->settings['unfamiliar category'] = $to; } } } if (isset($sub->settings['add global categories'])) { $sub->settings['add/category'] = $sub->settings['add global categories']; unset($sub->settings['add global categories']); } $sub->save_settings(true); } update_option('feedwordpress_version', FEEDWORDPRESS_VERSION); } else { // No upgrade needed. Just brand it with the new version. update_option('feedwordpress_version', FEEDWORDPRESS_VERSION); } } return $ret; }
/** * SyndicatedPost constructor: Given a feed item and the source from * which it was taken, prepare a post that can be inserted into the * WordPress database on request, or updated in place if it has already * been syndicated. * * @param array $item The item syndicated from the feed. * @param SyndicatedLink $source The feed it was syndicated from. */ function SyndicatedPost($item, $source) { if (is_array($item) and isset($item['simplepie']) and isset($item['magpie'])) { $this->entry = $item['simplepie']; $this->item = $item['magpie']; $item = $item['magpie']; } else { $this->item = $item; } FeedWordPress::diagnostic('feed_items', 'Considering item [' . $this->guid() . '] "' . $this->entry->get_title() . '"'); $this->link = $source; $this->feed = $source->magpie; $this->feedmeta = $source->settings; # Dealing with namespaces can get so ... $this->xmlns['forward'] = $source->magpie->_XMLNS_FAMILIAR; $this->xmlns['reverse'] = array(); foreach ($this->xmlns['forward'] as $url => $ns) { if (!isset($this->xmlns['reverse'][$ns])) { $this->xmlns['reverse'][$ns] = array(); } $this->xmlns['reverse'][$ns][] = $url; } // F*****g SimplePie. $this->xmlns['reverse']['rss'][] = ''; # These globals were originally an ugly kludge around a bug in # apply_filters from WordPress 1.5. The bug was fixed in 1.5.1, # and I sure hope at this point that nobody writing filters for # FeedWordPress is still relying on them. # # Anyway, I hereby declare them DEPRECATED as of 8 February # 2010. I'll probably remove the globals within 1-2 releases in # the interests of code hygiene and memory usage. If you # currently use them in your filters, I advise you switch off to # accessing the public members SyndicatedPost::feed and # SyndicatedPost::feedmeta. global $fwp_channel, $fwp_feedmeta; $fwp_channel = $this->feed; $fwp_feedmeta = $this->feedmeta; // Trigger global syndicated_item filter. $this->item = apply_filters('syndicated_item', $this->item, $this); // Allow for feed-specific syndicated_item filters. $this->item = apply_filters("syndicated_item_" . $source->uri(), $this->item, $this); # Filters can halt further processing by returning NULL if (is_null($this->item)) { $this->post = NULL; } else { # Note that nothing is run through $wpdb->escape() here. # That's deliberate. The escaping is done at the point # of insertion, not here, to avoid double-escaping and # to avoid screwing with syndicated_post filters $this->post['post_title'] = apply_filters('syndicated_item_title', $this->entry->get_title(), $this); $this->post['named']['author'] = apply_filters('syndicated_item_author', $this->author(), $this); // This just gives us an alphanumeric name for the author. // We look up (or create) the numeric ID for the author // in SyndicatedPost::add(). $this->post['post_content'] = apply_filters('syndicated_item_content', $this->content(), $this); $excerpt = apply_filters('syndicated_item_excerpt', $this->excerpt(), $this); if (!empty($excerpt)) { $this->post['post_excerpt'] = $excerpt; } $this->post['epoch']['issued'] = apply_filters('syndicated_item_published', $this->published(), $this); $this->post['epoch']['created'] = apply_filters('syndicated_item_created', $this->created(), $this); $this->post['epoch']['modified'] = apply_filters('syndicated_item_updated', $this->updated(), $this); // Dealing with timestamps in WordPress is so ... $offset = (int) get_option('gmt_offset') * 60 * 60; $this->post['post_date'] = gmdate('Y-m-d H:i:s', apply_filters('syndicated_item_published', $this->published(true, -1), $this) + $offset); $this->post['post_modified'] = gmdate('Y-m-d H:i:s', apply_filters('syndicated_item_updated', $this->updated(true, -1), $this) + $offset); $this->post['post_date_gmt'] = gmdate('Y-m-d H:i:s', apply_filters('syndicated_item_published', $this->published(true, -1), $this)); $this->post['post_modified_gmt'] = gmdate('Y-m-d H:i:s', apply_filters('syndicated_item_updated', $this->updated(true, -1), $this)); // Use feed-level preferences or the global default. $this->post['post_status'] = $this->link->syndicated_status('post', 'publish'); $this->post['comment_status'] = $this->link->syndicated_status('comment', 'closed'); $this->post['ping_status'] = $this->link->syndicated_status('ping', 'closed'); // Unique ID (hopefully a unique tag: URI); failing that, the permalink $this->post['guid'] = apply_filters('syndicated_item_guid', $this->guid(), $this); // User-supplied custom settings to apply to each post. Do first so that FWP-generated custom settings will overwrite if necessary; thus preventing any munging $default_custom_settings = get_option('feedwordpress_custom_settings'); if ($default_custom_settings and !is_array($default_custom_settings)) { $default_custom_settings = unserialize($default_custom_settings); } if (!is_array($default_custom_settings)) { $default_custom_settings = array(); } $custom_settings = isset($this->link->settings['postmeta']) ? $this->link->settings['postmeta'] : null; if ($custom_settings and !is_array($custom_settings)) { $custom_settings = unserialize($custom_settings); } if (!is_array($custom_settings)) { $custom_settings = array(); } $postMetaIn = array_merge($default_custom_settings, $custom_settings); $postMetaOut = array(); // Big ugly loop to do any element substitutions // that we may need. foreach ($postMetaIn as $key => $values) { if (is_string($values)) { $values = array($values); } $postMetaOut[$key] = array(); foreach ($values as $value) { if (preg_match('/\\$\\( ([^)]+) \\)/x', $value, $ref)) { $elements = $this->query($ref[1]); foreach ($elements as $element) { $postMetaOut[$key][] = str_replace($ref[0], $element, $value); } } else { $postMetaOut[$key][] = $value; } } } foreach ($postMetaOut as $key => $values) { $this->post['meta'][$key] = array(); foreach ($values as $value) { $this->post['meta'][$key][] = apply_filters("syndicated_post_meta_{$key}", $value, $this); } } // RSS 2.0 / Atom 1.0 enclosure support $enclosures = $this->entry->get_enclosures(); if (is_array($enclosures)) { foreach ($enclosures as $enclosure) { $this->post['meta']['enclosure'][] = apply_filters('syndicated_item_enclosure_url', $enclosure->get_link(), $this) . "\n" . apply_filters('syndicated_item_enclosure_length', $enclosure->get_length(), $this) . "\n" . apply_filters('syndicated_item_enclosure_type', $enclosure->get_type(), $this); } } // In case you want to point back to the blog this was syndicated from if (isset($this->feed->channel['title'])) { $this->post['meta']['syndication_source'] = apply_filters('syndicated_item_source_title', $this->feed->channel['title'], $this); } if (isset($this->feed->channel['link'])) { $this->post['meta']['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->feed->channel['link'], $this); } // Make use of atom:source data, if present in an aggregated feed if (isset($this->item['source_title'])) { $this->post['meta']['syndication_source_original'] = $this->item['source_title']; } if (isset($this->item['source_link'])) { $this->post['meta']['syndication_source_uri_original'] = $this->item['source_link']; } if (isset($this->item['source_id'])) { $this->post['meta']['syndication_source_id_original'] = $this->item['source_id']; } // Store information on human-readable and machine-readable comment URIs // Human-readable comment URI $commentLink = apply_filters('syndicated_item_comments', $this->comment_link(), $this); if (!is_null($commentLink)) { $this->post['meta']['rss:comments'] = $commentLink; } // Machine-readable content feed URI $commentFeed = apply_filters('syndicated_item_commentrss', $this->comment_feed(), $this); if (!is_null($commentFeed)) { $this->post['meta']['wfw:commentRSS'] = $commentFeed; } // Yeah, yeah, now I know that it's supposed to be // wfw:commentRss. Oh well. Path dependence, sucka. // Store information to identify the feed that this came from if (isset($this->feedmeta['link/uri'])) { $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri']; } if (isset($this->feedmeta['link/id'])) { $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id']; } if (isset($this->item['source_link_self'])) { $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self']; } // In case you want to know the external permalink... $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->permalink()); // Store a hash of the post content for checking whether something needs to be updated $this->post['meta']['syndication_item_hash'] = $this->update_hash(); // Feed-by-feed options for author and category creation $this->post['named']['unfamiliar']['author'] = isset($this->feedmeta['unfamiliar author']) ? $this->feedmeta['unfamiliar author'] : null; $this->post['named']['unfamiliar']['category'] = isset($this->feedmeta['unfamiliar category']) ? $this->feedmeta['unfamiliar category'] : null; // Categories: start with default categories, if any $fc = get_option("feedwordpress_syndication_cats"); if ($fc) { $this->post['named']['preset/category'] = explode("\n", $fc); } else { $this->post['named']['preset/category'] = array(); } if (isset($this->feedmeta['cats']) and is_array($this->feedmeta['cats'])) { $this->post['named']['preset/category'] = array_merge($this->post['named']['preset/category'], $this->feedmeta['cats']); } // Now add categories from the post, if we have 'em $this->post['named']['category'] = array(); if (isset($this->item['category#'])) { for ($i = 1; $i <= $this->item['category#']; $i++) { $cat_idx = $i > 1 ? "#{$i}" : ""; $cat = $this->item["category{$cat_idx}"]; if (isset($this->feedmeta['cat_split']) and strlen($this->feedmeta['cat_split']) > 0) { $pcre = "" . $this->feedmeta['cat_split'] . ""; $this->post['named']['category'] = array_merge($this->post['named']['category'], preg_split($pcre, $cat, -1, PREG_SPLIT_NO_EMPTY)); } else { $this->post['named']['category'][] = $cat; } } } $this->post['named']['category'] = apply_filters('syndicated_item_categories', $this->post['named']['category'], $this); // Tags: start with default tags, if any $ft = get_option("feedwordpress_syndication_tags"); if ($ft) { $this->post['tags_input'] = explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft); } else { $this->post['tags_input'] = array(); } if (isset($this->feedmeta['tags']) and is_array($this->feedmeta['tags'])) { $this->post['tags_input'] = array_merge($this->post['tags_input'], $this->feedmeta['tags']); } $this->post['tags_input'] = apply_filters('syndicated_item_tags', $this->post['tags_input'], $this); } }
function categories_box($page, $box = NULL) { $link = $page->link; $dummy = null; $syndicatedlink = new SyndicatedLink($dummy); if ($this->for_feed_settings()) { $post_type = $link->setting('syndicated post type', 'syndicated_post_type', 'post'); } else { $post_type = get_option('feedwordpress_syndicated_post_type', 'post'); } $taxonomies = get_object_taxonomies(array('object_type' => $post_type), 'names'); $option_map = $this->term_option_map(); $setting_map = $this->term_setting_map(); $globalTax = get_option('feedwordpress_syndication_terms', array()); if ($page->for_feed_settings()) { $terms = $link->setting('terms', NULL, array()); } ?> <table class="edit-form narrow"> <tbody> <?php foreach ($taxonomies as $tax) { $taxonomy = get_taxonomy($tax); ?> <tr><th><?php print $taxonomy->labels->name; ?> </th> <td><?php if (isset($option_map[$tax])) { $option = $option_map[$tax]; $globalCats = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, get_option($option)); } elseif (isset($globalTax[$tax])) { $globalCats = $globalTax[$tax]; } else { $globalCats = array(); } $globalCats = array_map('trim', $globalCats); if ($page->for_feed_settings()) { $add_global_categories = $link->setting("add/{$tax}", NULL, 'yes'); $checked = array('yes' => '', 'no' => ''); $checked[$add_global_categories] = ' checked="checked"'; if (isset($setting_map[$tax])) { $setting = $setting_map[$tax]; $cats = $link->setting($setting, NULL, NULL); if (is_null($cats)) { $cats = array(); } } elseif (isset($terms[$tax])) { $cats = $terms[$tax]; } else { $cats = array(); } } else { $cats = $globalCats; } if ($page->for_feed_settings()) { ?> <table class="twofer"> <tbody> <tr> <td class="primary"> <?php } $dogs = $syndicatedlink->category_ids(NULL, $cats, NULL, array($tax)); if ($taxonomy->hierarchical) { // Use a category-style checkbox fwp_category_box($dogs, 'all ' . $page->these_posts_phrase(), array(), array('taxonomy' => $tax)); } else { // Use a tag-style edit box fwp_tags_box($cats, 'all ' . $page->these_posts_phrase(), array('taxonomy' => $tax)); } $globalDogs = $syndicatedlink->category_ids(NULL, $globalCats, 'create:' . $tax, array($tax)); $siteWideHref = $this->admin_page_href(basename(__FILE__)); if ($page->for_feed_settings()) { ?> </td> <td class="secondary"> <h4>Site-wide <?php print $taxonomy->labels->name; ?> </h4> <?php if (count($globalCats) > 0) { ?> <ul class="current-setting"> <?php foreach ($globalDogs as $dog) { ?> <li><?php $cat = get_term($dog, $tax); print $cat->name; ?> </li> <?php } ?> </ul> </div> <p> <?php } else { ?> <p>Site-wide settings may also assign categories to syndicated posts. <?php } ?> Should <?php print $page->these_posts_phrase(); ?> be assigned these <?php print $taxonomy->labels->name; ?> from the <a href="<?php print esc_html($siteWideHref); ?> ">site-wide settings</a>, in addition to the feed-specific <?php print $taxonomy->labels->name; ?> you set up here?</p> <ul class="settings"> <li><p><label><input type="radio" name="add_global[<?php print $tax; ?> ]" value="yes" <?php print $checked['yes']; ?> /> Yes. Place <?php print $page->these_posts_phrase(); ?> under all these categories.</label></p></li> <li><p><label><input type="radio" name="add_global[<?php print $tax; ?> ]" value="no" <?php print $checked['no']; ?> /> No. Only use the categories I set up on the left. Do not use the global defaults for <?php print $page->these_posts_phrase(); ?> </label></p></li> </ul> </td> </tr> </tbody> </table> <?php } ?> </td> </tr> <?php } ?> </tbody> </table> <?php }
/** Uninstall plugin * * Called with Wordpress uninstall plugin hook. Cleans up database and removes plugin settings * @since 0.4 */ function faf_uninstall() { $cat_id = FeedWordpress::link_category_id(); $links = get_bookmarks(array("category" => $cat_id)); foreach ($links as $l => $link) { $Slink = new SyndicatedLink($link); unset($Slink->settings["faf_advanced_filters_options"]); $Slink->save_settings(); } delete_option("faf_advanced_filters_options"); global $wpdb; $table = $wpdb->prefix . "faftemp"; $sql = "DROP TABLE IF EXISTS {$table}"; $wpdb->query($sql); }