/** * 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); } }
/** * 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); } }