You are here

class FeedsFeedNodeProcessor in Feeds 6

Same name and namespace in other branches
  1. 7 plugins/FeedsFeedNodeProcessor.inc \FeedsFeedNodeProcessor

Creates *feed* nodes from feed items. The difference to FeedsNodeProcessor is that this plugin only creates nodes that are feed nodes themselves.

Hierarchy

Expanded class hierarchy of FeedsFeedNodeProcessor

2 string references to 'FeedsFeedNodeProcessor'
feeds_news_feeds_importer_default in feeds_news/feeds_news.feeds_importer_default.inc
Implementation of hook_feeds_importer_default().
_feeds_feeds_plugins in ./feeds.plugins.inc
Break out for feeds_feed_plugins().

File

plugins/FeedsFeedNodeProcessor.inc, line 12
Class definition of FeedsFeedNodeProcessor.

View source
class FeedsFeedNodeProcessor extends FeedsProcessor {

  /**
   * Implementation of FeedsProcessor::process().
   */
  public function process(FeedsImportBatch $batch, FeedsSource $source) {
    while ($item = $batch
      ->shiftItem()) {

      // If the target item does not exist OR if update_existing is enabled,
      // map and save.
      if (!($nid = $this
        ->existingItemId($batch, $source) || $this->config['update_existing'])) {

        // Map item to a node.
        $node = $this
          ->map($batch);

        // If updating populate nid and vid avoiding an expensive node_load().
        if (!empty($nid)) {
          $node->nid = $nid;
          $node->vid = db_result(db_query("SELECT vid FROM {node} WHERE nid = %d", $nid));
        }

        // Save the node.
        node_save($node);
        if ($nid) {
          $batch->updated++;
        }
        else {
          $batch->created++;
        }
      }
    }

    // Set messages.
    if ($batch->created) {
      drupal_set_message(format_plural($batch->created, 'Created @number @type node.', 'Created @number @type nodes.', array(
        '@number' => $batch->created,
        '@type' => $this->config['content_type'],
      )));
    }
    elseif ($batch->updated) {
      drupal_set_message(format_plural($batch->updated, 'Updated @number @type node.', 'Updated @number @type nodes.', array(
        '@number' => $batch->updated,
        '@type' => $this->config['content_type'],
      )));
    }
    else {
      drupal_set_message(t('There is no new content.'));
    }
  }

  /**
   * Implementation of FeedsProcessor::clear().
   */
  public function clear(FeedsBatch $batch, FeedsSource $source) {

    // Do not support deleting imported items as we would have to delete all
    // items of the content type we imported which may contain nodes that a
    // user created by hand.
    throw new Exception(t('This configuration does not support deleting imported items.'));
  }

  /**
   * Execute mapping on an item.
   */
  protected function map(FeedsImportBatch $batch, $target_node = NULL) {
    static $included;
    if (!$included) {
      module_load_include('inc', 'node', 'node.pages');
      $included = TRUE;
    }

    // Prepare node object.
    if (!isset($target_node)) {
      $target_node = new stdClass();
    }
    $target_node->type = $this->config['content_type'];
    $target_node->feeds = array();

    // Suppress auto import, we may be creating many feeds
    $target_node->feeds['suppress_import'] = TRUE;
    node_object_prepare($target_node);

    /*
    Assign an aggregated node always to current user.
    @todo This won't work in all cases as the assumption here is that
    import is happening one off when user is logged in. Assumption breaks if
    feed node processor is being used for aggregation on cron time and a
    specific user should still be the owner of the imported feed nodes.
    */
    global $user;
    $target_node->uid = $user->uid;

    // Have parent class do the iterating.
    return parent::map($batch, $target_node);
  }

  /**
   * Override parent::configDefaults().
   */
  public function configDefaults() {
    return array(
      'content_type' => '',
      'update_existing' => 0,
      'mappings' => array(),
    );
  }

  /**
   * Override parent::configForm().
   */
  public function configForm(&$form_state) {
    $feeds = feeds_importer_load_all();
    $types = array();
    foreach ($feeds as $feed) {
      if ($feed->id != $this->id && !empty($feed->config['content_type'])) {
        $types[$feed->config['content_type']] = node_get_types('name', $feed->config['content_type']);
      }
    }
    if (empty($types)) {
      $types[''] = t('No feed node content type available');
    }
    else {
      $types = array(
        '' => t('Select'),
      ) + $types;
    }
    $form = array();
    $form['content_type'] = array(
      '#type' => 'select',
      '#title' => t('Content type'),
      '#description' => t('Choose node type to create from this feed. Only node types with attached importer configurations are listed here. <strong>Note:</strong> Users with "import !feed_id feeds" permissions will be able to <strong>import</strong> nodes of the content type selected here regardless of the node level permissions. However, users with "clear !feed_id permissions" need to have sufficient node level permissions to delete the imported nodes.', array(
        '!feed_id' => $this->id,
      )),
      '#options' => $types,
      '#default_value' => $this->config['content_type'],
    );

    // @todo Implement real updating.
    $form['update_existing'] = array(
      '#type' => 'checkbox',
      '#title' => t('Replace existing feed nodes'),
      '#description' => t('If an existing node is found for an imported node, replace it. Existing nodes will be determined using mappings that are a "unique target".'),
      '#default_value' => $this->config['update_existing'],
    );
    return $form;
  }

  /**
   * Override setTargetElement to operate on a target item that is a node.
   */
  public function setTargetElement(&$target_node, $target_element, $value) {
    if ($target_element == 'source') {

      // Get the class of the feed node importer's fetcher and set the source
      // property. See feeds_nodeapi() how $node->feeds gets stored.
      $class = get_class($this
        ->feedNodeImporter()->fetcher);
      $target_node->feeds[$class]['source'] = $value;
    }
    elseif ($target_element == 'body') {
      $target_node->teaser = $value;
      $target_node->body = $value;
    }
    elseif (in_array($target_element, array(
      'title',
      'status',
      'created',
    ))) {
      $target_node->{$target_element} = $value;
    }
  }

  /**
   * Return available mapping targets.
   */
  public function getMappingTargets() {
    $targets = array(
      'title' => array(
        'name' => t('Title'),
        'description' => t('The title of the feed node.'),
      ),
      'status' => array(
        'name' => t('Published status'),
        'description' => t('Whether a feed node is published or not. 1 stands for published, 0 for not published.'),
      ),
      'created' => array(
        'name' => t('Published date'),
        'description' => t('The UNIX time when a node has been published.'),
      ),
      'body' => array(
        'name' => t('Body'),
        'description' => t('The body of the node. The teaser will be the same as the entire body.'),
      ),
      'source' => array(
        'name' => t('Feed source'),
        'description' => t('Depending on the selected fetcher, this could be for example a URL or a path to a file.'),
        'optional_unique' => TRUE,
      ),
    );
    return $targets;
  }

  /**
   * Get nid of an existing feed item node if available.
   */
  protected function existingItemId(FeedsImportBatch $batch, FeedsSource $source) {

    // We only support one unique target: source
    foreach ($this
      ->uniqueTargets($batch) as $target => $value) {
      if ($target == 'source') {
        return db_result(db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = '%s' AND fs.source = '%s'", $this
          ->feedNodeImporter()->id, $value));
      }
    }
    return 0;
  }

  /**
   * Helper for retrieving the importer object for the feed nodes to produce.
   */
  protected function feedNodeImporter() {
    if ($id = feeds_get_importer_id($this->config['content_type'])) {
      return feeds_importer($id);
    }
    else {
      throw new Exception(t('Content type to be created is not a valid Feed content type.'));
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FeedsConfigurable::$config protected property
FeedsConfigurable::$disabled protected property CTools export enabled status of this object.
FeedsConfigurable::$export_type protected property
FeedsConfigurable::$id protected property
FeedsConfigurable::addConfig public function Similar to setConfig but adds to existing configuration. 1
FeedsConfigurable::configFormSubmit public function Submission handler for configForm(). 3
FeedsConfigurable::configFormValidate public function Validation handler for configForm(). 3
FeedsConfigurable::copy public function Copy a configuration. 1
FeedsConfigurable::existing public function Determine whether this object is persistent and enabled. I. e. it is defined either in code or in the database and it is enabled. 1
FeedsConfigurable::getConfig public function Implementation of getConfig(). 1
FeedsConfigurable::instance public static function Instantiate a FeedsConfigurable object. 1
FeedsConfigurable::setConfig public function Set configuration. 1
FeedsConfigurable::__get public function Override magic method __get(). Make sure that $this->config goes through getConfig()
FeedsConfigurable::__isset public function Override magic method __isset(). This is needed due to overriding __get().
FeedsFeedNodeProcessor::clear public function Implementation of FeedsProcessor::clear(). Overrides FeedsProcessor::clear
FeedsFeedNodeProcessor::configDefaults public function Override parent::configDefaults(). Overrides FeedsProcessor::configDefaults
FeedsFeedNodeProcessor::configForm public function Override parent::configForm(). Overrides FeedsConfigurable::configForm
FeedsFeedNodeProcessor::existingItemId protected function Get nid of an existing feed item node if available. Overrides FeedsProcessor::existingItemId
FeedsFeedNodeProcessor::feedNodeImporter protected function Helper for retrieving the importer object for the feed nodes to produce.
FeedsFeedNodeProcessor::getMappingTargets public function Return available mapping targets. Overrides FeedsProcessor::getMappingTargets
FeedsFeedNodeProcessor::map protected function Execute mapping on an item. Overrides FeedsProcessor::map
FeedsFeedNodeProcessor::process public function Implementation of FeedsProcessor::process(). Overrides FeedsProcessor::process
FeedsFeedNodeProcessor::setTargetElement public function Override setTargetElement to operate on a target item that is a node. Overrides FeedsProcessor::setTargetElement
FeedsPlugin::hasSourceConfig public function Returns TRUE if $this->sourceForm() returns a form. Overrides FeedsSourceInterface::hasSourceConfig
FeedsPlugin::loadMappers protected static function Loads on-behalf implementations from mappers/ directory.
FeedsPlugin::save public function Save changes to the configuration of this object. Delegate saving to parent (= Feed) which will collect information from this object by way of getConfig() and store it. Overrides FeedsConfigurable::save
FeedsPlugin::sourceDefaults public function Implementation of FeedsSourceInterface::sourceDefaults(). Overrides FeedsSourceInterface::sourceDefaults 1
FeedsPlugin::sourceDelete public function A source is being deleted. Overrides FeedsSourceInterface::sourceDelete 1
FeedsPlugin::sourceForm public function Callback methods, exposes source form. Overrides FeedsSourceInterface::sourceForm 3
FeedsPlugin::sourceFormValidate public function Validation handler for sourceForm. Overrides FeedsSourceInterface::sourceFormValidate 2
FeedsPlugin::sourceSave public function A source is being saved. Overrides FeedsSourceInterface::sourceSave 1
FeedsPlugin::__construct protected function Constructor. Overrides FeedsConfigurable::__construct
FeedsProcessor::expire public function Delete feed items younger than now - $time. Do not invoke expire on a processor directly, but use FeedsImporter::expire() instead. 2
FeedsProcessor::expiryTime public function Per default, don't support expiry. If processor supports expiry of imported items, return the time after which items should be removed. 2
FeedsProcessor::getMappings public function Get mappings.
FeedsProcessor::uniqueTargets protected function Utility function that iterates over a target array and retrieves all sources that are unique.