--- featured_content.module	2010-06-04 22:17:14.000000000 +0200
+++ featured_content_cache.module	2010-09-26 17:37:27.000000000 +0200
@@ -51,6 +50,14 @@ function featured_content_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'featured_content.pages.inc',
   );
+  $items['featured-content/cache/generate/%'] = array(
+    'title' => 'Featured Content Cache Generation',
+    'description' => 'Featured Content Cache Generation for a Block',
+    'access arguments' => array('access content'),
+    'page callback' => 'featured_content_generate_sort_cache_cron',
+    'page arguments' => array(3),
+    'type' => MENU_CALLBACK,
+  );  
   return $items;
 }
 
@@ -224,11 +231,20 @@ function featured_content_view($delta, $
     $nids = featured_content_get_cck_nids($featured_content['cck']);
     break;
   case 'filter':
+    //Xavi: Sí sort cache es true, aquí hay que apuntar a la cache
+    if($featured_content['filter']['sort_cache'] == 'true') {
+    	// Si la cache esta activada no hace falta este paso
+	} else {
     $nids = featured_content_get_filtered_nids($featured_content['filter']);
+	}
     break;
   }
+  if($featured_content['filter']['sort_cache'] == 'true') {
+  	    // Si el tipo es 'filter' y la caché está activada, aquí deberemos leer los nodos de la cache
+  	   $nodes = featured_content_get_nodes_from_cache($delta,$this_node->nid);
+  } else {
   $nodes = featured_content_get_nodes($nids, $featured_content['sort']);
-
+  }
   // create settings for theming
 
   // all block settings
@@ -263,29 +279,67 @@ function featured_content_view($delta, $
       }
       break;
     case 'popular_asc':
+	    if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {    
       $nodes = featured_content_sort_nodes($nodes, 'totalcount', TRUE, 'asc');
+      	}
       break;
     case 'popular_desc':
+        if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {
       $nodes = featured_content_sort_nodes($nodes, 'totalcount');
+		}
       break;
     case 'date_asc':
+        if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {
       $nodes = featured_content_sort_nodes($nodes, 'created', TRUE, 'asc');
+		}
       break;
     case 'date_desc':
+        if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {
       $nodes = featured_content_sort_nodes($nodes, 'created');
+		}
       break;
     case 'alpha_asc':
+        if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {
       $nodes = featured_content_sort_nodes($nodes, 'title', FALSE, 'asc');
+		}
       break;
     case 'alpha_desc':
+        if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {
       $nodes = featured_content_sort_nodes($nodes, 'title', FALSE);
+		}
       break;
     case 'terms_asc':
-      $nodes = featured_content_sort_nodes_by_terms($nodes, 'asc');
+      if($featured_content['filter']['sort_cache']=='true'){
+	  } else {
+		$nodes = featured_content_sort_nodes_by_terms($nodes, $node->nid, 'asc');
+	  }
       break;
     case 'terms_desc':
-      $nodes = featured_content_sort_nodes_by_terms($nodes);
+    	if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {      
+      		$nodes = featured_content_sort_nodes_by_terms($nodes, $node->nid);
+		}
+      	break;
+    //BEGIN::Xavier Sanz
+    case 'words_asc':
+      if($featured_content['filter']['sort_cache']=='true'){
+	  } else {
+		$nodes = featured_content_sort_nodes_by_words($nodes, $node->nid, 'asc');
+	  }
+      break;
+    case 'words_desc':
+    	if($featured_content['filter']['sort_cache'] == 'true') {
+		} else {      
+      		$nodes = featured_content_sort_nodes_by_words($nodes, $node->nid);
+		}
       break;
+    //END::Xavier Sanz
     case 'none':
       if ($nids) {
         foreach ($nids as $nid) {
@@ -303,7 +357,12 @@ function featured_content_view($delta, $
     if ($type == 'more' && ! in_array($featured_content['more']['display'], array('none', 'custom'))) {
       $show_num = $featured_content['more']['num'];
     }
+    //BEGIN::Xavier Sanz, What happens if $nodes is smaller than $show_num??
+    //if(sizeof($nodes)<$show_num) {
+	//	$nodes = array_splice($nodes, 0, sizeof($nodes));
+	//} else {
     $nodes = array_splice($nodes, 0, $show_num);
+	//}	
 
     $links = array();
     $teasers = array();
@@ -470,10 +529,14 @@ function featured_content_get_vocabulary
  * Get filtered node nids. Filter base on content types, users (authors) and
  * taxonomy terms.
  */
-function featured_content_get_filtered_nids($data) {
+function featured_content_get_filtered_nids($data, $nid = NULL) {
 
+  if (!empty($nid)) {
+	  //this comes from cache block generation
+	  $node = node_load($nid);
+	  //drupal_set_message("Loading node: ".$node->nid);
   // unless configured, exclude current node page
-  if (! $data['include_node']) {
+  } elseif (! $data['include_node']) {
     if (arg(0) == 'node' && is_numeric(arg(1))) {
       $node = node_load(arg(1));
     }
@@ -621,6 +684,10 @@ function featured_content_get_filtered_n
     }
   }
 
+  //Xavi::Debug
+  //drupal_set_message('SELECT n.nid FROM {node} AS n ' . $tid_inner_join . ' ' . $pt_inner_join . ' WHERE n.status <> 0 ' . $where_clause . $where_data[0] . $where_data[1] );
+  //print_r($where_data);
+  
   $results = db_query('SELECT n.nid FROM {node} AS n ' . $tid_inner_join . ' ' . $pt_inner_join . ' WHERE n.status <> 0 ' . $where_clause, $where_data);
   while ($row = db_fetch_object($results)) {
     $add = TRUE;
@@ -634,6 +701,8 @@ function featured_content_get_filtered_n
       $nids[] = $row->nid;
     }
   }
+  //print_r($data);
+  //print_r($nids);
   return $nids;
 }
 
@@ -659,11 +728,13 @@ function featured_content_get_path_patte
 /**
  * Sort nodes based on terms.
  */
-function featured_content_sort_nodes_by_terms($nodes, $order = 'desc') {
+function featured_content_sort_nodes_by_terms($nodes, $node_nid, $order = 'desc') {
   // only works if on a node page
-  if (arg(0) == 'node' && is_numeric(arg(1))) {
+  // but it must be changed to admin
+  if (arg(0) == 'node' || arg(0) == 'admin' || arg(0) == 'featured-content') {
     $tmp = array();
     $nids = array_keys($nodes);
+    /*
     $results = db_query('
       SELECT count(tn1.tid) AS count, tn1.nid
       FROM {term_node} AS tn1
@@ -674,17 +745,68 @@ function featured_content_sort_nodes_by_
         WHERE tn2.nid=%d
       )
       GROUP BY tn1.nid
-      ORDER BY count ' . $order, array_merge($nids, array(arg(1)))
+      ORDER BY count ' . $order, array_merge($nids, array($node_nid)) 
+    );
+    */
+    $results = db_query('
+	  SELECT tn2.tid,tn1.nid,count(tn1.tid) AS count 
+	  FROM term_node AS tn2 
+	  LEFT OUTER JOIN (term_node AS tn1) 
+	  ON (tn1.tid = tn2.tid AND tn1.nid IN (' . db_placeholders($nids, 'int') . ')) 
+	  WHERE tn2.nid = %d
+	  GROUP BY tn1.nid 
+	  ORDER BY count ' . $order, array_merge($nids, array($node_nid)) 
     );
     while ($row = db_fetch_object($results)) {
-      $tmp[$row->nid] = $node[$row->nid];
+      $tmp[$row->nid] = $nodes[$row->nid]; // Xavier Sanz: I think there was a bug here.
     }
+    
+    /*
     foreach ($nodes as $nid => $node) {
-      if (! in_array($nid, $tmp)) {
+      //if (! in_array($nid, $tmp)) { 
         // tack on the rest of the nodes
         $tmp[$nid] = $node;
+      //}
+    }
+    */
+    $nodes = $tmp;
+  }
+  return $nodes;
+}
+
+
+/**
+ * Sort nodes by words.
+ */
+
+function featured_content_sort_nodes_by_words($nodes, $node_nid, $order = 'desc') {
+  // only works if on a node page
+  // but it must be changed to admin
+  if (arg(0) == 'node' || arg(0) == 'admin' || arg(0) == 'featured-content') {
+    $tmp = array();
+    $nids = array_keys($nodes);
+    $node = node_load($node_nid);
+	$stripped_title = mysql_real_escape_string(strip_tags($node->title));
+	$stripped_teaser = mysql_real_escape_string(strip_tags($node->teaser));
+    $results = db_query('SELECT DISTINCT(nid), MATCH (title,teaser) 
+    AGAINST ("' . $stripped_title . ' ' . $stripped_teaser . '") AS count 
+    FROM {node_revisions} 
+    WHERE nid IN (' . db_placeholders($nids, 'int') . ') 
+    AND MATCH (title,teaser) AGAINST ("' . $stripped_title . ' ' . $stripped_teaser . '") 
+    ORDER BY count '.$order, array_merge($nids, array($node_nid)) 
+    );
+    while ($row = db_fetch_object($results)) {
+      $tmp[$row->nid] = $nodes[$row->nid]; // Xavier Sanz: I think there was a bug here.
       }
+    
+    /*
+    foreach ($nodes as $nid => $node) {
+      //if (! in_array($nid, $tmp)) { 
+        // tack on the rest of the nodes
+        $tmp[$nid] = $node;
+      //}
     }
+    */
     $nodes = $tmp;
   }
   return $nodes;
@@ -736,7 +860,7 @@ function featured_content_get_nodes($nid
       $totalcount_select = ', nc.totalcount ';
       $totalcount_inner_join = ' INNER JOIN {node_counter} AS nc ON n.nid=nc.nid ';
     }
-
+	//drupal_set_message($sort);
     $results = db_query(db_rewrite_sql('SELECT n.nid, n.title, n.created, n.type ' . $totalcount_select . ' FROM {node} AS n ' . $totalcount_inner_join . ' WHERE n.nid IN (' . db_placeholders($nids, 'int') . ') AND n.status <> 0'), $nids);
     while ($node = db_fetch_object($results)) {
       if ($totalcount_select == '') {
@@ -749,6 +873,124 @@ function featured_content_get_nodes($nid
 }
 
 /**
+ * Get nodes from cache table
+ *
+ */
+function featured_content_get_nodes_from_cache($delta,$nid) {
+	//drupal_set_message("Getting nodes from cache");
+	$result = db_query('SELECT nid2 FROM {featured_content_sort_cache} WHERE delta = %d AND nid1 = %d ORDER BY revision DESC LIMIT 0,1', $delta, $nid);
+ 	if($row = db_fetch_object($result)) {
+ 		$results = db_query('SELECT n.nid, n.title, n.created, n.type FROM {node} AS n WHERE n.nid IN ('.$row->nid2.')');
+    	while ($node = db_fetch_object($results)) {
+      		if ($totalcount_select == '') {
+        		$node->totalcount = 1; // treat all nodes equally for sort purposes
+      		}
+      		$nodes[$node->nid] = $node;
+    	}
+    	return $nodes;
+  	} 		
+}
+
+
+/**
+ * Set the action to perform saving or updating a node.
+ *
+ */
+function featured_content_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
+  switch ($op) {
+    case 'update':
+	//Here we will generate cache table for the node being created or updated
+	//Here we know the nid
+	$featured_content_blocks = array();
+	$featured_content_blocks = featured_content_block();
+	foreach($featured_content_blocks as $delta => $data) {
+			$featured_content = featured_content_get_block_data($delta);
+           	if($featured_content['filter']['content_types']['type'][$node->type]) {
+           		if($featured_content['type']=='filter') {
+           			if($featured_content['filter']['sort_cache'] == 'true') {
+           				//Metemos caña a la cache!!
+           				//drupal_set_message("Generating Featured Content Sort Cache...");
+           				$nids = featured_content_get_filtered_nids($data);
+           				$nodes = featured_content_get_nodes($nids, $featured_content['sort']);
+    					switch ($featured_content['sort']) {
+    						case 'random':
+      							if (is_array($nodes)) {
+        							shuffle($nodes);
+      							}
+      							break;
+    						case 'popular_asc':
+      							$nodes = featured_content_sort_nodes($nodes, 'totalcount', TRUE, 'asc');
+      							break;
+    						case 'popular_desc':
+      							$nodes = featured_content_sort_nodes($nodes, 'totalcount');
+      							break;
+    						case 'date_asc':
+      							$nodes = featured_content_sort_nodes($nodes, 'created', TRUE, 'asc');
+      							break;
+    						case 'date_desc':
+      							$nodes = featured_content_sort_nodes($nodes, 'created');
+      							break;
+    						case 'alpha_asc':
+      							$nodes = featured_content_sort_nodes($nodes, 'title', FALSE, 'asc');
+      							break;
+    						case 'alpha_desc':
+      							$nodes = featured_content_sort_nodes($nodes, 'title', FALSE);
+      							break;
+    						case 'terms_asc':
+								$nodes = featured_content_sort_nodes_by_terms($nodes, $node->nid, 'asc');
+							    break;
+    						case 'terms_desc':
+								$nodes = featured_content_sort_nodes_by_terms($nodes, $node->nid);
+      							break;
+      						//BEGIN::Xavi Sanz
+    						case 'words_asc':
+								$nodes = featured_content_sort_nodes_by_words($nodes, $node->nid, 'asc');
+							    break;
+    						case 'words_desc':
+								$nodes = featured_content_sort_nodes_by_words($nodes, $node->nid);
+      							break;
+							//END::Xavi Sanz
+    						case 'none':
+      							if ($nids) {
+        							foreach ($nids as $nid) {
+          								$tmp[] = $nodes[$nid];
+        							}	
+        							$nodes = $tmp;
+      							}
+      							break;
+    					}
+    					// Aquí cogemos los nodos resultantes y grabamos en la caché
+    					$count = 0;
+    					$nodos_cache = array();
+    					foreach($nodes as $nodo) {
+    						if($count < $featured_content['num_show']) {
+	           					$nodos_cache[] = $nodo->nid;
+	           				}
+	           				$count++;
+	           			}
+	           			$nodos = implode(",",$nodos_cache);
+	           			// Aqui grabo el registro en la tabla de la BBDD
+	           			$record = (object) NULL;
+	           			$record->delta = $delta;
+	           			$record->nid1 = $node->nid;
+	           			$record->nid2 = "$nodos";
+	           			$record->revision = time();
+	           			//print_r($record);
+	           			//if (! drupal_write_record('featured_content_sort_cache', $record, array("delta","nid1"))) {
+						drupal_write_record('featured_content_sort_cache', $record);
+							//
+						//}
+						drupal_set_message('Featured Content Cache generated for this node.');
+					}
+				}
+			}
+	}
+	//drupal_set_message("Nodo: ".$node->nid." Actualizado!!");
+	
+  }
+}
+
+/**
  * Get the block data for the given $delta.
  *
  * @param $delta
@@ -756,6 +998,7 @@ function featured_content_get_nodes($nid
  */
 function featured_content_get_block_data($delta) {
   $featured_blocks = variable_get('featured_content_blocks', array());
+  //($featured_blocks[$delta]);
   return featured_content_get_value($featured_blocks[$delta], array());
 }
 
@@ -799,3 +1042,111 @@ function featured_content_get_block_titl
   }
   return check_plain($block_title);
 }
+
+/**
+ * Generate a cache for a entire block from cron
+ */
+function featured_content_generate_sort_cache_cron($delta){
+	print "Starting time: ".date("d-m-Y H:i:s");
+	featured_content_generate_sort_cache($delta);
+	print "Ending time: ".date("d-m-Y H:i:s");
+}
+
+/**
+ * Generate a cache for a entire block
+ */
+
+function featured_content_generate_sort_cache($delta){
+	
+	drupal_set_message('Cache Generation - Starting time: '.date("d-m-Y H:i:s",time()));
+	// first we retrieve block data
+	$featured_block = featured_content_get_block_data($delta);
+	// first we must look foreach content_type marked on block
+	$content_types = featured_content_get_content_types();
+	foreach ($content_types as $content_type_name => $content_type_label) {
+		if ($featured_block['filter']['content_types']['type'][$content_type_name]) {
+			$ct[] = $content_type_name;
+		}
+	}	
+	$content_types = implode(",", $ct);
+	//drupal_set_message("SELECT nid FROM {node} WHERE type IN ('$content_types')");
+	// now we must select nodes nids from table nodes
+	$results = db_query("SELECT nid FROM {node} WHERE type IN ('%s')", $content_types);	
+	while ($row = db_fetch_object($results)){
+		$nids = array();
+		$nodes = array();
+		$node_nid = $row->nid;
+		//drupal_set_message("Cache for node $node_nid");
+		$nids = featured_content_get_filtered_nids($featured_block['filter'],$node_nid);
+		$nodes = featured_content_get_nodes($nids, $featured_block['sort']);
+		switch ($featured_block['sort']) {
+			case 'random':
+				if (is_array($nodes)) {
+					shuffle($nodes);
+				}
+				break;
+			case 'popular_asc':
+				$nodes = featured_content_sort_nodes($nodes, 'totalcount', TRUE, 'asc');
+				break;
+			case 'popular_desc':
+      			$nodes = featured_content_sort_nodes($nodes, 'totalcount');
+      			break;
+    		case 'date_asc':
+      			$nodes = featured_content_sort_nodes($nodes, 'created', TRUE, 'asc');
+      			break;
+    		case 'date_desc':
+      			$nodes = featured_content_sort_nodes($nodes, 'created');
+      			break;
+    		case 'alpha_asc':
+      			$nodes = featured_content_sort_nodes($nodes, 'title', FALSE, 'asc');
+      			break;
+    		case 'alpha_desc':
+      			$nodes = featured_content_sort_nodes($nodes, 'title', FALSE);
+				break;
+    		case 'terms_asc':
+				$nodes = featured_content_sort_nodes_by_terms($nodes, $node_nid, 'asc');
+			    break;
+    		case 'terms_desc':
+				$nodes = featured_content_sort_nodes_by_terms($nodes, $node_nid);
+      			break;
+      		//BEGIN::Xavier Sanz
+    		case 'words_asc':
+				$nodes = featured_content_sort_nodes_by_words($nodes, $node_nid, 'asc');
+			    break;
+    		case 'words_desc':
+				$nodes = featured_content_sort_nodes_by_words($nodes, $node_nid);
+      			break;
+      		//END::Xavier Sanz
+    		case 'none':
+				$tmp = array();
+      			if ($nids) {
+        			foreach ($nids as $nid) {
+          				$tmp[] = $nodes[$nid];
+        			}	
+        			$nodes = $tmp;
+      			}
+      			break;
+    	}
+    	// Aquí cogemos los nodos resultantes y grabamos en la caché
+    	$count = 0;
+    	$nodos_cache = array();
+		foreach($nodes as $nodo) {
+    		if($count < $featured_block['num_show']) {
+	       		$nodos_cache[] = $nodo->nid;
+	       	}
+	       	$count++;
+	    }
+	    $nodos = implode(",",$nodos_cache);
+	    // Aqui grabo el registro en la tabla de la BBDD
+	    $record = (object) NULL;
+	    $record->delta = $delta;
+	    $record->nid1 = $node_nid;
+	    $record->nid2 = "$nodos";
+	    $record->revision = time();
+		//if (! drupal_write_record('featured_content_sort_cache', $record, array("delta","nid1"))) {
+			drupal_write_record('featured_content_sort_cache', $record);
+		//}
+		// Here we must call the function to generate cache with nid node and delta
+	}	
+	drupal_set_message('Cache Generation - Ending time: '.date("d-m-Y H:i:s",time()));
+}
