You are here

function _feedapi_invoke_refresh in FeedAPI 5

Same name and namespace in other branches
  1. 6 feedapi.module \_feedapi_invoke_refresh()

Helper function for feedapi_invoke(). Refresh the feed, call the proper parsers and processors' hooks. Don't call this function directly, use feedapi_refresh() instead.

@ TODO Fix: This may loop forever when a feed has no processors

1 call to _feedapi_invoke_refresh()
feedapi_invoke in ./feedapi.module
Invoke feedapi API callback functions.

File

./feedapi.module, line 1095
Handle the submodules (for feed and item processing) Provide a basic management of feeds

Code

function _feedapi_invoke_refresh(&$feed, $param) {
  $timestamp = variable_get('cron_semaphore', FALSE) !== FALSE ? variable_get('cron_semaphore', FALSE) : time();
  $counter = array();
  timer_start('feedapi_' . $feed->nid);
  $cron = $param;

  // Step 0: Check processors and parsers and grab settings
  if (!is_array($feed->processors) || count($feed->processors) == 0) {
    if (!$cron) {
      drupal_set_message(t("No processors specified for URL %url. Could not refresh.", array(
        '%url' => $feed->url,
      )), "error");
      drupal_goto('node/' . $feed->nid);
    }
    return 0;
  }
  else {
    if (!is_array($feed->parsers) || count($feed->parsers) == 0) {
      drupal_set_message(t("No parsers specified for URL %url. Could not refresh.", array(
        '%url' => $feed->url,
      )), "error");
      drupal_goto('node/' . $feed->nid);
    }
  }
  $settings = feedapi_get_settings(NULL, $feed->nid);

  // Step 1: Force processors to delete old items and determine the max. create elements.
  $counter['expired'] = feedapi_expire($feed);

  // Step 2: Get feed.
  $nid = $feed->nid;
  $hash_old = $feed->hash;
  $feed = _feedapi_call_parsers($feed, $feed->parsers, $feed->half_done);
  if (is_object($feed)) {
    $feed->hash = md5(serialize($feed->items));
  }

  // Step 3: See, whether feed has been modified.
  if ($feed === FALSE || $hash_old == $feed->hash) {

    // Updated the checked field in any case.
    db_query("UPDATE {feedapi} SET checked = %d, half_done = %d WHERE nid = %d", time(), FALSE, $nid);
    if (!$cron) {
      if ($hash_old == $feed->hash && is_object($feed)) {
        drupal_set_message(t('There are no new items in the feed.'), 'status');
      }
      else {
        drupal_set_message(t('Could not refresh feed.'), 'error');
      }
    }
    return $counter;
  }

  // Step 4: Walk through the items and check duplicates, then save or update
  $items = $feed->items;
  $updated = 0;
  $new = 0;
  $half_done = FALSE;

  // We check for time-out after each item
  foreach ($items as $index => $item) {

    // Call each item parser
    $item->is_updated = FALSE;
    $item->is_new = FALSE;
    foreach ($feed->processors as $processor) {
      if (!module_invoke($processor, 'feedapi_item', 'unique', $item, $feed->nid, $settings['processors'][$processor])) {
        if ($settings['update_existing'] == TRUE) {
          module_invoke($processor, 'feedapi_item', 'update', $item, $feed->nid, $settings['processors'][$processor]);
          $item->is_updated = TRUE;
        }
      }
      else {

        // We have checked before for expired items, so just save it.
        // if the item is already expired then do nothing
        $items_delete = $settings['items_delete'];
        $diff = abs(time() - (isset($item->options->timestamp) ? $item->options->timestamp : time()));
        if ($diff > $items_delete && $items_delete > FEEDAPI_NEVER_DELETE_OLD) {
          break;
        }
        $result = module_invoke($processor, 'feedapi_item', 'save', $item, $feed->nid, $settings['processors'][$processor]);
        if ($result !== FALSE) {
          $item->is_new = TRUE;
        }
      }
    }
    $new = $item->is_new ? $new + 1 : $new;
    $updated = $item->is_updated && !$item->is_new ? $updated + 1 : $updated;

    // Decision on time. If the exec time is greather than the user-set percentage of php max execution time
    if ($cron && !feedapi_cron_time()) {
      $half_done = $new + $updated == count($items) ? FALSE : TRUE;
      break;
    }

    // Save the item status for further processing
    $feed->items[$index] = $item;
  }

  // Closing step: Call after refresh and update feed statistics
  foreach (module_implements('feedapi_after_refresh') as $module) {
    $func = $module . '_feedapi_after_refresh';
    $func($feed);
  }
  if ($new > 0) {
    _feedapi_store_stat($nid, 'update_times', time(), $timestamp);
    _feedapi_store_stat($nid, 'new', $new, $timestamp);
    _feedapi_store_stat($nid, 'download_num', count($items), $timestamp);
    _feedapi_store_stat($nid, 'process_time', timer_read('feedapi_' . $feed->nid), $timestamp);
  }
  db_query("UPDATE {feedapi} SET checked = %d, half_done = %d, hash = '%s' WHERE nid = %d", time(), $half_done, $feed->hash, $feed->nid);
  if (!$cron) {
    if ($new == 0 && $updated == 0) {
      drupal_set_message(t('There are no new items in the feed.'), 'status');
    }
    else {
      drupal_set_message(t("%new new item(s) were saved. %updated existing item(s) were updated.", array(
        "%new" => $new,
        "%updated" => $updated,
      )));
    }

    // @ TODO what value to return here?
  }
  else {

    // Update and return counter
    $counter['new'] = $new;
    $counter['updated'] = $updated;
    return $counter;
  }
}