directnews.info

; $Id$
name = DirectNews Scheduled Feed Importer
description = Imports news articles from DirectNews feeds on a scheduled basis.
package = Feed Parser
core = 6.x

directnews.module

<?php
/**
 * @file
 * These are the functions used to create the settings pages and import functions
 * fired by the drupal cron system. 
 * 
 * Feature improvements:
 * * Add support for custom intervals - run once per hour etc.
 * * Add base taxonomy - all categories/stories added below base
 */

/**
 * Implement the hook_node_info to add the 'news' node type
 */
function directnews_node_info() {
  return array(
    'news' => array(
      'name' => t('News Article'),
      'module' => 'directnews',
      'description' => t('A <em>news article</em> is a story about the latest industry news.'),
    )
  );
}

/**
 * Implementation of hook_perm() - permissions.
 */
function directnews_perm() {
  return array('create news articles', 'delete own news articles', 'delete any news article', 'edit own news article', 'edit any news article');
}

/**
 * Implementation of hook_access() - user access rights.
 */
function directnews_access($op, $node, $account) {
  switch ($op) {
    case 'create':
      // Anonymous users cannot post even if they have the permission. 
      return user_access('create news articles', $account) && $account->uid;
    case 'update':
      return user_access('edit any news article', $account) || (user_access('edit own news articles', $account) && ($node->uid == $account->uid));
    case 'delete':
      return user_access('delete any news article', $account) || (user_access('delete own news articles', $account) && ($node->uid == $account->uid));
  }
}

/**
 * Implementation of hook_view().
 */
function directnews_view($node, $teaser = FALSE, $page = FALSE) {
  if ($page) {
    // Breadcrumb navigation
    drupal_set_breadcrumb(array(l(t('Home'), NULL), l(t('News'), 'news')));
  }
  return node_prepare($node, $teaser);
}

/**
 * Implementation of hook_block().
 *
 * Displays the most recent 10 news article titles.
 */
function directnews_block($op = 'list', $delta = 0) {
  global $user;
  if ($op == 'list') {
    $block[0]['info'] = t('Recent news articles');
    return $block;
  }
  else if ($op == 'view') {
    if (user_access('access content')) {
      $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.created FROM {node} n WHERE n.type = 'news' AND n.status = 1 ORDER BY n.created DESC"), 0, 10);
      if ($node_title_list = node_title_list($result)) {
        $block['content'] = $node_title_list;
        $block['content'] .= theme('more_link', url('news'), t('Read breaking news.'));
        $block['subject'] = t('Recent news articles');
        return $block;
      }
    }
  }
}

/**
 * Implementation of hook_form().
 */
function directnews_form(&$node) {
  global $nid;
  $iid = isset($_GET['iid']) ? (int)$_GET['iid'] : 0;
  $type = node_get_types('type', $node);
 
 
  if (empty($node->body)) {
    if ($nid && $news = node_load($nid)) {
      $node->body = '<em>'. $news->body .'</em> ['. l($news->name, "node/$nid") .']';
    }
 
    if ($iid && $item = db_fetch_object(db_query('SELECT i.*, f.title as ftitle, f.link as flink FROM {aggregator_item} i, {aggregator_feed} f WHERE i.iid = %d AND i.fid = f.fid', $iid))) {
      $node->title = $item->title;
      // Note: $item->description has been validated on aggregation.
      $node->body = '<a href="'. check_url($item->link) .'">'. check_plain($item->title) .'</a> - <em>'. $item->description .'</em> [<a href="'. check_url($item->flink) .'">'. check_plain($item->ftitle) ."</a>]\n";
    }
 
  }
 
  $form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => !empty($node->title) ? $node->title : NULL, '#weight' => -5);
  $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
  return $form;
}

/**
 * Create admin forms for configuring importer
 */
function directnews_admin() {
	$form = array();
	$form['directnews_feedurl'] = array(
		'#type' => 'textfield',
		'#title' => t('DirectNews XML feed URL'),
		'#default_value' => variable_get('directnews_feedurl', 'http://feeds.directnews.co.uk/'),
		'#size' => 50,
		'#maxlength' => 255,
		'#description' => t("This is the URL to your unique DirectNewsXML feed."),
		'#required' => TRUE,
	);
//	$form['directnews_checkfreq'] = array(
//		'#type' => 'textfield',
//		'#title' => t('Update check frequency (mins)'),
//		'#default_value' => variable_get('directnews_checkfreq', '60'),
//		'#size' => 5,
//		'#maxlength' => 5,
//		'#description' => t("The number of minutes between each check of the news feed for new stories."),
//		'#required' => TRUE,
//	);
	return system_settings_form($form);
}

/**
 * Add menu items
 */
function directnews_menu() {
	$menu = array();
	$menu['admin/settings/directnews'] = array(
		'title' => t('DirectNews settings'),
		'description' => t("DirectNewsXML feed scheduled importer module settings"),
		'page callback' => 'drupal_get_form',
		'page arguments' => array('directnews_admin'),
		'access arguments' => array('access administration pages'),
		'type' => MENU_NORMAL_ITEM,
	);
	$menu['news'] = array(
		'title' => 'News',
		'description' => t("View the latest industry news"),
		'page callback' => 'news_page_last',
		'access arguments' => array('access content'),
		'type' => MENU_SUGGESTED_ITEM,
		'file' => 'directnews.pages.inc',
	);
	$items['news/feed'] = array(
		'title' => 'News',
		'page callback' => 'news_feed_last',
		'access arguments' => array('access content'),
		'type' => MENU_CALLBACK,
		'file' => 'directnews.pages.inc',
	);
	return $menu;
}

/**
 * The scheduled task - import stories from feed
 */
function directnews_cron() {
	//update vocabulary
	_directnews_update_vocabulary();
	$vid = variable_get('directnews_vocabulary', 0);
	//load feed into dom document
	$doc = new DOMDocument();
	$doc->load(variable_get('directnews_feedurl', 'http://feeds.directnews.co.uk/'));
 
	$xpath = new DOMXPath($doc);
	// Selecting nodes matching node "Article" using xpath_eval command and passing it the xpath context
	$nodes = $xpath->evaluate("//Article", $doc);
	// For each nodes in the collection we loop through each node and retrive and save the data.
	for ($i = 0; $i < $nodes->length; $i++) {
		$currentNode = $nodes->item($i);
		$id = $currentNode->getAttribute('ID');
		$created = $currentNode->getAttribute('Created');
		$heading = $xpath->evaluate('Heading', $currentNode)->item(0)->nodeValue;
		$content = $xpath->evaluate('Contents', $currentNode)->item(0)->nodeValue;
		$summary = $xpath->evaluate('Summary', $currentNode)->item(0)->nodeValue;
		$caption = $xpath->evaluate('Picture/PhotoTag', $currentNode)->item(0)->nodeValue;
		$largeURL = $xpath->evaluate('Picture/Large/URL', $currentNode)->item(0)->nodeValue;
		$date = $xpath->evaluate('Date', $currentNode)->item(0)->nodeValue;
#		$categoryID = $xpath->evaluate('Categories/Category', $currentNode)->item(0)->getAttribute('ID');
#		$categoryName = $xpath->evaluate('Categories/Category', $currentNode)->item(0)->nodeValue;
#		$longheading = $xpath->evaluate('LongHeading', $currentNode)->item(0)->nodeValue;
#		$priority = $xpath->evaluate('Priority', $currentNode)->item(0)->nodeValue;
#		$largeWidth = $xpath->evaluate('Picture/Large', $currentNode)->item(0)->getAttribute('Width');
#		$largeHeight = $xpath->evaluate('Picture/Large', $currentNode)->item(0)->getAttribute('Height');
#		$smallURL = $xpath->evaluate('Picture/Small/URL', $currentNode)->item(0)->nodeValue;
#		$smallWidth = $xpath->evaluate('Picture/Small', $currentNode)->item(0)->getAttribute('Width');
#		$smallHeight = $xpath->evaluate('Picture/Small', $currentNode)->item(0)->getAttribute('Height');
#		$orientation = $xpath->evaluate('Picture', $currentNode)->item(0)->getAttribute('Orientation');
#		$ratio = $xpath->evaluate('Picture', $currentNode)->item(0)->getAttribute('Ratio');
#		$photoID = $xpath->evaluate('Picture', $currentNode)->item(0)->getAttribute('PhotoID');
		$nid = 0;
		$vid = 0;
 
		/*** create time from created & date fields ***/
		list($day, $month, $year) = split('[/]',$date);
		$time = strtotime($year . '-' . $month . '-' . $day . ' ' . $created);
 
		/*** prepare content - insert line breaks & add double quoting for sql ***/
		$heading = _directnews_sql_prep($heading);
		$content = _directnews_sql_prep($content);
		$summary = _directnews_sql_prep($summary);
		$caption = _directnews_sql_prep($caption);
 
		/*** Does this article alread exist ***/
		$article_node = _directnews_node_exists($id);
 
		if($article_node) {
			/*** Update Drupal ***/
			$nid = $article_node['nid'];
			$vid = $article_node['vid'];
			$n_upd_sql = "
				UPDATE {node} SET title = '$heading', created = '$time', changed = '$time' 
				WHERE nid = '$nid'
				";
			$v_upd_sql = "
				UPDATE {node_revisions} SET title = '$heading', body = '$content', teaser = '$summary', timestamp = '$time' 
				WHERE vid = '$vid'
				";
			//echo $n_upd_sql;
			//echo $v_upd_sql;
			$n_up_res = db_query($n_upd_sql);
			$v_up_res = db_query($v_upd_sql);
		}
		else {
			/*** Insert into Drupal ***/
			$nid = _directnews_next_nid();
			$vid =_directnews_next_vid();
			$n_ins_sql = "
				INSERT INTO {node} (nid, vid, type,language, title, uid, status, created, changed, comment, promote, moderate, sticky, tnid, translate) 
				VALUES ('$nid','$vid','news','','$heading','1','1','$time','$time','2','1','0','0','0','0')
				";
			$v_ins_sql = "
				INSERT INTO {node_revisions} (nid, vid, uid, title, body, teaser, log, timestamp, format)
				VALUES ('$nid','$vid','1','$heading','$content','$summary','','$time','2')
				";
			//echo $n_ins_sql;
			//echo $v_ins_sql;
			$res = db_query($n_ins_sql);
			$res = db_query($v_ins_sql);
			$dn_ins_sql = "
				INSERT INTO {directnews_node} (nid, dnid)
				VALUES ('$nid', '$id')
				";
			//echo $dn_ins_sql;
			$dn_res = update_sql($dn_ins_sql);
		}
		_directnews_update_vocabulary();
		//remove all existing categories on article
		$node_terms_rem_sql = "DELETE FROM {term_node} WHERE nid = $nid";
		//echo db_prefix_tables($node_terms_rem_sql);
		db_query($node_terms_rem_sql);
		$CatColl = $xpath->evaluate('Categories/Category',$currentNode);
		$vocab_id = variable_get('directnews_vocabulary',0);
		foreach ($CatColl as $category){
			$Catid = $category->getAttribute('ID');
			$CatName = $category->nodeValue;
			//Check if term exists - add if not - get tid
			$tid = _directnews_term($Catid, $CatName);
			$term_node_ins_sql = "
				INSERT INTO {term_node} (nid, vid, tid)
				VALUES ('$nid', '$vid', '$tid')
				";
			//echo $term_node_ins_sql;
			db_query($term_node_ins_sql);
		}
	}
}

/**
 * Implementation of hook_init
 *
 * Make sure that database schema is correct for directnews module:
 * - add table for relating nodes to feed items
 * - add table for relating terms to categories
 */
function directnews_init() {
	db_set_active();
	if(!db_table_exists('directnews_node')) {
		$nodes_ret = update_sql("
			CREATE TABLE {directnews_node} (
			`nid` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
			`dnid` INTEGER UNSIGNED NOT NULL,
			PRIMARY KEY (`nid`))
		");
	}
	if(!db_table_exists('directnews_term')) {
		$nodes_ret = update_sql("
			CREATE TABLE {directnews_term} (
			`tid` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
			`dncid` INTEGER UNSIGNED NOT NULL,
			PRIMARY KEY (`tid`))
		");
	}
}

/**
 * Implementation of hook_uninstall
 *
 * Remove all directnews module specific tables
 * - remove table for relating nodes to feed items
 * - remove table for relating terms to categories
 */
function directnews_uninstall() {
	if(db_table_exists('directnews_node')) {
		$nodes_ret = update_sql("
			DROP TABLE {directnews_node}
		");
	}
	if(db_table_exists('directnews_term')) {
		$nodes_ret = update_sql("
			DROP TABLE {directnews_term}
		");
	}
}

/**
 * Check if node is tagged with the article id
 */
function _directnews_node_exists($dnid) {
	$dnres_sql = "SELECT nid FROM {directnews_node} WHERE dnid = '$dnid'";
	$dnres = db_query($dnres_sql);
	$dnres_array = db_fetch_array($dnres);
	//get nid and vid if article exists
	if($dnres_array) {
		$nid = $dnres_array['nid'];
		$vid_res = db_query("SELECT vid FROM {node} WHERE nid = '$nid'");
		$vid_res_array = db_fetch_array($vid_res);
		$vid = $vid_res_array['vid'];
		$identifiers = array(
			'nid' => $nid,
			'vid' => $vid,
			);
		return $identifiers;
	}
	else 
		return false;
}

/**
 * Get incremented nid
 */
function _directnews_next_nid() {
	$q = db_query("SELECT max(nid) FROM {node}");
	$r = db_fetch_array($q);
	$id = $r['max(nid)'] + 1;
	return $id;
}

/**
 * Get incremented vid
 */
function _directnews_next_vid() {
	$q = db_query("SELECT max(vid) FROM {node_revisions}");
	$r = db_fetch_array($q);
	$id = $r['max(vid)'] + 1;
	return $id;
}

/**
 * Get incremented tid
 */
function _directnews_next_tid() {
	$q = db_query("SELECT max(tid) FROM {term_data}");
	$r = db_fetch_array($q);
	$id = $r['max(tid)'] + 1;
	//echo $id;
	return $id;
}

/**
 * Make sure News vocab is in place and save vid
 */
function _directnews_update_vocabulary() {
	$vid = variable_get('directnews_vocabulary', 0);
	$vocabularies = taxonomy_get_vocabularies();
	if (!isset($vocabularies[$vid])) {
		$vocabulary = array(
			'name' => t('News'),
			'description' => t(''),
			'multiple' => 1,
			'required' => 0,
			'hierarchy' => 0,
			'relations' => 1,
			'module' => 'taxonomy',
			'weight' => 0,
			'nodes' => array('news' => 1),
		);
		taxonomy_save_vocabulary($vocabulary);
		variable_set('directnews_vocabulary', $vocabulary['vid']);
	}
}

/**
 * Check if cat exists as term
 * - add if not
 * - return tid
 */
function _directnews_term($catid, $catname) {
	$tid = _directnews_term_exists($catid);
	//got ter - return tid
	if($tid) {
		return $tid;
	}
	//not got term - add new term - add new dncat
	else {
		$tid = _directnews_next_tid();
		$vid = variable_get('directnews_vocabulary', 0);
		$term_ins_sql = "
			INSERT INTO {term_data} (tid, vid, name, description, weight)
			VALUES ('$tid', '$vid', '$catname', '', 0)
			";
		//echo $term_ins_sql;
		db_query($term_ins_sql);
		$term_heir_ins_sql = "
			INSERT INTO {term_hierarchy} (tid, parent)
			VALUES ('$tid', '0')
			";
		//echo $term_heir_ins_sql;
		db_query($term_heir_ins_sql);
		$dncat_sql = "
			INSERT INTO {directnews_term} (tid, dncid)
			VALUES ('$tid', '$catid')
			";
		//echo $dncat_sql;
		db_query($dncat_sql);
		return $tid;
	}
}

/**
 * Check if term is tagged with the category id
 */
function _directnews_term_exists($dncid) {
	$res = db_query("SELECT tid FROM {directnews_term} WHERE dncid = '$dncid'");
	$res_array = db_fetch_array($res);
	if($res_array)
		return $res_array['tid'];
	else
		return false;
}
 
function _directnews_sql_prep($string) {
	$string = str_replace("'", "''", $string);
	$string = str_replace("<br/>", "\n", $string);
	return $string;
}


directnews.pages.inc

<?php
// $Id$
 
/**
 * @file
 * Page callback file for the directnews module.
 */
 
/**
 * Menu callback; displays a Drupal page containing recent news articles of all users.
 */
function news_page_last() {
  global $user;
 
  $output = '';
  $items = array();
 
  if (user_access('edit own news')) {
    $items[] = l(t('Add a new article.'), "node/add/news");
  }
 
  $output = theme('item_list', $items);
 
  $result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'news' AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10));
  $has_articles = FALSE;
 
  while ($node = db_fetch_object($result)) {
    $output .= node_view(node_load($node->nid), 1);
    $has_articles = TRUE;
  }
 
  if ($has_articles) {
    $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
  }
  else {
    drupal_set_message(t('No news articles have been written.'));
  }
  drupal_add_feed(url('news/feed'), t('RSS - news'));
 
  return $output;
}

Comments

worlandoo’s picture

Hi - do you have any notes on how to install this module as it does not seem to appear in admin/modules when placed in the drupal - modules folder. Thanks