<?
###
###	Duplicates Detection Mechanism v.0.1
###	m.tauber@icb.at, June 2009
###
###	This mechanism allows you to detect equal Biblio items (nodes). 
###	Two or more Biblio items are defined to be equal if they have the same:
###		*title
###		*list of authors
###		*type (e.g. tech report)
###
###	(conditions are encoded in class RespubItem::equals())
###	
###	If two or more items are detected which are potentially equal the first discovered one is defined as original. 
######################################################
#	User-Usage:
#	
#	create a node in which you can store php content
# 	include this file and call the check() method. 
#	You can do that using the following example:
#	----------------------
#	$filename="/var/www/webcontent/cs/sites/all/modules/biblio/duplicatesDetection";
#
#	 if (is_file($filename)){
#	   	require($filename); 
#	 }else{
#   		print "cannot open ".$filename; 
#  	}
#
#	check();
#	----------------------
#
#####################################################
#	Developer-Usage:
#	check() reades if this mechanism should check for duplicates or if it should delete a submitted list of node ids. 
#	If node ids are submitted, they are deleted with delete(). 
#	After that the databased is searched for duplicates again by calling display().

#	display() displays discovered duplicates 
#
#	delete() deletes drupal nodes provided in a GET variable
#
#	An object of type RespubItem is created for each biblio item and stored in a list (array) of biblio items.
#	RespubItem provides a equals() method which determines a duplicate when comparing each object with the rest of the list (o^2).  
#
#	The code is used within biblio-5.x-1.13 on to of a pgsql database and may contain some dirty hacks but it works :) and potentially also work with mysql 

/**
*	cut down biblio node object which is used to detect similarities between biblio items 
*/
class RespubItem {
  protected $nid, $title, $type, $authors;

  public function __construct($nid, $title, $type, $authors) {
	$this->nid=$nid;
 	$this->title=$title; 
	$this->type=$type; 
	$this->authors=$authors;
  }

  public function get_nid(){
	return $this->nid;
  }

  public function get_title(){
	return $this->title;
  }

  public function get_authors(){
	return $this->authors;
  }
  public function get_type(){
	return $this->type;
  }


  public function equals($item) {
	$o_nid=$item->nid;
	$t_nid=$this->nid;

	if($o_nid === $t_nid){
		return TRUE;
	}
	if((strcmp($item->title,$this->title)==0)&&($item->type==$this->type)&&(strcmp($item->authors,$this->authors)==0)){
		return TRUE;
	}
	return FALSE;
  }

  public function __toString() {
    return "nid:".$this->nid.",title:".$this->title.",authors:".$this->authors.",type:".$this->type."\n";
  }
}

/**
* the main fuction, it decides whether to actually delete things provided via HTTP GET vars or to only detect duplicats
*/

function check(){
	if($_GET['delete']== "true"){
		delete();
	}else{
		display();
	}
}
/**
*deletes drupal node ids provided in a GET variable
*/
function delete(){
	$i=0;
      	foreach($_GET AS $key => $value) {
      		${$key} = $value;
		if(preg_match("/node_id_to_be_deleted/",$key)){
			node_delete($value);
			$i++;
		}
      }

	printh("<br>deleted ".$i." items<br>");
	display();

}
/**
* selects all biblio items and creates a RespubItem for each. 
* each item is checked for similarties whith any item of the list. 
*/
function display(){
	global $DEBUG;
	$DEBUG=FALSE;
	global $respub_item;
	$respub_item = array();	
	global	$items_for_which_we_already_found_a_dub;
	$items_for_which_we_already_found_a_dub=array();

	$result=db_query("SELECT n.nid,n.title,n.created,b.* FROM {node} AS n left join {biblio} b  on n.vid=b.vid WHERE n.type = 'biblio' AND n.status=1 ORDER BY n.created DESC");
	$i=0;
	while ($node = db_fetch_object($result)) {
		// Perform operations on $node->body, etc. here.
		if($DEBUG){
			printh($node->nid);
			printh($node->title);
			printh($node->biblio_authors);
			printh($node->biblio_type);
		}
		//($nid, $title, $type, $authors)
		$respub_item[$i] = new RespubItem($node->nid,$node->title,$node->biblio_type,$node->biblio_authors);
		$i++;
  	}
	#printh("DEBUG: made ".$i." respub items, the size of the respub array is ".sizeof($respub_item));
	$q=$_GET['q'];
	$action= $_SERVER['URI']."?q=".$q;

	$text_per_item=array();
	for($a=0;$a<sizeof($respub_item);$a++){
		$item = $respub_item[$a];
    		$d=check_4_dups($item);
		if($d !=""){
			array_push($text_per_item,$d);
		}
	}
	$content ="Found potential duplicates for ".count($text_per_item)." respub items.";
	if(count($text_per_item)>=1){
		$content .= "<form name=\"dub_del_form\" action=\"".$action."\" method=\"GET\">";
		$content .= "<input type=\"hidden\" name=\"q\" value=\"".$q."\">";
		for($i=0;$i<sizeof($text_per_item);$i++){
			$content .= $text_per_item[$i];
		}
		$content .= "<input type=\"hidden\" name=\"delete\" value=\"true\">";
		$content .= "<input type=\"submit\" value=\"delete all selected\">";
	}else{
		$content .= "No (more) duplicates found."; 
		$content .= "You can continue your work by going <a href=/new_respub_system>here</a>.";
	}

	printh($content);
}
/**
 * goes through the entired list and compare is a specific object of type RespubItem does have any duplicates 
 */
function check_4_dups($item_to_chk){	
	$DEBUG=False;
	$content ="";
	global $respub_item;
	global $items_for_which_we_already_found_a_dub;
	$equ=array();
	$i=0;
	foreach ($respub_item as &$item) {
		if($DEBUG){
			if(strcmp($item_to_chk->get_title(),$item->get_title())==0) {
				if($item->get_nid()!=$item_to_chk->get_nid()){
				printh("DEBUG: check:".$item_to_chk->get_title()." vs ".$item->get_title());;
				printh("DEBUG: the node ids of the two items are:".$item->get_nid()." & ".$item_to_chk->get_nid());	
				printh("DEBUG: authors list 1:".$item->get_authors()." & 2:".$item_to_chk->get_authors());	
				if(strcmp($item->get_authors(),$item_to_chk->get_authors())==0)
				{
					printh("DEBUG:authors are equal");
				}
				printh("DEBUG: type 1:".$item->get_type()." & 2:".$item_to_chk->get_type());	
				if($item_to_chk->equals($item)){
					printh("DEBUG: this is a duplicate");
				}else{
					printh("DEBUG: this is NOT a duplicate");
				}
				printh("DEBUG:");
				}
			}
		}
		##if item got the same title, authors and type but if it has not the same nid 
		## (otherwise it is rather the same item than being equal)
		if(($item_to_chk->equals($item))&&($item_to_chk->get_nid()!=$item->get_nid())){
			#but before we realy record it as duplicate we check if we have no already recorded this item
			$a=0;
			foreach ($items_for_which_we_already_found_a_dub as &$already_recorded_nid) {
				#printh($already_recorded->get_nid()." vs ".$item->get_nid());
				if($item->get_nid()==$already_recorded_nid){
					#printh("this has already been recorded");
					$a++;
				}
			}
			if($a==0){	
				$equ[$i]=$item;
				$i++;	
				array_push($items_for_which_we_already_found_a_dub,$item->get_nid());
				array_push($items_for_which_we_already_found_a_dub,$item_to_chk->get_nid()); //dirty hack alarm 
				#printh("DEBUG: found dups:".$item_to_chk->get_title()." vs ".$item->get_title());;
			}
		}
	}
	if(count($equ)>0){
		$content .= "<br>Original item: ".showRespubItem($item_to_chk)." :"; 
		$content .= "<ul>\n";
		foreach ($equ as &$item) {
			$content .="<li>".show_dup($item)."\n";	
		}
		$content .= "</ul>\n";
	}
	#printh("-->".$content."<--");
	return $content;
}

function show_dup($item){
	return "delete duplicate: <input type=\"checkbox\" name=\"node_id_to_be_deleted".$item->get_nid()."\" value=".$item->get_nid().">: ".showRespubItem($item);
}

function showRespubItem($item){
	$node=node_load($item->get_nid());
	return $node->biblio_authors.".\"<a href=?q=node/".$item->get_nid()." target=\"_blank\" >".$item->get_title()."</a>\",<i>".$node->biblio_secondary_title.",</i>".$node->biblio_publisher;
}

function printh($string){
	print $string."\n<br>";
}

?>
