Skip to content
Snippets Groups Projects
feed.inc 4.79 KiB
Newer Older
<?php
// $Id$
/**
 * @file
 */

/**
 * Importer class.
 * 
 * After fetch() has been invoked, it can be cached and revoked in a subsequent 
 * page callback until it is reset().
 */
class Feed extends FeedsConfigurable {

  public $fetcher, $parser, $processors; 

  /**
   * Instantiate class variables.
   */
  public function __construct($id, $config = NULL) {
    parent::__construct($id, $config);

    feeds_require_plugin($this->config['fetcher']);
    $this->fetcher = new $this->config['fetcher']($id);

    feeds_require_plugin($this->config['parser']);
    $this->parser = new $this->config['parser']($id);

    foreach ($this->config['processors'] as $processor) {
      feeds_require_plugin($processor);
      $this->processors[$processor] = new $processor($id);
    }
  }

  /**
   * Import feed by using configured fetchers, parsers, processors.
   */
  public function import() {
    $raw = $this->fetcher->fetch($this->source);
    $parsed = $this->parser->parse($raw);
    foreach ($this->processors as $processor) {
      $processor->process($parsed);
    }
  }

  /**
   * Set active fetcher. Does not save fetcher to configuration.
   *
   * @param $fetcher
   *   String that is the class name of the fetcher.
   */
  public function setFetcher($fetcher) {
    unset($this->fetcher);
    feeds_require_plugin($fetcher);
    $this->config['fetcher'] = $fetcher;
    $this->fetcher = new $fetcher($this->id);
  }

  /**
   * Set active parser. Does not save parser to configuration.
   *
   * @param $parser
   *   String that is the class name of the parser.
   */
  public function setParser($parser) {
    unset($this->parser);
    feeds_require_plugin($parser);
    $this->config['parser'] = $parser;
    $this->save();
    $this->parser = new $parser($this->id);
  }

  /**
   * Set active processors.
   *
   * @param $processors
   *  Array of strings that are the processors of this feed.
   */
  public function setProcessors($processors) {
    unset($this->processors);
    $this->processors = array();
    $this->config['processors'] = $processors;
    $this->save();
    foreach ($processors as $processor) {
      feeds_require_plugin($processor);
      $this->processors[] = new $processor($this->id);
    }
  }
}

/**
 * Base class for configurable, peristent objects.
 */
class FeedsConfigurable {
  protected $config;
  protected $id;

  /**
   * Constructor.
   *
   * @param $id
   *   String identifier of this object.
   * @param $config
   *   Configuration of this object. If not available, will attempt to load from database.
   */
  public function __construct($id, $config = NULL) {
    $this->id = $id;
    if (empty($config)) {
      $this->load();
    }
    else {
      $this->config = $config;
    }
  }

  /**
   * Save configuration.
   */
  public function save() {
    $save = new stdClass();
    $save->id = $this->id;
    $save->class = get_class($this);
    $save->config = $this->config;
    db_query('DELETE FROM {feeds_configuration} WHERE id = "%s"', $save->id);
    drupal_write_record('feeds_configuration', $save);
  }

  /**
   * Load configuration and unpack.
   */
  public function load() {
    ctools_include('export');
    if ($config = ctools_export_load_object('feeds_configuration', 'conditions', array('id' => $this->id, 'class' => get_class($this)))) {
      $config = array_shift($config);
      $this->config = $config->config;
      return TRUE;
    }
    return FALSE;
  }

  public function getConfig($fallback = TRUE) {
    if ($fallback) {
      return empty($this->config) ? $this->getDefaultConfig() : $this->config;
    }
    return $this->config;
  }

  public function setConfig($config) {
    $this->config = $config;
  }

  public function getDefaultConfig() {
    return array();
  }

  public function getId() {
    return $this->id;
  }

  public function form() {
    return array();
  }
}

/**
 * Abstract class, defines interface for fetchers.
 * 
 * Not using interfaces because we need a simple inheritence tree for determining the 
 * plugin type. See hook_feeds_plugin().
 */
class FeedsFetcher extends FeedsConfigurable {
  public function fetch($source) {
    return NULL;
  }
}

/**
 * Abstract class, defines interface for parsers.
 */
class FeedsParser extends FeedsConfigurable {
  public function parse($raw) {
    return NULL;
  }
  public function getMappingSources() {
    return NULL;
  }
}

/**
 * Abstract class, defines interface for processors.
 */
class FeedsProcessor extends FeedsConfigurable {
  public function process($feed) {
    return NULL;
  }
  public function getMappingTargets() {
    return NULL;
  }

  /**
   * Build the mapping form.
   */
  public function mappingForm() {
    return array();
  }

  /**
   * Return TRUE if processor requires that the feed configuration be attached to a feed node.
   */
  public function requiresFeedAsNode() {
    return TRUE;
  }
}