? .git ? .gitignore ? 641522-12_results.patch ? 641522-15_results.patch ? libraries/simplepie.inc Index: feeds.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/feeds.module,v retrieving revision 1.22 diff -u -p -r1.22 feeds.module --- feeds.module 12 Dec 2009 01:20:32 -0000 1.22 +++ feeds.module 12 Dec 2009 14:51:09 -0000 @@ -254,16 +254,16 @@ function feeds_nodeapi(&$node, $op, $for try { $source->addConfig($node->feeds); // @todo: Too many indirections. Clean up. - $result = $source->importer->fetcher->fetch($source); - $result = $source->importer->parser->parse($result, $source); - if (!isset($result->value['title']) || trim($result->value['title']) == '') { + $feed = $source->importer->fetcher->fetch($source); + $source->importer->parser->parse($feed, $source); + if (!$feed->getTitle()) { form_set_error('title', t('Could not retrieve title from feed.'), 'error'); } else { // Keep the title in a static cache and populate $node->title on // 'presave' as node module looses any changes to $node after // 'validate'. - $last_title = $result->value['title']; + $last_title = $feed->getTitle(); } } catch (Exception $e) { Index: includes/FeedsFeed.inc =================================================================== RCS file: includes/FeedsFeed.inc diff -N includes/FeedsFeed.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/FeedsFeed.inc 12 Dec 2009 14:51:09 -0000 @@ -0,0 +1,147 @@ +url = $url; + $this->file_path = $file_path; + $this->items = array(); + } + + /** + * @return + * The raw content of the feed. + */ + public function getRaw() { + if (empty($this->raw)) { + // Prefer file. + if ($this->file_path) { + $this->raw = file_get_contents(realpath($this->file_path)); + } + elseif ($this->url) { + feeds_include_library('http_request.inc', 'http_request'); + $result = http_request_get($this->url); + if ($result->code != 200) { + throw new Exception(t('Download of @url failed with code !code.', array('@url' => $url, '!code' => $result->code))); + } + $this->raw = $result->data; + } + } + return $this->raw; + } + + /** + * @return + * Path to the feed. This path is relative to Drupal's root directory. + * If the feed is not local, getFilePath downloads it to file directory. + */ + public function getFilePath() { + if (!isset($this->file_path)) { + $dest = file_destination(file_directory_path() .'/feeds/'. get_class($this) .'_'. md5($this->url) .'_'. time(), FILE_EXISTS_RENAME); + $this->file_path = file_save_data($this->getRaw(), $dest); + if($this->file_path === 0) { + throw new Exception(t('Cannot write content to %dest', array('%dest' => $dest))); + } + } + return $this->file_path; + } + + /** + * @return + * URL to the document. + */ + public function getURL() { + if (!isset($this->url) && isset($this->file)) { + return $_GLOBALS['base_url'] .'/'. $this->file; + } + } + + /** + * @return + * A string that is the feed's title. + */ + public function getTitle() { + return $this->title; + } + + /** + * @return + * A string that is the feed's description. + */ + public function getDescription() { + return $this->description; + } + + /** + * @return + * A string that is the link to the feed's site (not the actual URL of the + * feed). Falls back to URL if not available. + */ + public function getLink() { + return isset($this->link) ? $this->link : $this->getURL(); + } + + /** + * @return + * Next available item or NULL if there is none. Every returned item is + * removed from the internal array. + */ + public function shiftItem() { + return array_shift($this->items); + } + + /** + * Set title. + */ + public function setTitle($title) { + $this->title = $title; + } + + /** + * Set description. + */ + public function setDescription($description) { + $this->description = $description; + } + + /** + * Set link. + */ + public function setLink($link) { + $this->link = $link; + } + + /** + * Set items. + */ + public function setItems($items) { + $this->items = $items; + } + + /** + * Add an item. + */ + public function addItem($item) { + $this->items[] = $item; + } +} Index: includes/FeedsImporter.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/includes/FeedsImporter.inc,v retrieving revision 1.6 diff -u -p -r1.6 FeedsImporter.inc --- includes/FeedsImporter.inc 12 Dec 2009 01:20:32 -0000 1.6 +++ includes/FeedsImporter.inc 12 Dec 2009 14:51:09 -0000 @@ -9,57 +9,7 @@ // Including FeedsImporter.inc automatically includes dependencies. require_once(dirname(__FILE__) .'/FeedsConfigurable.inc'); require_once(dirname(__FILE__) .'/FeedsSource.inc'); - -/** - * A Feeds result class. - * - * @see class FeedsFetcherResult - * @see class FeedsParserResult - */ -abstract class FeedsResult { - - // An array of valid values for $type. - protected $valid_types = array(); - // The type of this result. - protected $type; - // The value of this result. - protected $value; - - /** - * Constructor: create object, validate class variables. - * - * @param $value - * The value of this result. - * @param $type - * The type of this result. Must be one of $valid_types. - */ - public function __construct($value, $type) { - $this->__set('type', $type); - $this->__set('value', $value); - } - - /** - * Control access to class variables. - */ - public function __set($name, $value) { - if ($name == 'valid_types') { - throw new Exception(t('Cannot write FeedsResult::valid_types.')); - } - if ($name == 'type') { - if (!in_array($value, $this->valid_types)) { - throw new Exception(t('Invalid type "!type"', array('!type' => $value))); - } - } - $this->$name = $value; - } - - /** - * Control access to class variables. - */ - public function __get($name) { - return $this->$name; - } -} +require_once(dirname(__FILE__) .'/FeedsFeed.inc'); /** * Class defining an importer object. This is the main hub for Feeds module's Index: includes/FeedsSource.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/includes/FeedsSource.inc,v retrieving revision 1.4 diff -u -p -r1.4 FeedsSource.inc --- includes/FeedsSource.inc 12 Dec 2009 01:20:32 -0000 1.4 +++ includes/FeedsSource.inc 12 Dec 2009 14:51:09 -0000 @@ -107,9 +107,10 @@ class FeedsSource extends FeedsConfigura */ public function import() { try { - $result = $this->importer->fetcher->fetch($this); - $result = $this->importer->parser->parse($result, $this); - $this->importer->processor->process($result, $this); + $feed = $this->importer->fetcher->fetch($this); + $this->importer->parser->parse($feed, $this); + $this->importer->processor->process($feed, $this); + unset($feed); } catch (Exception $e) { drupal_set_message($e->getMessage(), 'error'); Index: plugins/FeedsCSVParser.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsCSVParser.inc,v retrieving revision 1.2 diff -u -p -r1.2 FeedsCSVParser.inc --- plugins/FeedsCSVParser.inc 20 Oct 2009 20:59:04 -0000 1.2 +++ plugins/FeedsCSVParser.inc 12 Dec 2009 14:51:09 -0000 @@ -9,18 +9,11 @@ class FeedsCSVParser extends FeedsParser /** * Parses a raw string and returns a Feed object from it. */ - public function parse(FeedsFetcherResult $fetcherResult, FeedsSource $source) { - feeds_include_library('ParserCSV.inc', 'ParserCSV'); - - if ($fetcherResult->type == 'text/filepath') { - $iterator = new ParserCSVIterator(realpath($fetcherResult->value)); - } - // @todo: write string buffer iterator. - else { - throw new Exception(t('You must use CSV Parser with File Fetcher.')); - } + public function parse(FeedsFeed $feed, FeedsSource $source) { // Parse. + feeds_include_library('ParserCSV.inc', 'ParserCSV'); + $iterator = new ParserCSVIterator(realpath($feed->getFilePath())); $source_config = $source->getConfigFor($this); $parser = new ParserCSV(); $parser->setDelimiter($source_config['delimiter']); @@ -44,8 +37,8 @@ class FeedsCSVParser extends FeedsParser } unset($rows); - // Return result. - return new FeedsParserResult(array('items' => $result_rows)); + // Populate feed. + $feed->setItems($result_rows); } /** Index: plugins/FeedsDataProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsDataProcessor.inc,v retrieving revision 1.5 diff -u -p -r1.5 FeedsDataProcessor.inc --- plugins/FeedsDataProcessor.inc 3 Dec 2009 21:27:40 -0000 1.5 +++ plugins/FeedsDataProcessor.inc 12 Dec 2009 14:51:09 -0000 @@ -14,12 +14,12 @@ class FeedsDataProcessor extends FeedsPr /** * Implementation of FeedsProcessor::process(). */ - public function process(FeedsParserResult $parserResult, FeedsSource $source) { + public function process(FeedsFeed $feed, FeedsSource $source) { // Count number of created and updated nodes. $inserted = $updated = 0; - foreach ($parserResult->value['items'] as $item) { + while ($item = $feed->shiftItem()) { if (!($id = $this->existingItemId($item, $source)) || $this->config['update_existing']) { // Map item to a data record, feed_nid and timestamp are mandatory. $data = array(); Index: plugins/FeedsFeedNodeProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsFeedNodeProcessor.inc,v retrieving revision 1.5 diff -u -p -r1.5 FeedsFeedNodeProcessor.inc --- plugins/FeedsFeedNodeProcessor.inc 12 Dec 2009 01:09:44 -0000 1.5 +++ plugins/FeedsFeedNodeProcessor.inc 12 Dec 2009 14:51:09 -0000 @@ -15,12 +15,12 @@ class FeedsFeedNodeProcessor extends Fee /** * Implementation of FeedsProcessor::process(). */ - public function process(FeedsParserResult $parserResult, FeedsSource $source) { + public function process(FeedsFeed $feed, FeedsSource $source) { // Count number of created and updated nodes. $created = $updated = 0; - foreach ($parserResult->value['items'] as $item) { + while ($item = $feed->shiftItem()) { // If the target item does not exist OR if update_existing is enabled, // map and save. Index: plugins/FeedsFetcher.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsFetcher.inc,v retrieving revision 1.1 diff -u -p -r1.1 FeedsFetcher.inc --- plugins/FeedsFetcher.inc 20 Oct 2009 21:03:08 -0000 1.1 +++ plugins/FeedsFetcher.inc 12 Dec 2009 14:51:09 -0000 @@ -2,17 +2,6 @@ // $Id: FeedsFetcher.inc,v 1.1 2009/10/20 21:03:08 alexb Exp $ /** - * Defines the object a Fetcher returns on fetch(). - */ -class FeedsFetcherResult extends FeedsResult { - // Define valid types. - // @todo: does text/filepath make sense? - // @todo: If convenient, we could expand on this concept and build content - // type negotiation between Fetchers and Parsers. - protected $valid_types = array('text/filepath', 'text/xml'); -} - -/** * Abstract class, defines shared functionality between fetchers. * * Implements FeedsSourceInfoInterface to expose source forms to Feeds. Index: plugins/FeedsFileFetcher.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsFileFetcher.inc,v retrieving revision 1.2 diff -u -p -r1.2 FeedsFileFetcher.inc --- plugins/FeedsFileFetcher.inc 20 Oct 2009 20:59:04 -0000 1.2 +++ plugins/FeedsFileFetcher.inc 12 Dec 2009 14:51:09 -0000 @@ -18,7 +18,7 @@ class FeedsFileFetcher extends FeedsFetc $source_config = $source->getConfigFor($this); // Just return path to file, contents can be read easily with // file_get_contents($file_path); - return new FeedsFetcherResult($source_config['source'], 'text/filepath'); + return new FeedsFeed(NULL, $source_config['source']); } /** Index: plugins/FeedsHTTPFetcher.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsHTTPFetcher.inc,v retrieving revision 1.5 diff -u -p -r1.5 FeedsHTTPFetcher.inc --- plugins/FeedsHTTPFetcher.inc 17 Nov 2009 20:14:30 -0000 1.5 +++ plugins/FeedsHTTPFetcher.inc 12 Dec 2009 14:51:09 -0000 @@ -22,19 +22,7 @@ class FeedsHTTPFetcher extends FeedsFetc */ public function fetch(FeedsSource $source) { $source_config = $source->getConfigFor($this); - $url = $source_config['source']; - - feeds_include_library('http_request.inc', 'http_request'); - if ($this->config['auto_detect_feeds']) { - $result = http_request_get_common_syndication($url); - } - else { - $result = http_request_get($url); - } - if ($result->code != 200) { - throw new Exception(t('Download of @url failed with code !code.', array('@url' => $url, '!code' => $result->code))); - } - return new FeedsFetcherResult($result->data, 'text/xml'); + return new FeedsFeed($source_config['source']); } /** Index: plugins/FeedsNodeProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsNodeProcessor.inc,v retrieving revision 1.17 diff -u -p -r1.17 FeedsNodeProcessor.inc --- plugins/FeedsNodeProcessor.inc 3 Dec 2009 20:55:05 -0000 1.17 +++ plugins/FeedsNodeProcessor.inc 12 Dec 2009 14:51:09 -0000 @@ -14,12 +14,12 @@ class FeedsNodeProcessor extends FeedsPr /** * Implementation of FeedsProcessor::process(). */ - public function process(FeedsParserResult $parserResult, FeedsSource $source) { + public function process(FeedsFeed $feed, FeedsSource $source) { // Count number of created and updated nodes. $created = $updated = 0; - foreach ($parserResult->value['items'] as $item) { + while ($item = $feed->shiftItem()) { // Create/update if item does not exist or update existing is enabled. if (!($nid = $this->existingItemId($item, $source)) || $this->config['update_existing']) { Index: plugins/FeedsOPMLParser.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsOPMLParser.inc,v retrieving revision 1.2 diff -u -p -r1.2 FeedsOPMLParser.inc --- plugins/FeedsOPMLParser.inc 2 Nov 2009 20:22:03 -0000 1.2 +++ plugins/FeedsOPMLParser.inc 12 Dec 2009 14:51:09 -0000 @@ -14,15 +14,11 @@ class FeedsOPMLParser extends FeedsParse /** * Parses a raw string and returns a Feed object from it. */ - public function parse(FeedsFetcherResult $fetcherResult, FeedsSource $source) { - if ($fetcherResult->type == 'text/filepath') { - $string = file_get_contents($fetcherResult->value); - } - else { - $string = $fetcherResult->value; - } + public function parse(FeedsFeed $feed, FeedsSource $source) { feeds_include_library('opml_parser.inc', 'opml_parser'); - return new FeedsParserResult(opml_parser_parse($string), 'syndication'); + $result = opml_parser_parse($feed->getRaw()); + $feed->setTitle($result['title']); + $feed->setItems($result['items']); } /** Index: plugins/FeedsParser.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsParser.inc,v retrieving revision 1.1 diff -u -p -r1.1 FeedsParser.inc --- plugins/FeedsParser.inc 20 Oct 2009 21:03:08 -0000 1.1 +++ plugins/FeedsParser.inc 12 Dec 2009 14:51:09 -0000 @@ -2,23 +2,6 @@ // $Id: FeedsParser.inc,v 1.1 2009/10/20 21:03:08 alexb Exp $ /** - * Defines the object a Parser returns on parser(). - */ -class FeedsParserResult extends FeedsResult { - // Define valid types. - // @todo: does this distinction make sense? We may be able to run with - // 'simple' and no special case for 'syndication'. - protected $valid_types = array('simple', 'syndication'); - - /** - * Override constructor to define a default type. - */ - public function __construct($value, $type = 'simple') { - parent::__construct($value, $type); - } -} - -/** * Abstract class, defines interface for parsers. * * @todo: make implement FeedsSourceInterface @@ -30,8 +13,8 @@ abstract class FeedsParser extends Feeds * * Stub method. Extending classes must implement this method. * - * @param $fetcherResult - * Content returned by fetcher. + * @param $feed + * Feed returned by fetcher. * @param FeedsSource $source * Source information. * @return @@ -40,7 +23,7 @@ abstract class FeedsParser extends Feeds * * @todo: Should it be execute() ? */ - public abstract function parse(FeedsFetcherResult $fetcherResult, FeedsSource $source); + public abstract function parse(FeedsFeed $feed, FeedsSource $source); /** * Clear all caches for results for given source. Index: plugins/FeedsProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsProcessor.inc,v retrieving revision 1.4 diff -u -p -r1.4 FeedsProcessor.inc --- plugins/FeedsProcessor.inc 31 Oct 2009 14:30:27 -0000 1.4 +++ plugins/FeedsProcessor.inc 12 Dec 2009 14:51:09 -0000 @@ -12,14 +12,14 @@ abstract class FeedsProcessor extends Fe * Process the result of the parser or previous processors. * Extending classes must implement this method. * - * @param FeedsParserResult $parserResult - * The result of the parsing stage. + * @param FeedsFeed $feed + * The feed passed in from the parsing stage. * @param FeedsSource $source * Source information about this import. * * @todo: Should it be execute()? */ - public abstract function process(FeedsParserResult $parserResult, FeedsSource $source); + public abstract function process(FeedsFeed $feed, FeedsSource $source); /** * Remove all stored results or stored results up to a certain time for this @@ -191,7 +191,7 @@ abstract class FeedsProcessor extends Fe * sources that are unique. * * @param $source_item - * A feed item from a FeedsParserResult. + * A feed item from a FeedsFeed. * * @return * An array where the keys are target field names and the values are the Index: plugins/FeedsSimplePieParser.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsSimplePieParser.inc,v retrieving revision 1.4 diff -u -p -r1.4 FeedsSimplePieParser.inc --- plugins/FeedsSimplePieParser.inc 2 Nov 2009 20:05:10 -0000 1.4 +++ plugins/FeedsSimplePieParser.inc 12 Dec 2009 14:51:09 -0000 @@ -11,18 +11,12 @@ class FeedsSimplePieParser extends Feeds /** * Parses a raw string and returns a Feed object from it. */ - public function parse(FeedsFetcherResult $fetcherResult, FeedsSource $source) { - if ($fetcherResult->type == 'text/filepath') { - $string = file_get_contents($fetcherResult->value); - } - else { - $string = $fetcherResult->value; - } + public function parse(FeedsFeed $feed, FeedsSource $source) { feeds_include_library('simplepie.inc', 'simplepie'); // Initialize SimplePie. $parser = new SimplePie(); - $parser->set_raw_data($string); + $parser->set_raw_data($feed->getRaw()); $parser->set_stupidly_fast(TRUE); $parser->encode_instead_of_strip(FALSE); // @todo: is caching effective when we pass in raw data? @@ -31,12 +25,10 @@ class FeedsSimplePieParser extends Feeds $parser->init(); // Construct the standard form of the parsed feed - $feed = array(); - $feed['title'] = ($title = $parser->get_title()) ? $title : $this->createTitle($parser->get_description()); - $feed['description'] = $parser->get_description(); - $feed['link'] = html_entity_decode($parser->get_link()); + $feed->setTitle(($title = $parser->get_title()) ? $title : $this->createTitle($parser->get_description())); + $feed->setDescription($parser->get_description()); + $feed->setLink(html_entity_decode($parser->get_link())); - $feed['items'] = array(); $items_num = $parser->get_item_quantity(); for ($i = 0; $i < $items_num; $i++) { $item = array(); @@ -96,11 +88,10 @@ class FeedsSimplePieParser extends Feeds $item['tags'] = $tags; // Stick the raw data onto the feed item. $item['raw'] = $simplepie_item->data; - $feed['items'][] = $item; + $feed->addItem($item); } // Release parser. unset($parser); - return new FeedsParserResult($feed, 'syndication'); } /** Index: plugins/FeedsSyndicationParser.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsSyndicationParser.inc,v retrieving revision 1.8 diff -u -p -r1.8 FeedsSyndicationParser.inc --- plugins/FeedsSyndicationParser.inc 2 Nov 2009 19:58:37 -0000 1.8 +++ plugins/FeedsSyndicationParser.inc 12 Dec 2009 14:51:09 -0000 @@ -11,15 +11,13 @@ class FeedsSyndicationParser extends Fee /** * Parses a raw string and returns a Feed object from it. */ - public function parse(FeedsFetcherResult $fetcherResult, FeedsSource $source) { - if ($fetcherResult->type == 'text/filepath') { - $string = file_get_contents($fetcherResult->value); - } - else { - $string = $fetcherResult->value; - } + public function parse(FeedsFeed $feed, FeedsSource $source) { feeds_include_library('common_syndication_parser.inc', 'common_syndication_parser'); - return new FeedsParserResult(common_syndication_parser_parse($string), 'syndication'); + $result = common_syndication_parser_parse($feed->getRaw()); + $feed->setTitle($result['title']); + $feed->setDescription($result['description']); + $feed->setLink($result['link']); + $feed->setItems($result['items']); } /** Index: plugins/FeedsTermProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsTermProcessor.inc,v retrieving revision 1.2 diff -u -p -r1.2 FeedsTermProcessor.inc --- plugins/FeedsTermProcessor.inc 2 Nov 2009 20:48:52 -0000 1.2 +++ plugins/FeedsTermProcessor.inc 12 Dec 2009 14:51:09 -0000 @@ -14,7 +14,7 @@ class FeedsTermProcessor extends FeedsPr /** * Implementation of FeedsProcessor::process(). */ - public function process(FeedsParserResult $parserResult, FeedsSource $source) { + public function process(FeedsFeed $feed, FeedsSource $source) { if (empty($this->config['vocabulary'])) { throw new Exception(t('You must define a vocabulary for Taxonomy term processor before importing.')); @@ -23,7 +23,7 @@ class FeedsTermProcessor extends FeedsPr // Count number of created and updated nodes. $created = $updated = $no_name = 0; - foreach ($parserResult->value['items'] as $item) { + while ($item = $feed->shiftItem()) { if (!($tid = $this->existingItemId($item, $source)) || $this->config['update_existing']) { Index: plugins/FeedsUserProcessor.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsUserProcessor.inc,v retrieving revision 1.2 diff -u -p -r1.2 FeedsUserProcessor.inc --- plugins/FeedsUserProcessor.inc 2 Nov 2009 20:26:57 -0000 1.2 +++ plugins/FeedsUserProcessor.inc 12 Dec 2009 14:51:09 -0000 @@ -14,12 +14,12 @@ class FeedsUserProcessor extends FeedsPr /** * Implementation of FeedsProcessor::process(). */ - public function process(FeedsParserResult $parserResult, FeedsSource $source) { + public function process(FeedsFeed $feed, FeedsSource $source) { // Count number of created and updated nodes. $created = $updated = $failed = 0; - foreach ($parserResult->value['items'] as $item) { + while ($item = $feed->shiftItem()) { if (!($uid = $this->existingItemId($item, $source)) || $this->config['update_existing']) {