'admin/settings/feedapi_feed', 'title' => t('Node-Feed processor'), 'callback' => 'drupal_get_form', 'callback arguments' => array('feedapi_feed_admin_settings'), 'type' => MENU_NORMAL_ITEM, 'access' => user_access('administer feedapi'), ); } return $items; } /** * Implementation of hook_nodeapi(). */ function feedapi_feed_nodeapi(&$node, $op, $teaser, $page) { if ($op == 'delete') { $result = db_query("SELECT fid FROM {feedapi_node_feed} WHERE nid = %d", $node->nid); if (db_num_rows($result) > 0) { $feed = db_fetch_object($result); feedapi_invoke_feedapi('purge', $feed); } } } /** * Implementation of hook_link(). */ function feedapi_feed_link($type, $node = NULL, $teaser = FALSE) { if ($type == 'node') { $result = db_query("SELECT link, fid FROM {feedapi_node_feed} WHERE nid = %d", $node->nid); if (db_num_rows($result) > 0) { $feed = db_fetch_object($result); if (variable_get('feedapi_feed_show_feed_origin_link', TRUE)) { $links['feedapi_original'] = array( 'title' => t('Link to the site'), 'href' => $feed->link, ); } global $user; feedapi_invoke_feedapi('load', $feed); $own_feed = $feed->uid == $user->uid && user_access('handle own feeds') ? TRUE : FALSE; if (variable_get('feedapi_feed_show_commands_link', TRUE) && (user_access('administer feedapi') || $own_feed)) { $links['feedapi_refresh'] = array( 'title' => t('Refresh the feed'), 'href' => 'feed/'. $feed->fid .'/refresh', ); $links['feedapi_delete'] = array( 'title' => t('Delete the feed'), 'href' => 'feed/'. $feed->fid .'/delete', ); $links['feedapi_edit'] = array( 'title' => t('Adjust settings'), 'href' => 'feed/'. $feed->fid .'/edit', ); } return $links; } } } /** * Implementation of hook_form_alter(). */ function feedapi_feed_form_alter($form_id, &$form) { if ($form_id == 'feedapi_edit_page') { $feed = new stdClass(); if (isset($form['fid']['#value'])) { $feed->fid = $form['fid']['#value']; feedapi_invoke_feedapi('load', $feed); if (in_array('feedapi_feed', $feed->processors_feed)) { $node = node_load($feed->nid); if (isset($node->uid)) { $user_current = user_load(array('uid' => $node->uid)); } global $user; $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 3628800, 4838400, 7257600, 15724800, 31536000), 'format_interval'); $period[FEEDAPI_FEED_NEVER_DELETE_OLD] = t('Never'); $form['processors_settings']['items_delete'] = array( '#type' => 'select', '#title' => t('Delete news items older than'), '#options' => $period, '#default_value' => is_numeric($feed->items_delete) ? $feed->items_delete : variable_get('feedapi_feed_items_delete', 15724800) ); $form['processors_settings']['feed_content_type'] = array( '#type' => 'select', '#title' => t('The content-type of the feed'), '#default_value' => isset($node->type) ? $node->type : variable_get('feedapi_feed_type', 'story'), '#options' => drupal_map_assoc(array_keys(node_get_types())), ); $form['processors_settings']['feed_node_user'] = array( '#type' => 'textfield', '#title' => t('The author of the feed node'), '#default_value' => isset($user_current->name) ? $user_current->name : $user->name, '#autocomplete_path' => 'user/autocomplete', ); $form['processors_settings']['feed_node_date'] = array( '#type' => 'radios', '#title' => t('Date of the feed node'), '#options' => array('current' => t('The current server time'), t('no') => 'Do not change'), '#default_value' => 'no', ); } } } } /** * Create the given feed content-representation * Implementation of hook_feedapi_save(). * * @param stdClass $feed * The object of the feed * @return boolean * TRUE on success, FALSE on fail */ function feedapi_feed_feedapi_save($feed) { $node = new stdClass(); $node->type = isset($feed->feed_content_type) ? $feed->feed_content_type: variable_get('feedapi_feed_type', 'story'); // Get the default options from the content type's default $options = variable_get('node_options_'. $node->type, FALSE); if (is_array($options)) { $node->status = in_array('status', $options) ? 1 : 0; $node->promote = in_array('promote', $options) ? 1 : 0; $node->sticky = in_array('sticky', $options) ? 1 : 0; } if (isset($feed->feed_node_date)) { switch ($feed->feed_node_date) { case 'current': $node->changed = $node->created = time(); break; } } $node->title = $feed->title; $node->body = $feed->description; if (isset($feed->feed_node_user)) { $user = user_load(array('name' => $feed->feed_node_user)); } else { global $user; } $node->uid = $user->uid; $items_delete = isset($feed->items_delete) ? $feed->items_delete : variable_get('feedapi_feed_items_delete', 15724800); if (!isset($feed->nid)) { node_save($node); $feed->nid = $node->nid; db_query("INSERT INTO {feedapi_node_feed} (fid, nid, link, items_delete) VALUES (%d, %d, '%s', %d)", $feed->fid, $feed->nid, $feed->options->link, $items_delete); } else { $node->nid = $feed->nid; node_save($node); db_query("UPDATE {feedapi_node_feed} SET items_delete = %d, link = '%s' WHERE fid = %d", $items_delete, $feed->options->link, $feed->fid); } return $feed; } /** * Update the given feed content-representation * Implementation of hook_feedapi_update(). * * @param stdClass $feed * The object of the feed * @return boolean * TRUE on success, FALSE on fail */ function feedapi_feed_feedapi_update($feed) { $node = db_fetch_object(db_query("SELECT nid FROM {feedapi_node_feed} WHERE fid = %d", $feed->fid)); $feed->nid = $node->nid; feedapi_feed_feedapi_save($feed); return $feed; } /** * Delete the given feed node-representation * Implementation of hook_feedapi_delete(). * * @param stdClass $feed * The object of the feed * @return boolean * TRUE on success, FALSE on fail */ function feedapi_feed_feedapi_delete($feed) { db_query("DELETE FROM {feedapi_node_feed} WHERE fid = %d", $feed->fid); node_delete($feed->nid); } /** * Load the feed if exists, tell if not exists * * @param $feed * Feed object * @return * FALSE if the feed is not exist in the processor, the Feed object otherwise */ function feedapi_feed_feedapi_load($feed) { $item = db_fetch_object(db_query("SELECT * FROM {feedapi_node_feed} WHERE fid = %d", $feed->fid)); if (!is_numeric($item->nid)) { return FALSE; } $feed->nid = $item->nid; $feed->items_delete = $item->items_delete; $feed->items_promote = $item->items_promote; $node = node_load($feed->nid); $feed->title = $node->title; $feed->description = $node->body; $feed->options->original_url = $item->link; return $feed; } /** * Check the format of the given URL or other validation * Implementation of hook_feedapi_validate(). * * @param string $url * URL (not only web URLs) * @return * Feed object */ function feedapi_feed_feedapi_validate($form_id, $form_values, $feed) { // Here we can decide the validity of the URL // Maybe it should checks if the URL returns 200 or not $valid_url = "`(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?`"; if (preg_match($valid_url, $form_values['url'])) { } else { form_set_error('url', t('The URL entered is not valid. It should be in the format of: %url_format', array('%url_format'=>'http://www.example.com/rss.xml'))); } return $feed; } /** * Tell which feed types are compatible with this submodule. * For eg. "XML feed", "FTP", "mailing list" * Implementation of hook_feedapi_type(). * * @return array * A string array of compatible types */ function feedapi_feed_feedapi_type() { return array("XML feed"); } /** * Get the content from the given URL * Implementation of hook_feedapi_get(). * * @param $url * A valid URL (not only web URLs) * @param $username * If the URL use authentication, here you can supply the username for this * @param $password * If the URL use authentication, here you can supply the password for this * @return string * The data pulled from the URL */ function feedapi_feed_feedapi_get($url, $username = NULL, $password = NULL) { $method = 'GET'; $follow = 3; $data = NULL; $timeout = 15; if (!function_exists('curl_init')) { // Conventional way - use drupal internal download mechanism $headers = array(); if ($username != NULL && $password != NULL) { $headers['Authorization'] = 'Basic: '. base64_encode("$username:$password"); } $result = drupal_http_request($url, $headers, $method, $data, $follow); return $result->data; } // Solid way - use cURL $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_USERAGENT, 'Drupal'); if (strlen($username) > 0 && strlen($password) > 0) { curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); } $result = curl_exec($ch); if (curl_errno($ch) != 0) { watchdog("feedapi", $url . " : " . curl_error($ch), WATCHDOG_WARNING); curl_close($ch); unset($ch); return FALSE; } // return $result; } /** * Delete expired items and return informations about the feed refreshing * Implementation of hook_feedapi_expire(). * * @param $feed * The feed object * @param $force * If TRUE, do not examine that the feed needs refresh * @return * FALSE if the feed don't have to be refreshed. (forbidden if the $force is TRUE) * The number of maximal new elements created otherwise */ function feedapi_feed_feedapi_expire($feed, $force = FALSE) { $needs_refresh = time() - $feed->checked > $feed->refresh; if (($needs_refresh || $force) && $feed->items_delete != FEEDAPI_FEED_NEVER_DELETE_OLD) { foreach ($feed->items as $item) { if (time() - $item->arrived > $feed->items_delete) { foreach($feed->processors_item as $processor) { module_invoke($processor, 'feedapi_item_delete', $item); } } } } if ($needs_refresh == FALSE && $force == FALSE) { return FALSE; } return variable_get('feedapi_feed_items_one_round', 15); } /** * Settings: * Content-type of feeds */ function feedapi_feed_admin_settings() { $form['feedapi_feed_type'] = array( '#type' => 'select', '#title' => t('Feed content-type'), '#default_value' => variable_get('feedapi_feed_type', 'story'), '#options' => drupal_map_assoc(array_keys(node_get_types())), '#description' => t('The default type of the feeds.') ); $form['feedapi_feed_items_one_round'] = array( '#type' => 'textbox', '#title' => t('Process items in one round'), '#default_value' => variable_get('feedapi_feed_items_one_round', 15), '#description' => t('In one refresh round how many feed items should be processed.') ); $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 3628800, 4838400, 7257600, 15724800, 31536000), 'format_interval'); $period[FEEDAPI_FEED_NEVER_DELETE_OLD] = t('Never'); $form['feedapi_feed_items_delete'] = array( '#type' => 'select', '#title' => t('Delete news items older than'), '#options' => $period, '#default_value' => variable_get('feedapi_feed_items_delete', 15724800) ); $form['feedapi_feed_show_feed_origin_link'] = array( '#type' => 'checkbox', '#title' => t('At the node of the feed, show the link to the original site'), '#default_value' => variable_get('feedapi_feed_show_feed_origin_link', TRUE), ); $form['feedapi_feed_show_commands_link'] = array( '#type' => 'checkbox', '#title' => t('At the node of the feed, show the link to the feed commands (refresh / delete / etc.)'), '#default_value' => variable_get('feedapi_feed_show_commands_link', TRUE), ); $form['processors_settings']['feed_node_date'] = array( '#type' => 'radios', '#title' => t('Date of the feed node'), '#options' => array('feed' => t('Comes from the feed'), 'current' => t('The current server time')), '#default_value' => variable_get('feedapi_feed_node_date', 'feed'), ); return system_settings_form($form); }