You are here

feed_import.module in Feed Import 7

Same filename and directory in other branches
  1. 8 feed_import.module
  2. 7.3 feed_import.module
  3. 7.2 feed_import.module

User interface, cron functions for feed_import module

File

feed_import.module
View source
<?php

/**
 * @file
 * User interface, cron functions for feed_import module
 */

/**
 * This is path to feed import UI
 */
define('FEED_IMPORT_PATH', 'admin/config/services/feed_import');

/**
 * Implements hook_help().
 */
function feed_import_help($path, $arg) {
  if ($path == 'admin/help#feed_import') {
    $vars = array(
      '!file' => l('README.txt', drupal_get_path('module', 'feed_import') . '/README.txt'),
      '!project_page' => l('Feed Import', 'http://drupal.org/sandbox/SorinSarca/1331632'),
    );
    $help = t('Import content into entities from XML files using XPATH.');
    $help .= '<br />';
    $help .= t('For more info please read !file file or go to !project_page.', $vars);
    return $help;
  }
}

/**
 * Implements hook_permision().
 */
function feed_import_permission() {
  return array(
    'feed import permission' => array(
      'title' => t('Administer feed import settings'),
      'description' => t('Change settings for feed import'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function feed_import_menu() {

  // FEED_IMPORT_PATH is defined at the top of this file
  // This is used for arguments to know the position
  $submenus = substr_count(FEED_IMPORT_PATH, '/');
  $items = array();
  $items[FEED_IMPORT_PATH] = array(
    'title' => 'Feed Import',
    'description' => 'Configure feed import',
    'page callback' => 'feed_import_list_feeds',
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  $items[FEED_IMPORT_PATH . '/add'] = array(
    'title' => 'Add new feed',
    'description' => 'Add a new feed',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'feed_import_add_new_feed_form',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 1,
  );
  $items[FEED_IMPORT_PATH . '/import'] = array(
    'title' => 'Import feed',
    'description' => 'Import an existing feed',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'feed_import_import_feed_form',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 2,
  );
  $items[FEED_IMPORT_PATH . '/export/all'] = array(
    'title' => 'Export all feeds',
    'description' => 'Exports all feeds',
    'page callback' => 'feed_import_export_feed_page',
    'page arguments' => array(
      $submenus + 2,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 3,
  );
  $items[FEED_IMPORT_PATH . '/settings'] = array(
    'title' => 'Settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'feed_import_settings_form',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 4,
  );
  $items[FEED_IMPORT_PATH . '/export/%'] = array(
    'title' => 'Export feeds',
    'description' => 'Export feeds',
    'page callback' => 'feed_import_export_feed_page',
    'page arguments' => array(
      $submenus + 2,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_CALLBACK,
  );
  $items[FEED_IMPORT_PATH . '/process'] = array(
    'title' => 'Process feed',
    'page callback' => 'feed_import_process_feed',
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_CALLBACK,
  );
  $items[FEED_IMPORT_PATH . '/enable'] = array(
    'title' => 'Enable feed',
    'page callback' => 'feed_import_change_status',
    'page arguments' => array(
      'enable',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_CALLBACK,
  );
  $items[FEED_IMPORT_PATH . '/disable'] = array(
    'title' => 'Disable feed',
    'page callback' => 'feed_import_change_status',
    'page arguments' => array(
      'disable',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_CALLBACK,
  );
  $items[FEED_IMPORT_PATH . '/delete'] = array(
    'title' => 'Delete feed',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'feed_import_delete_feed_form',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_CALLBACK,
  );
  $items[FEED_IMPORT_PATH . '/edit/%/feed'] = array(
    'title' => 'Edit feed',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'feed_import_edit_feed_form',
      $submenus + 2,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_LOCAL_TASK,
    'tab_root' => FEED_IMPORT_PATH . '/edit/%',
    'weight' => 1,
  );
  $items[FEED_IMPORT_PATH . '/edit/%/pre-filter'] = array(
    'title' => 'Edit pre-filters',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'feed_import_edit_filter_form',
      '#pre_filter',
      $submenus + 2,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_LOCAL_TASK,
    'tab_root' => FEED_IMPORT_PATH . '/edit/%',
    'weight' => 2,
  );
  $items[FEED_IMPORT_PATH . '/edit/%/filter'] = array(
    'title' => 'Edit filters',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'feed_import_edit_filter_form',
      '#filter',
      $submenus + 2,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'feed import permission',
    ),
    'type' => MENU_LOCAL_TASK,
    'tab_root' => FEED_IMPORT_PATH . '/edit/%',
    'weight' => 3,
  );
  return $items;
}

/**
 * Implements hook_feed_import_process_info().
 */
function feed_import_feed_import_process_info() {

  // Return default process functions located in FeedImport class
  return array(
    'processFeedNormal' => array(
      'FeedImport',
      'processFeedNormal',
    ),
    'processFeedChunked' => array(
      'FeedImport',
      'processFeedChunked',
    ),
  );
}

/**
 * Implements hook_entity_delete().
 */
function feed_import_entity_delete($entity, $type) {
  $info = FeedImport::getEntityInfo($type);
  $id = $entity->{$info['column']};
  if ($id && is_numeric($id)) {
    feed_import_add_to_delete($id, $type);
  }
}

/**
 * Schedule an item for removing from feed import items at the end of the script
 * @param int $id
 *   Entity id
 * @param string $type
 *   Entity name
 */
function feed_import_add_to_delete($id = NULL, $type = NULL) {

  // ids to delete
  static $ids = array();

  // if delete function is registered at shutdown
  static $registered = FALSE;
  if (!$registered) {

    // Register shutdown function
    drupal_register_shutdown_function(__FUNCTION__, NULL);
    $registered = TRUE;
  }

  // NULL means function is called at shutdown
  // so delete items
  if ($id == NULL) {
    FeedImport::deleteItemsbyEntityId($ids);

    // Reset ids
    $ids = array();
  }
  else {

    // Just add to entities array an integer id
    $ids[$type][] = (int) $id;
  }
}

/**
 * Implements hook_cron().
 */
function feed_import_cron() {

  // Check if cron import is enabled
  if (variable_get('feed_import_use_cron', FALSE)) {

    // Check if there is an already running import or there are no feeds because
    // overlapping an import for the same entity is bad
    if (!variable_get('feed_import_import_running', FALSE)) {
      $last_executed = variable_get('feed_import_last_executed_import', 0);
      $time_between = variable_get('feed_import_time_between_imports', 3600);

      // Check if time between imports elapsed
      if ($last_executed + $time_between < REQUEST_TIME) {
        $feeds = FeedImport::loadFeeds(TRUE);
        if (!empty($feeds)) {
          $feed_names = array_keys($feeds);
          $last_feed = variable_get('feed_import_last_imported_feed', '');
          if ($last_feed == '') {
            $last_feed = 0;
          }
          else {
            $last_feed = (array_search($last_feed, $feed_names) + 1) % count($feed_names);
          }
          $last_feed = $feed_names[$last_feed];
          $feeds = $feeds[$last_feed];
          variable_set('feed_import_last_imported_feed', $last_feed);
          variable_set('feed_import_last_executed_import', REQUEST_TIME);

          // Mark import as running
          variable_set('feed_import_import_running', TRUE);

          // Process feed
          feed_import_import_items($feeds);

          // Change running status
          variable_set('feed_import_import_running', FALSE);
          unset($feeds, $feed_names, $last_feed);
        }
      }
    }
  }

  // Delete expired items
  $ids = FeedImport::getExpiredItems(variable_get('feed_import_delete_items_per_cron', 300));
  feed_import_delete_items($ids);
  unset($ids);
}

/**
 * Import feed and set report
 * @param array &$feed
 *   Feed info array
 */
function feed_import_import_items(&$feed) {

  // Process feed
  FeedImport::processFeed($feed);

  // Get generated report
  $report = FeedImport::$report;

  // Reset feed report
  FeedImport::$report = array();

  // Set report message
  $msg = 'Feed %feed imported.
          Started %started, file downloaded & parsed %parse,
          processing items %process, total duration %time,
          total feed items %total, rescheduled %rescheduled,
          updated %updated, new %new, not imported %skipped.
          !errors';
  if (!empty($report['errors'])) {
    $report['errors'] = array(
      'rows' => $report['errors'],
      'header' => array(
        t('Error'),
        t('Error number'),
        t('Line'),
        t('File'),
      ),
    );
    $report['errors'] = theme('table', $report['errors']);
  }
  else {
    $report['errors'] = '';
  }
  $info = array(
    '%feed' => $feed['name'],
    '%started' => date('d/m/Y H:i:s', $report['start']),
    '%time' => gmdate('H:i:s', $report['time']),
    '%parse' => gmdate('H:i:s', $report['parse']),
    '%process' => gmdate('H:i:s', $report['time'] - $report['parse']),
    '%total' => $report['total'],
    '%rescheduled' => $report['rescheduled'],
    '%updated' => $report['updated'],
    '%new' => $report['new'],
    '%skipped' => $report['total'] - ($report['updated'] + $report['rescheduled'] + $report['new']),
    '!errors' => '<br />' . $report['errors'],
  );
  watchdog('feed_import_info', $msg, $info, $report['errors'] ? WATCHDOG_WARNING : WATCHDOG_NOTICE);
}

/**
 * Delete feed items and set report
 * @param array &$items
 *   Array of entity ids keyed by entity type
 */
function feed_import_delete_items(&$items) {
  $start = time();
  $ids = array();

  // Get deleted ids
  foreach ($items as $type => &$value) {
    $value = FeedImport::entityDelete($type, $value);
    if (!isset($ids[$type])) {
      $ids[$type] = $value;
    }
    else {
      $ids[$type] += $value;
    }
    $value = NULL;
  }
  unset($items);
  if (empty($ids)) {
    return;
  }

  // Delete items from feed_import_hashes
  FeedImport::deleteItemsbyEntityId($ids);

  // Count deleted items for each entity
  foreach ($ids as $type => &$id) {
    $id = count($id) . ' ' . $type . ' ' . t('items');
  }
  $ids = implode(', ', $ids);

  // Set report message only if we deleted items
  $msg = 'Deleted %items. Started %started, duration %time';
  $info = array(
    '%items' => $ids,
    '%started' => date('d/m/Y H:i:s', $start),
    '%time' => gmdate('H:i:s', time() - $start),
  );
  watchdog('feed_import_info', $msg, $info);
}

/**
 * Settings form
 */
function feed_import_settings_form($form, &$form_state) {
  $form['feed_import_use_cron'] = array(
    '#type' => 'checkbox',
    '#default_value' => variable_get('feed_import_use_cron', 0),
    '#title' => t('Cron import'),
    '#description' => t('Run import for enabled feeds at cron'),
  );
  $form['feed_import_time_between_imports'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_time_between_imports', 3600),
    '#title' => t('Time between two imports at cron (seconds)'),
    '#description' => t('Time betwen two cron imports.'),
  );
  $form['feed_import_delete_items_per_cron'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_delete_items_per_cron', 300),
    '#title' => t('Expired items delete per cron (seconds)'),
    '#description' => t('How many expired items to delete when cron runs.'),
  );
  $form['feed_import_insert_hashes_chunk'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_insert_hashes_chunk', 500),
    '#title' => t('Chunk size for inserting hashes'),
    '#description' => t('How many items to insert at once'),
  );
  $form['feed_import_update_ids_chunk'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_update_ids_chunk', 1000),
    '#title' => t('Chunk size for updating expire time'),
    '#description' => t('How many items to update at once'),
  );
  $form['feed_import_hash_property'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_hash_property', '_feed_item_hash'),
    '#title' => t('Tomporary property wich holds item hash'),
    '#description' => t('Change this only if you already have a property named like this.'),
  );
  $form['feed_import_field_param_name'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_field_param_name', '[field]'),
    '#title' => t('Param name for filters'),
    '#description' => t('Enter this when using filters and you want to send extracted field value as argument.'),
  );
  $form['feed_import_entity_info_keep'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_entity_info_keep', 0),
    '#title' => t('Keep entity info in cache (seconds)'),
    '#description' => t('Entity info is used for UI'),
  );
  $form['feed_import_processFeedChunked_xml_head'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_processFeedChunked_xml_head', '<?xml version="1.0" encoding="utf-8"?>'),
    '#title' => t('If you use processFeedChunked function then set xml properties'),
    '#description' => t('Change xml properties like encoding.'),
  );
  $form['feed_import_processFeedChunked_chunk_length'] = array(
    '#type' => 'textfield',
    '#default_value' => variable_get('feed_import_processFeedChunked_chunk_length', 8192),
    '#title' => t('If you use processFeedChunked function then set chunk size in bytes'),
    '#description' => t('How many bytes to read in each chunk (default 8192 = 8k)'),
  );
  return system_settings_form($form);
}

/**
 * Settings form validate
 */
function feed_import_settings_form_validate($form, &$form_state) {
  $numeric_fields = array(
    'feed_import_time_between_imports',
    'feed_import_delete_items_per_cron',
    'feed_import_insert_hashes_chunk',
    'feed_import_update_ids_chunk',
    'feed_import_entity_info_keep',
    'feed_import_processFeedChunked_chunk_length',
  );

  // Checking numeric fields
  foreach ($numeric_fields as &$field) {
    if (!is_numeric($form_state['values'][$field])) {
      form_error($form[$field], t('Field value must be numeric.'));
    }
  }

  // Checking hash property field (this must be a variable name)
  if (!preg_match("/^[A-Za-z_][A-Za-z0-9_]*\$/", $form_state['values']['feed_import_hash_property'])) {
    form_error($form['feed_import_hash_property'], t('This must be a valid variable name.'));
  }

  // Checking xml head
  if (!preg_match("/^\\<\\?xml (.*)\\?\\>\$/", $form_state['values']['feed_import_processFeedChunked_xml_head'])) {
    form_error($form['feed_import_processFeedChunked_xml_head'], t('Invalid XML head.'));
  }
}

/**
 * List all feeds
 *
 * @return string
 *   A formatted table containing all feeds
 */
function feed_import_list_feeds() {

  // Load all feeds
  $feeds = FeedImport::loadFeeds();
  $rows = array();
  foreach ($feeds as &$feed) {
    $feed['name'] = l($feed['name'], FEED_IMPORT_PATH . '/edit/' . $feed['id'] . '/feed');
    $feed['url'] = l($feed['url'], $feed['url'], array(
      'attributes' => array(
        'target' => '_new',
      ),
    ));
    if ($feed['enabled']) {
      $enabled = TRUE;
      $feed['enabled'] = t('Yes') . ' ' . l('Disable', FEED_IMPORT_PATH . '/disable/' . $feed['id']);
    }
    else {
      $enabled = FALSE;
      $feed['enabled'] = t('No') . ' ' . l('Enable', FEED_IMPORT_PATH . '/enable/' . $feed['id']);
    }

    // Add operations
    $feed['operations']['edit'] = l(t('Edit'), FEED_IMPORT_PATH . '/edit/' . $feed['id'] . '/feed');
    $feed['operations']['process'] = l(t('Process'), FEED_IMPORT_PATH . '/process/' . $feed['id']);
    $feed['operations']['export'] = l(t('Export'), FEED_IMPORT_PATH . '/export/' . $feed['id']);
    $feed['operations']['delete'] = l(t('Delete'), FEED_IMPORT_PATH . '/delete/' . $feed['id']);
    $rows[] = array(
      'data' => array(
        $feed['name'],
        $feed['url'],
        $feed['enabled'],
        $feed['operations']['edit'],
        $feed['operations']['process'],
        $feed['operations']['export'],
        $feed['operations']['delete'],
      ),
      'class' => array(
        $enabled ? 'enabled-feed' : 'disabled-feed',
      ),
    );
  }

  // Path to CSS file
  $path = drupal_get_path('module', 'feed_import') . '/feed_import.css';
  return array(
    '#theme' => 'table',
    '#header' => array(
      t('Name'),
      t('Url'),
      t('Enabled'),
      array(
        'data' => t('Operations'),
        'colspan' => 4,
      ),
    ),
    '#rows' => $rows,
    '#empty' => t('There are no feeds.'),
    '#attached' => array(
      'css' => array(
        $path => array(
          'type' => 'file',
        ),
      ),
    ),
  );
}

/**
 * Processes a feed
 *
 * @param int $id
 *   Feed id to process
 */
function feed_import_process_feed($id = 0) {
  $err = FALSE;
  if ($id) {
    $feed = FeedImport::loadFeeds(FALSE, $id);
    if (!empty($feed)) {
      feed_import_import_items($feed);
      drupal_set_message(t('Feed @name processed!', array(
        '@name' => $feed['name'],
      )));
    }
    else {
      $err = TRUE;
    }
  }
  else {
    $err = TRUE;
  }
  if ($err) {
    drupal_set_message(t('Feed cannot be processed!'), 'error');
  }
  drupal_goto(FEED_IMPORT_PATH);
}

/**
 * Export feed
 *
 * @param int $id
 *   Feed id to be exported
 *
 * @return string
 *   A textarea containing serialized feed code
 */
function feed_import_export_feed_page($id = 0) {
  if ($id == 'all') {
    $feed = FeedImport::loadFeeds(FALSE);
  }
  else {
    $feed = FeedImport::loadFeeds(FALSE, $id);
    if (!$feed) {
      return MENU_NOT_FOUND;
    }
  }

  // Set page title
  drupal_set_title(t('Copy and save all code below. Paste it where you want to import feed.'));
  $feed = serialize($feed);
  return array(
    '#theme' => 'textarea',
    '#value' => $feed,
    '#rows' => 20,
  );
}

/**
 * Feed import form
 */
function feed_import_import_feed_form($form, &$form_state) {
  $form['code'] = array(
    '#type' => 'textarea',
    '#title' => t('Paste your code here'),
    '#rows' => 10,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Start import'),
  );
  return $form;
}

/**
 * Feed import form validate
 */
function feed_import_import_feed_form_validate($form, &$form_state) {

  // This is to silence unserialize warning
  $ok = @unserialize(trim($form_state['values']['code']));
  if (!$ok) {
    form_error($form['code'], t("Code couldn't be imported!"));
  }
}

/**
 * Feed import form submit
 */
function feed_import_import_feed_form_submit($form, &$form_state) {

  // Silence unserialize warning
  $feeds = @unserialize($form_state['values']['code']);

  // There is only one feed
  if (isset($feeds['xpath']['#root'])) {
    $feeds['enabled'] = 0;
    FeedImport::saveFeed($feeds);
    drupal_set_message(t('Feed @name was imported and disabled', array(
      '@name' => $feeds['name'],
    )));
  }
  else {
    $names = array();
    foreach ($feeds as &$feed) {
      $feed['enabled'] = 0;
      FeedImport::saveFeed($feed);
      $names[] = $feed['name'];
      $feed = NULL;
    }
    $names = implode(', ', $names);
    drupal_set_message(t('Feeds @names were imported and disabled', array(
      '@names' => $names,
    )));
  }
  drupal_goto(FEED_IMPORT_PATH);
}

/**
 * Add a new feed form
 */
function feed_import_add_new_feed_form($form, &$form_state) {
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Feed name'),
    '#description' => t('This usually is source name.'),
    '#required' => TRUE,
  );
  $entities = FeedImport::getEntityInfo();
  $options = array();
  foreach ($entities as &$entity) {
    $options[$entity['name']] = $entity['name'];
  }
  $form['entity'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#default_value' => 'node',
    '#title' => t('Entity name'),
    '#description' => t('Entity where you want to import content. Ex: "node"'),
    '#required' => TRUE,
  );
  $form['url'] = array(
    '#type' => 'textfield',
    '#title' => t('URL to XML feed'),
    '#description' => t('Please use a valid url that returns a valid xml file!'),
    '#required' => TRUE,
  );
  $options = array();
  $functions = array_keys(FeedImport::processFunctions());
  foreach ($functions as $f) {
    $options[$f] = $f;
  }
  $form['process_function'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#title' => t('Select feed processing function'),
    '#description' => t('Read help for more information about processing functions'),
  );
  $form['time'] = array(
    '#type' => 'textfield',
    '#title' => t('Keep imported items (seconds)'),
    '#description' => t('This is used to delete items after expiration.'),
    '#default_value' => 0,
    '#required' => TRUE,
  );
  $form['enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Feed is active'),
    '#default_value' => 0,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Add feeed'),
  );
  return $form;
}

/**
 * Add new feed form validate
 */
function feed_import_add_new_feed_form_validate($form, &$form_state) {
  $feeds = FeedImport::loadFeeds();
  if (isset($feeds[$form_state['values']['name']])) {
    form_error($form['name'], t('Feed name already exists!'));
  }
}

/**
 * Add new feed form submit
 */
function feed_import_add_new_feed_form_submit($form, &$form_state) {
  $entity = FeedImport::getEntityInfo($form_state['values']['entity']);
  $feed = array(
    'name' => $form_state['values']['name'],
    'url' => $form_state['values']['url'],
    'time' => (int) $form_state['values']['time'],
    'enabled' => (int) $form_state['values']['enabled'],
    'entity_info' => array(
      '#entity' => $form_state['values']['entity'],
      '#table_pk' => $entity['column'],
    ),
    'xpath' => array(
      '#root' => '// ?',
      '#uniq' => '?',
      '#process_function' => $form_state['values']['process_function'],
      '#items' => array(),
    ),
  );

  // Save feed
  FeedImport::saveFeed($feed);
  drupal_set_message(t('Feed @name was created', array(
    '@name' => $form_state['values']['name'],
  )));
  drupal_goto(FEED_IMPORT_PATH);
}

/**
 * Enable/disable feeds
 * @param string $how
 *   enable/disable options
 * @param int $id
 *   Feed id to enable or disable
 */
function feed_import_change_status($how, $id = 0) {
  $id = (int) $id;
  if ($id) {
    $how = $how == 'enable' ? 1 : 0;
    db_update('feed_import_settings')
      ->fields(array(
      'enabled' => $how,
    ))
      ->condition('id', $id, '=')
      ->execute();
    drupal_set_message($how ? t('Feed enabled') : t('Feed disabled'));
  }
  drupal_goto(FEED_IMPORT_PATH);
}

/**
 * Feed delete form
 */
function feed_import_delete_feed_form($form, &$form_state, $id = 0) {
  if (!$id) {
    drupal_set_message(t("Feed doesn't exist!"), 'error');
    drupal_goto(FEED_IMPORT_PATH);
    return;
  }
  $form['id'] = array(
    '#type' => 'value',
    '#value' => $id,
  );
  return confirm_form($form, t('This action cannot be undone!'), FEED_IMPORT_PATH);
}

/**
 * Feed delete form submit
 */
function feed_import_delete_feed_form_submit($form, &$form_state) {
  db_delete('feed_import_settings')
    ->condition('id', $form_state['values']['id'], '=')
    ->execute();
  db_delete('feed_import_hashes')
    ->condition('feed_id', $form_state['values']['id'], '=')
    ->execute();
  drupal_set_message(t('Feed deleted!'));
  drupal_goto(FEED_IMPORT_PATH);
}

/**
 * Edit feed form
 */
function feed_import_edit_feed_form($form, &$form_state, $id) {

  // Get feed
  $id = (int) $id;
  $feed = FeedImport::loadFeeds(FALSE, $id);
  if (!$feed) {
    drupal_set_message(t("Feed doesn't exist!"), 'error');
    return;
  }

  // Set page title
  drupal_set_title(t('Edit feed @name', array(
    '@name' => $feed['name'],
  )), PASS_THROUGH);

  // Basic feed fields
  $form['id'] = array(
    '#type' => 'value',
    '#value' => $feed['id'],
  );
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Feed name'),
    '#description' => t('This usually is source name.'),
    '#default_value' => $feed['name'],
    '#required' => TRUE,
  );
  $options = array();
  $entities = FeedImport::getEntityInfo();
  foreach ($entities as &$entity) {
    $options[$entity['name']] = $entity['name'];
  }
  if (!isset($feed['entity_info']['#entity']) || empty($feed['entity_info']['#entity'])) {
    $feed['entity_info']['#entity'] = 'node';
  }
  $form['entity'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#default_value' => isset($feed['entity_info']['#entity']) ? $feed['entity_info']['#entity'] : 'node',
    '#title' => t('Entity name'),
    '#description' => t('Entity where you want to import content. Ex: "node"'),
    '#required' => TRUE,
    '#disabled' => is_array($feed['xpath']['#items']) ? count($feed['xpath']['#items']) : 0,
  );
  $form['url'] = array(
    '#type' => 'textfield',
    '#title' => t('URL to XML feed'),
    '#description' => t('Please use a valid url that returns a valid XML file!'),
    '#default_value' => $feed['url'],
    '#required' => TRUE,
  );
  $options = array();
  $functions = array_keys(FeedImport::processFunctions());
  foreach ($functions as $f) {
    $options[$f] = $f;
  }
  $form['process_function'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#default_value' => isset($feed['xpath']['#process_function']) ? $feed['xpath']['#process_function'] : 'processFeedNormal',
    '#title' => t('Select process function'),
  );
  $form['time'] = array(
    '#type' => 'textfield',
    '#title' => t('Keep imported items (seconds)'),
    '#description' => t("This is used to delete items after expiration. 0 means item don't expire."),
    '#default_value' => $feed['time'],
    '#required' => TRUE,
  );
  $form['enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Feed is active'),
    '#default_value' => $feed['enabled'],
  );

  // XPATH settings fieldset
  $form['xpath'] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#title' => t('XPATH settings'),
  );
  $form['xpath']['root'] = array(
    '#type' => 'textfield',
    '#default_value' => isset($feed['xpath']['#root']) ? $feed['xpath']['#root'] : '',
    '#title' => t('Enter xpath item parent'),
    '#description' => t("Usualy this starts with // and it's base query (context for all items)."),
    '#required' => TRUE,
  );
  $form['xpath']['uniq'] = array(
    '#type' => 'textfield',
    '#default_value' => isset($feed['xpath']['#uniq']) ? $feed['xpath']['#uniq'] : '',
    '#title' => t('Enter xpath to a unique identifier of item'),
    '#description' => t("This is unique per item. Usually it's an ID."),
    '#required' => TRUE,
  );

  // XPATH items
  $form['xpath']['items'] = array(
    '#type' => 'container',
    '#attributes' => array(
      'id' => 'xpath_items',
    ),
    '#prefix' => '<label for="xpath_items">' . t('Current fields') . '</label>',
  );
  $xpaths = array();
  if (isset($form_state['#current_item'])) {
    for ($i = 0; $i <= $form_state['#current_item']; $i++) {
      if (isset($form_state['values']['xpath_' . $i])) {
        $default_val = isset($form_state['values']['xpath_' . $i]) ? $form_state['values']['xpath_' . $i] : '';
        if (is_array($default_val)) {
          $default_val = implode(PHP_EOL, $default_val);
        }
        $vars = array(
          '#field' => $form_state['complete form']['xpath']['items']['container_' . $i]['#title'],
          '#xpath' => $default_val,
          '#default_value' => isset($form_state['values']['default_' . $i]) ? $form_state['values']['default_' . $i] : '',
          '#default_action' => isset($form_state['values']['default_action_' . $i]) ? $form_state['values']['default_action_' . $i] : '',
        );
        $xpaths += feed_import_generate_xpath_item($i, $vars);
      }
    }
  }
  else {
    $form_state['#current_item'] = -1;
    if (!empty($feed['xpath']['#items'])) {
      foreach ($feed['xpath']['#items'] as &$field) {
        $form_state['#current_item']++;
        $xpaths += feed_import_generate_xpath_item($form_state['#current_item'], $field, TRUE);
      }
    }
  }
  $cbk = isset($form_state['triggering_element']['#parents'][0]) ? $form_state['triggering_element']['#parents'][0] : '';
  switch (TRUE) {
    case $cbk == 'add_new_item':
      $form_state['#current_item']++;
      $vars = array(
        '#field' => $form_state['values']['add_new_item_field'],
      );
      $xpaths += feed_import_generate_xpath_item($form_state['#current_item'], $vars);
      break;
    case preg_match('/remove_container_([0-9]{1,9})/', $cbk, $match):

      // Delete container
      unset($xpaths['container_' . $match[1]]);
      break;
  }
  $form['xpath']['items'] += $xpaths;
  unset($xpaths);

  // Add new name
  $fields_options = array();
  foreach ($entities[$feed['entity_info']['#entity']]['columns'] as $f => &$v) {
    if (!isset($feed['xpath']['#items'][$f])) {
      $fields_options[$f] = $f;
    }
  }
  $form['xpath']['add_new_item_field'] = array(
    '#type' => 'select',
    '#options' => $fields_options,
    '#title' => t('Add new field'),
    '#description' => t('Select field name and click "' . t('Add field') . '" button'),
  );

  // Add new item button
  $form['xpath']['add_new_item'] = array(
    '#type' => 'button',
    '#value' => t('Add selected field'),
    '#inline' => TRUE,
    '#ajax' => array(
      'event' => 'click',
      'callback' => 'feed_import_ajax_add_new_item',
      'wrapper' => 'xpath_items',
      'method' => 'append',
    ),
  );

  // Submit buttons
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save feed'),
  );
  $form['cancel'] = array(
    '#type' => 'submit',
    '#value' => t('Cancel'),
  );

  // Add js
  $form['#attached'] = array(
    'js' => array(
      drupal_get_path('module', 'feed_import') . '/feed_import.js' => array(
        'type' => 'file',
      ),
    ),
  );
  return $form;
}

/**
 * Edit feed form validate
 */
function feed_import_edit_feed_form_validate($form, &$form_state) {

  // Cancel button pressed
  $but = isset($form_state['clicked_button']['#parents'][0]) ? $form_state['clicked_button']['#parents'][0] : '';
  if ($but == 'cancel') {
    drupal_goto(FEED_IMPORT_PATH);
  }
}

/**
 * Edit feed form submit
 */
function feed_import_edit_feed_form_submit($form, &$form_state) {
  $values =& $form_state['values'];
  $feed = FeedImport::loadFeeds(FALSE, $values['id']);
  $entity = FeedImport::getEntityInfo($values['entity']);
  $items = array();
  for ($i = 0; $i <= $form_state['#current_item']; $i++) {
    if (isset($form_state['complete form']['xpath']['items']['container_' . $i]['#title'])) {
      $field = $form_state['complete form']['xpath']['items']['container_' . $i]['#title'];
    }
    else {
      continue;
    }
    if ($field && array_key_exists($field, $entity['columns'])) {
      $items[$field] = array(
        '#field' => $field,
        '#column' => $entity['columns'][$field],
        '#xpath' => explode(PHP_EOL, $values['xpath_' . $i]),
        '#default_value' => $values['default_' . $i],
        '#default_action' => $values['default_action_' . $i],
        '#filter' => isset($feed['xpath']['#items'][$field]['#filter']) ? $feed['xpath']['#items'][$field]['#filter'] : array(),
        '#pre_filter' => isset($feed['xpath']['#items'][$field]['#pre_filter']) ? $feed['xpath']['#items'][$field]['#pre_filter'] : array(),
      );
    }
  }
  $feed = array(
    'id' => (int) $values['id'],
    'name' => $values['name'],
    'url' => $values['url'],
    'time' => (int) $values['time'],
    'enabled' => (int) $values['enabled'],
    'entity_info' => array(
      '#entity' => $values['entity'],
      '#table_pk' => $entity['column'],
    ),
    'xpath' => array(
      '#root' => $values['root'],
      '#uniq' => $values['uniq'],
      '#process_function' => $values['process_function'],
      '#items' => $items,
    ),
  );

  // Save feed
  FeedImport::saveFeed($feed, TRUE);
  drupal_set_message(t('Feed @name saved!', array(
    '@name' => $feed['name'],
  )));
}

/**
 * Ajax callback to add a new item
 */
function feed_import_ajax_add_new_item($form, &$form_state) {
  return $form['xpath']['items']['container_' . $form_state['#current_item']];
}

/**
 * Ajax callback to remove an item
 */
function feed_import_ajax_remove_item($form, &$form_state) {

  // Send empty string to remove container
  return '';
}

/**
 * Generate field
 *
 * @param int $pos
 *   Fieldset number
 * @param array $values
 *   Array containing default values
 * @param bool $collapsed
 *   Inicates if fieldset is collapsed
 *
 * @return array
 *   Fieldset containing xpath inputs
 */
function feed_import_generate_xpath_item($pos = 0, $values = NULL, $collapsed = FALSE) {
  $container = 'container_' . $pos;
  $item[$container] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => $collapsed,
    '#title' => isset($values['#field']) ? $values['#field'] : t('Unspecified field'),
    '#attributes' => array(
      'id' => 'item_container_' . $pos,
    ),
  );
  $container =& $item[$container];
  $values['#xpath'] = isset($values['#xpath']) ? $values['#xpath'] : '';
  if (is_array($values['#xpath'])) {
    $values['#xpath'] = implode(PHP_EOL, $values['#xpath']);
  }
  $container['xpath_' . $pos] = array(
    '#type' => 'textarea',
    '#default_value' => $values['#xpath'],
    '#title' => t('XPATH'),
    '#description' => t('Enter XPATH to item. You can enter multiple XPATHs (one per line) until one passes pre-filter.'),
  );
  $container['default_action_' . $pos] = array(
    '#type' => 'select',
    '#options' => FeedImport::getDefaultActions(),
    '#default_value' => isset($values['#default_action']) ? $values['#default_action'] : 'default_value',
    '#title' => t('Action when filtered result is empty'),
    '#description' => t('If the filter is empty you can choose what action to take next.'),
  );
  $container['default_' . $pos] = array(
    '#type' => 'textfield',
    '#default_value' => isset($values['#default_value']) ? $values['#default_value'] : '',
    '#title' => t('Default value'),
    '#description' => t('If no XPATH passes pre-filter then use a default value.'),
    '#prefix' => '<div style="display: none;" rel="default_action_' . $pos . '">',
    '#suffix' => '</div>',
  );
  $container['remove_container_' . $pos] = array(
    '#type' => 'button',
    '#value' => t('Remove field @field', array(
      '@field' => drupal_strtoupper($container['#title']),
    )),
    '#ajax' => array(
      'event' => 'click',
      'wrapper' => 'item_container_' . $pos,
      'method' => 'replace',
      'callback' => 'feed_import_ajax_remove_item',
    ),
  );
  return $item;
}

/**
 * Edit filter form
 */
function feed_import_edit_filter_form($form, &$form_state, $f = '#filter', $id = 0) {
  $feed = FeedImport::loadFeeds(FALSE, $id);
  if (!$feed) {
    drupal_set_message(t("Feed doesn't exist!"), 'error');
    return;
  }
  if (!isset($form_state['#item_filter'])) {

    // Save filter
    $form_state['#item_filter'] = $f;

    // Save fields to be filtered
    $form_state['#filter_fields'] = array_keys($feed['xpath']['#items']);
  }
  $form['#filter_fields'] = $form_state['#filter_fields'];
  $param_field = variable_get('feed_import_field_param_name', '[field]');
  $help = array();
  $help[0] = t('Filter name') . ': ' . t('A name given by you for this filter.');
  $help[1] = t('Filter function') . ': ' . t('Name of the php function to apply on field value.') . ' ';
  $help[1] .= t('You may also use a static function like this: ClassName::functionName.') . ' ';
  $help[1] .= t('Also check our provided filters in FeedImportFilter class.');
  $help[2] = t('Function params') . ': ' . t('Enter here params (one per line) for php function.') . ' ';
  $help[2] .= t('Enter "@param_field" (without quotes) were you want to be sent field value as parameter.', array(
    '@param_field' => $param_field,
  )) . ' ';
  $help[3] = t('Filtered value is the resulted string of all function calls from top to bottom.');
  $help = implode('<br />', $help);
  $form['help'] = array(
    '#markup' => $help,
  );
  $vars = array(
    '@name' => $feed['name'],
    '@filter' => $form_state['#item_filter'] == '#filter' ? t('filters') : t('pre-filters'),
  );

  // Set page title
  drupal_set_title(t('Edit @filter for @name', $vars), PASS_THROUGH);
  $form['id'] = array(
    '#type' => 'value',
    '#value' => $feed['id'],
  );
  if (isset($form_state['values'])) {
    foreach ($form_state['#filter_fields'] as &$field) {
      $filters = array();
      $filter[$field]['#tree'] = TRUE;
      $pos = 0;
      if (!empty($form_state['values']['table_content'][$field])) {
        foreach ($form_state['values']['table_content'][$field] as &$filter) {
          $vars = array(
            '#name' => $filter['name'],
            '#function' => $filter['function'],
            '#params' => explode(PHP_EOL, $filter['params']),
          );
          $filters[$field][$pos] = feed_import_new_filter($pos, $vars);
          $pos++;
        }
      }

      // Add new field
      if ($form_state['#add_filter'] == $field) {
        $vars = array(
          '#name' => '',
          '#function' => '',
          '#params' => array(
            $param_field,
          ),
        );
        $filters[$field][$pos] = feed_import_new_filter($pos, $vars);
      }
      $form['container_' . $field] = array(
        '#type' => 'fieldset',
        '#title' => check_plain($field),
        '#collapsible' => TRUE,
        '#collapsed' => $field != $form_state['#add_filter'] && $field != $form_state['#delete_filter'],
        'table_content' => array(
          '#tree' => TRUE,
        ) + $filters,
        'actions' => feed_import_add_filter_actions($field),
      );
    }
  }
  else {
    foreach ($feed['xpath']['#items'] as $field => &$val) {
      $filters = array();
      $filters[$field]['#tree'] = TRUE;
      $pos = 0;
      foreach ($val[$form_state['#item_filter']] as $name => &$filter) {
        $vars = array(
          '#name' => $name,
          '#function' => $filter['#function'],
          '#params' => $filter['#params'],
        );
        $filters[$field][$pos] = feed_import_new_filter($pos, $vars);
        $pos++;
      }
      $form['container_' . $field] = array(
        '#type' => 'fieldset',
        '#title' => check_plain($field),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        'table_content' => array(
          '#tree' => TRUE,
        ) + $filters,
        'actions' => feed_import_add_filter_actions($field),
      );
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save filters'),
    '#prefix' => t('Your filters will be saved only after you press the button below.') . '<br />',
  );
  return $form;
}

/**
 * Edit filter form validate
 */
function feed_import_edit_filter_form_validate(&$form, &$form_state) {
  if ($form_state['submitted']) {
    return;
  }
  $delete_filter = NULL;
  $add_filter = NULL;
  foreach ($form_state['#filter_fields'] as &$field) {
    $cbk = $form_state['clicked_button']['#array_parents'];
    switch (TRUE) {
      case $cbk[1] == 'actions' && preg_match('/add_new_filter_([a-zA-Z0-9_]{1,255})/', $cbk[2], $match):
        $add_filter = $match[1];
        break;
      case $cbk[1] == 'actions' && preg_match('/delete_selected_filters_([a-zA-Z0-9_]{1,255})/', $cbk[2], $match):
        $delete_filter = $match[1];
        break;
    }

    // Delete selected
    if ($field == $delete_filter) {
      foreach ($form_state['values']['table_content'][$field] as $key => &$filter) {
        if ($filter['selected']) {
          unset($form_state['values']['table_content'][$field][$key]);
        }
      }
    }
    if (!empty($form_state['values']['table_content'][$field])) {

      // Set filters order
      usort($form_state['values']['table_content'][$field], 'feed_import_sort_filter_by_weight');
    }
  }
  $form_state['#add_filter'] = $add_filter;
  $form_state['#delete_filter'] = $delete_filter;
}

/**
 * Edit filter form submit
 */
function feed_import_edit_filter_form_submit($form, &$form_state) {
  $values =& $form_state['values'];
  $feed = FeedImport::loadFeeds(FALSE, $values['id']);
  foreach ($feed['xpath']['#items'] as $field => &$item) {
    $item[$form_state['#item_filter']] = array();
    if (!empty($values['table_content'][$field])) {
      usort($values['table_content'][$field], 'feed_import_sort_filter_by_weight');
      foreach ($values['table_content'][$field] as &$filter) {
        if (!$filter['name'] || !$filter['function']) {
          continue;
        }
        if (!$filter['params']) {
          $filter['params'] = array(
            variable_get('feed_import_field_param_name', '[field]'),
          );
        }
        else {
          $filter['params'] = explode(PHP_EOL, $filter['params']);
          $filter['params'] = array_map('trim', $filter['params']);
        }
        $item[$form_state['#item_filter']][$filter['name']] = array(
          '#function' => trim($filter['function']),
          '#params' => $filter['params'],
        );
        $filter = NULL;
      }
    }
  }

  // Save feed
  FeedImport::saveFeed($feed, TRUE);
  $vars = array(
    '@filter' => $form_state['#item_filter'] == '#filter' ? t('Filters') : t('Pre-filters'),
    '@name' => $feed['name'],
  );
  drupal_set_message(t('@filter saved for @name', $vars));
}

/**
 * usort() callback, for sorting filters by weight
 */
function feed_import_sort_filter_by_weight($a, $b) {
  if ($a['weight'] == $b['weight']) {
    return 0;
  }
  return $a['weight'] > $b['weight'] ? 1 : -1;
}

/**
 * Return new filter elements
 *
 * @param int $pos
 *   Filter position
 * @param array $values
 *   Default filter values
 *
 *  @return array
 *    Array containing filter html forms
 */
function feed_import_new_filter($pos = 0, $values = NULL) {
  $values['#params'] = isset($values['#params']) ? $values['#params'] : '';
  if (is_array($values['#params'])) {
    $values['#params'] = implode(PHP_EOL, $values['#params']);
  }
  return array(
    'name' => array(
      '#type' => 'textfield',
      '#size' => 30,
      '#default_value' => isset($values['#name']) ? $values['#name'] : '',
    ),
    'function' => array(
      '#type' => 'textfield',
      '#size' => 30,
      '#default_value' => isset($values['#function']) ? $values['#function'] : '',
    ),
    'params' => array(
      '#type' => 'textarea',
      '#default_value' => $values['#params'],
      '#rows' => 2,
    ),
    'selected' => array(
      '#type' => 'checkbox',
      '#default_value' => 0,
    ),
    'weight' => array(
      '#type' => 'weight',
      '#delta' => 15,
      '#default_value' => $pos,
      '#attributes' => array(
        'class' => array(
          'weight',
        ),
      ),
    ),
  );
}

/**
 * Add filter button actions: add new, remove all
 *
 * @param string $field
 *   Field name
 *
 * @return array
 *   Array with buttons
 */
function feed_import_add_filter_actions($field) {
  return array(
    'add_new_filter_' . $field => array(
      '#type' => 'button',
      '#value' => t('Add new filter to @field', array(
        '@field' => drupal_strtoupper($field),
      )),
    ),
    'delete_selected_filters_' . $field => array(
      '#type' => 'button',
      '#value' => t('Remove selected from @field', array(
        '@field' => drupal_strtoupper($field),
      )),
    ),
  );
}

/**
 * Implements hook_theme().
 */
function feed_import_theme() {
  return array(
    'feed_import_edit_filter_form' => array(
      'render element' => 'form',
    ),
  );
}

/**
 * Theme form feed_import_edit_filter_form
 */
function theme_feed_import_edit_filter_form($form) {
  $form = $form['form'];
  $header = array(
    t('Filter name'),
    t('Filter function'),
    t('Function params (one per line)'),
    t('Select'),
    t('Weight'),
  );
  foreach ($form['#filter_fields'] as &$field) {
    $rows = array();
    if (!empty($form['container_' . $field]['table_content'][$field])) {
      foreach ($form['container_' . $field]['table_content'][$field] as $id => &$row) {
        if (!is_numeric($id)) {
          continue;
        }

        // Table columns
        $data = array(
          'name',
          'function',
          'params',
          'selected',
          'weight',
        );
        foreach ($data as &$d) {
          if (isset($row[$d]['#checked'])) {
            $row[$d]['#checked'] = FALSE;
          }
          $row[$d]['#value'] = $row[$d]['#default_value'];
          $d = drupal_render($row[$d]);
        }
        $rows[] = array(
          'data' => $data,
          'class' => array(
            'draggable',
          ),
        );
      }
    }
    drupal_add_tabledrag('table_' . $field, 'order', 'sibling', 'weight');
    $form['container_' . $field]['table_content'][$field] = array(
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
      '#attributes' => array(
        'id' => 'table_' . $field,
      ),
      '#empty' => t('There are no filters.'),
    );
  }
  return drupal_render_children($form);
}

Functions

Namesort descending Description
feed_import_add_filter_actions Add filter button actions: add new, remove all
feed_import_add_new_feed_form Add a new feed form
feed_import_add_new_feed_form_submit Add new feed form submit
feed_import_add_new_feed_form_validate Add new feed form validate
feed_import_add_to_delete Schedule an item for removing from feed import items at the end of the script
feed_import_ajax_add_new_item Ajax callback to add a new item
feed_import_ajax_remove_item Ajax callback to remove an item
feed_import_change_status Enable/disable feeds
feed_import_cron Implements hook_cron().
feed_import_delete_feed_form Feed delete form
feed_import_delete_feed_form_submit Feed delete form submit
feed_import_delete_items Delete feed items and set report
feed_import_edit_feed_form Edit feed form
feed_import_edit_feed_form_submit Edit feed form submit
feed_import_edit_feed_form_validate Edit feed form validate
feed_import_edit_filter_form Edit filter form
feed_import_edit_filter_form_submit Edit filter form submit
feed_import_edit_filter_form_validate Edit filter form validate
feed_import_entity_delete Implements hook_entity_delete().
feed_import_export_feed_page Export feed
feed_import_feed_import_process_info Implements hook_feed_import_process_info().
feed_import_generate_xpath_item Generate field
feed_import_help Implements hook_help().
feed_import_import_feed_form Feed import form
feed_import_import_feed_form_submit Feed import form submit
feed_import_import_feed_form_validate Feed import form validate
feed_import_import_items Import feed and set report
feed_import_list_feeds List all feeds
feed_import_menu Implements hook_menu().
feed_import_new_filter Return new filter elements
feed_import_permission Implements hook_permision().
feed_import_process_feed Processes a feed
feed_import_settings_form Settings form
feed_import_settings_form_validate Settings form validate
feed_import_sort_filter_by_weight usort() callback, for sorting filters by weight
feed_import_theme Implements hook_theme().
theme_feed_import_edit_filter_form Theme form feed_import_edit_filter_form

Constants

Namesort descending Description
FEED_IMPORT_PATH This is path to feed import UI