diff options
| author | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-12-18 11:03:40 +0000 | 
|---|---|---|
| committer | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-12-18 11:03:40 +0000 | 
| commit | 4d122aa3fca560f9b93bfb5a8abe6feee96d9e61 (patch) | |
| tree | 6a4e115cb6a6acfec68fe18cc330089725bdfae7 /services | |
| parent | d8a5adc285fbd9237d7c3140f6d6a11b6eceaaee (diff) | |
| download | semanticscuttle-4d122aa3fca560f9b93bfb5a8abe6feee96d9e61.tar.gz semanticscuttle-4d122aa3fca560f9b93bfb5a8abe6feee96d9e61.tar.bz2  | |
Major refactoring: add a cache table to accelerate the search of linked tags by inference (children and synonyms)
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@204 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'services')
| -rw-r--r-- | services/bookmark2tagservice.php | 4 | ||||
| -rw-r--r-- | services/bookmarkservice.php | 2 | ||||
| -rw-r--r-- | services/servicefactory.php | 4 | ||||
| -rw-r--r-- | services/tag2tagservice.php | 110 | ||||
| -rw-r--r-- | services/tagcacheservice.php | 345 | ||||
| -rw-r--r-- | services/tagstatservice.php | 322 | 
6 files changed, 583 insertions, 204 deletions
diff --git a/services/bookmark2tagservice.php b/services/bookmark2tagservice.php index 851884f..268ec66 100644 --- a/services/bookmark2tagservice.php +++ b/services/bookmark2tagservice.php @@ -25,6 +25,9 @@ class Bookmark2TagService {  	function attachTags($bookmarkid, $tags, $fromApi = false, $extension = NULL, $replace = true, $fromImport = false) {  		// Make sure that categories is an array of trimmed strings, and that if the categories are  		// coming in from an API call to add a bookmark, that underscores are converted into strings. +		 +		trigger_error($GLOBALS['filetypes'].'bbbbbbbbbbbbbbbbbbbbbbbbbbbb'); +		  		if (!is_array($tags)) {  			$tags = trim($tags);  			if ($tags != '') { @@ -70,6 +73,7 @@ class Bookmark2TagService {  		// Media and file types  		if (!is_null($extension)) {  			include_once(dirname(__FILE__) .'/../functions.inc.php'); +			  			if ($keys = multi_array_search($extension, $GLOBALS['filetypes'])) {  				$tags[] = 'system:filetype:'. $extension;  				$tags[] = 'system:media:'. array_shift($keys); diff --git a/services/bookmarkservice.php b/services/bookmarkservice.php index 7eeed7c..ecd93f2 100644 --- a/services/bookmarkservice.php +++ b/services/bookmarkservice.php @@ -153,6 +153,8 @@ class BookmarkService {  		$uriparts = explode('.', $address);  		$extension = end($uriparts);  		unset($uriparts); +		 +		trigger_error($GLOBALS['filetypes'].'aaaaaaaaaaaaaaaaaaaaa');  		$b2tservice = & ServiceFactory :: getServiceInstance('Bookmark2TagService');  		if (!$b2tservice->attachTags($bId, $categories, $fromApi, $extension, false, $fromImport)) { diff --git a/services/servicefactory.php b/services/servicefactory.php index f4d6af7..73e5626 100644 --- a/services/servicefactory.php +++ b/services/servicefactory.php @@ -16,7 +16,8 @@ class ServiceFactory {  			if(!$db->db_connect_id) {  				message_die(CRITICAL_ERROR, "Could not connect to the database", $db);  			} -		} +		}		 +		  		if (!isset($instances[$name])) {  			if (isset($serviceoverrules[$name])) {  				$name = $serviceoverrules[$name]; @@ -25,6 +26,7 @@ class ServiceFactory {  				if (!isset($servicedir)) {  					$servicedir = dirname(__FILE__) .'/';  				} +								  				require_once($servicedir . strtolower($name) . '.php');  			}  			$instances[$name] = call_user_func(array($name, 'getInstance'), $db); diff --git a/services/tag2tagservice.php b/services/tag2tagservice.php index d19b097..9d94e2c 100644 --- a/services/tag2tagservice.php +++ b/services/tag2tagservice.php @@ -18,15 +18,15 @@ class Tag2TagService {  	function addLinkedTags($tag1, $tag2, $relationType, $uId) {  		$tagservice =& ServiceFactory::getServiceInstance('TagService');  		$tag1 = $tagservice->normalize($tag1); -		$tag2 = $tagservice->normalize($tag2);				 -		 +		$tag2 = $tagservice->normalize($tag2); +  		if($tag1 == $tag2 || strlen($tag1) == 0 || strlen($tag2) == 0  		|| ($relationType != ">" && $relationType != "=")  		|| !is_numeric($uId) || $uId<=0  		|| ($this->existsLinkedTags($tag1, $tag2, $relationType, $uId))) {  			return false;  		} -		 +  		$values = array('tag1' => $tag1, 'tag2' => $tag2, 'relationType'=> $relationType, 'uId'=> $uId);  		$query = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values);  		//die($query); @@ -37,9 +37,8 @@ class Tag2TagService {  		}  		$this->db->sql_transaction('commit'); -		// Update stats -		$tsts =& ServiceFactory::getServiceInstance('TagStatService'); -		$tsts->updateStat($tag1, $relationType, $uId); +		// Update stats and cache +		$this->update($tag1, $tag2, $relationType, $uId);  		return true;  	} @@ -77,7 +76,6 @@ class Tag2TagService {  		$output = array();  		foreach($rowset as $row) {  			if(!in_array($row['tag'], $stopList)) { -  				$output[] = $row['tag'];  			}  		} @@ -93,49 +91,69 @@ class Tag2TagService {  		return $output;  	} -	/* TODO: clean the outputs to obtain homogenous ones*/ -	function getAllLinkedTags($tag1, $relationType, $uId, $asFlatList=true, $stopList=array()) { -		$asFlatList = true; //we disable the tree list parameter for the moment - +	/* +	 * Returns all linked tags (all descendants if relation is >, +	 * all synonyms if relation is = ) +	 * $stopList allows to avoid cycle (a > b > a) between tags +	 */ +	function getAllLinkedTags($tag1, $relationType, $uId, $stopList=array()) {  		if(in_array($tag1, $stopList) || $tag1 == '') {  			return array();  		} +		// try to find data in cache +		$tcs = & ServiceFactory::getServiceInstance('TagCacheService'); +		if(count($stopList) == 0) { +			$activatedCache = true; +		} else { +			$activatedCache = false; +		} + +		// look for existing links  		$stopList[] = $tag1;  		$linkedTags = $this->getLinkedTags($tag1, $relationType, $uId, false, $stopList); -  		if($relationType != '=') {  			$linkedTags = array_merge($linkedTags, $this->getLinkedTags($tag1, '=', $uId, false, $stopList));  		}  		if(count($linkedTags) == 0) {  			return array(); +  		} else { -			$output = array(); -			if($asFlatList == true) { -				//$output[$tag1] = $tag1; -			} else { -				$output = array('node'=>$tag1); +			// use cache if possible +			if($activatedCache) { +				if($relationType == '>') { +					$output = $tcs->getChildren($tag1, $uId); +				} elseif($relationType == '=') { +					$output = $tcs->getSynonyms($tag1, $uId); +				} +				if(count($output)>0) { +					return $output; +				}  			} +			// else compute the links +			$output = array(); +  			foreach($linkedTags as $linkedTag) { -				$allLinkedTags = $this->getAllLinkedTags($linkedTag, $relationType, $uId, $asFlatList, $stopList); - -				if($asFlatList == true) { -					$output[] = $linkedTag; -					if(is_array($allLinkedTags)) { -							 -						$output = array_merge($output, $allLinkedTags); -					} else { -						$output[] = $allLinkedTags; -					} +				$allLinkedTags = $this->getAllLinkedTags($linkedTag, $relationType, $uId, $stopList); +				$output[] = $linkedTag; +				if(is_array($allLinkedTags)) { +					$output = array_merge($output, $allLinkedTags);  				} else {  					$output[] = $allLinkedTags;  				}  			} + +			// and save in cache +			if($activatedCache == true) { +				$tcs->updateTag($tag1, $relationType, $output, $uId); +			} +				 +			//$output = array_unique($output); // remove duplication +			return $output; +  		} -		//$output = array_unique($output); // remove duplication -		return $output;  	}  	function getOrphewTags($relationType, $uId = 0, $limit = null, $orderBy = null) { @@ -220,16 +238,16 @@ class Tag2TagService {  	function existsLinkedTags($tag1, $tag2, $relationType, $uId) { -		 +  		//$tag1 = mysql_real_escape_string($tag1);  		//$tag2 = mysql_real_escape_string($tag2); -		 +  		$query = "SELECT tag1, tag2, relationType, uId FROM `". $this->getTableName() ."`";  		$query.= " WHERE tag1 = '" .$tag1 ."'";  		$query.= " AND tag2 = '".$tag2."'";  		$query.= " AND relationType = '". $relationType ."'";  		$query.= " AND uId = '".$uId."'"; -		 +  		//echo($query."<br>\n");  		return $this->db->sql_numrows($this->db->sql_query($query)) > 0; @@ -263,9 +281,9 @@ class Tag2TagService {  			return false;  		} -		// Update stats -		$tsts =& ServiceFactory::getServiceInstance('TagStatService'); -		$tsts->updateStat($tag1, $relationType, $uId); + +		// Update stats and cache +		$this->update($tag1, $tag2, $relationType, $uId);  		return true;  	} @@ -273,7 +291,7 @@ class Tag2TagService {  	function renameTag($uId, $oldName, $newName) {  		$tagservice =& ServiceFactory::getServiceInstance('TagService');  		$newName = $tagservice->normalize($newName); -		 +  		$query = 'UPDATE `'. $this->getTableName() .'`';  		$query.= ' SET tag1="'.$newName.'"';  		$query.= ' WHERE tag1="'.$oldName.'"'; @@ -286,17 +304,25 @@ class Tag2TagService {  		$query.= ' AND uId="'.$uId.'"';  		$this->db->sql_query($query); -		// Update stats -		$tsts =& ServiceFactory::getServiceInstance('TagStatService'); -		$tsts->updateStat($oldName, '=', $uId); -		$tsts->updateStat($oldName, '>', $uId); -		$tsts->updateStat($newName, '=', $uId); -		$tsts->updateStat($newName, '>', $uId); + +		// Update stats and cache +		$this->update($oldName, NULL, '=', $uId); +		$this->update($oldName, NULL, '>', $uId); +		$this->update($newName, NULL, '=', $uId); +		$this->update($newName, NULL, '>', $uId);  		return true;  	} +	function update($tag1, $tag2, $relationType, $uId) { +		$tsts =& ServiceFactory::getServiceInstance('TagStatService'); +		$tsts->updateStat($tag1, $relationType, $uId); + +		$tcs = & ServiceFactory::getServiceInstance('TagCacheService'); +		$tcs->deleteByUser($uId); +	} +  	function deleteAll() {  		$query = 'TRUNCATE TABLE `'. $this->getTableName() .'`';  		$this->db->sql_query($query); diff --git a/services/tagcacheservice.php b/services/tagcacheservice.php new file mode 100644 index 0000000..bb82864 --- /dev/null +++ b/services/tagcacheservice.php @@ -0,0 +1,345 @@ +<?php + +/* + * This class infers on relation between tags by storing all the including tags or synonymous tag. + * For example, if the user creates: tag1>tag2>tag3, the system can infer that tag is included into tag1. + * Instead of computing this relation several times, it is saved into this current table. + * For synonymy, this table stores also the group of synonymous tags. + * The table must be updated for each modification of the relations between tags. + */ + +class TagCacheService { +	var $db; +	var $tablename; + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new TagCacheService($db); +		return $instance; +	} + +	function TagCacheService(&$db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'tagscache'; +	} + +	function getChildren($tag1, $uId) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag1 = $tagservice->normalize($tag1); + +		if($tag1 == '') return false; + +		$query = "SELECT DISTINCT tag2 as 'tag'"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE relationType = '>'"; +		$query.= " AND tag1 = '".$tag1."'"; +		$query.= " AND uId = '".$uId."'"; + +		//die($query); +		if (! ($dbresult =& $this->db->sql_query($query)) ){ +			message_die(GENERAL_ERROR, 'Could not get related tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + + +		$rowset = $this->db->sql_fetchrowset($dbresult); +		$output = array(); +		foreach($rowset as $row) { +			$output[] = $row['tag']; +		} + +		return $output; +	} + +	function addChild($tag1, $tag2, $uId) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag1 = $tagservice->normalize($tag1); +		$tag2 = $tagservice->normalize($tag2); + +		if($tag1 == $tag2 || strlen($tag1) == 0 || strlen($tag2) == 0 +		|| ($this->existsChild($tag1, $tag2, $uId))) { +			return false; +		} + +		$values = array('tag1' => $tag1, 'tag2' => $tag2, 'relationType'=> '>', 'uId'=> $uId); +		$query = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); +		//die($query); +		if (!($dbresult =& $this->db->sql_query($query))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not add tag cache inference', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +		$this->db->sql_transaction('commit'); +	} + +	function removeChild($tag1, $tag2, $uId) { +		if(($tag1 != '' && $tag1 == $tag2) || +		($tag1 == '' && $tag2 == '' && $uId == '')) { +			return false; +		} + +		$query = 'DELETE FROM '. $this->getTableName(); +		$query.= ' WHERE 1=1'; +		$query.= strlen($tag1)>0 ? ' AND tag1 = "'. $tag1 .'"' : ''; +		$query.= strlen($tag2)>0 ? ' AND tag2 = "'. $tag2 .'"' : ''; +		$query.= ' AND relationType = ">"'; +		$query.= strlen($uId)>0 ? ' AND uId = "'. $uId .'"' : ''; + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not remove tag cache inference', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +	} +	 +	function removeChildren($tag1, $uId) { +		$this->removeChild($tag1, NULL, $uId); +	} + +	function existsChild($tag1, $tag2, $uId) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag1 = $tagservice->normalize($tag1); +		$tag2 = $tagservice->normalize($tag2); + +		$query = "SELECT tag1, tag2, relationType, uId FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND tag2 = '".$tag2."'"; +		$query.= " AND relationType = '>'"; +		$query.= " AND uId = '".$uId."'"; + +		//echo($query."<br>\n"); + +		return $this->db->sql_numrows($this->db->sql_query($query)) > 0; + +	} + +	/* +	 * Synonyms of a same concept are a group. A group has one main synonym called key +	 * and a list of synonyms called values. +	 */ +	function addSynonym($tag1, $tag2, $uId) { + +		if($tag1 == $tag2 || strlen($tag1) == 0 || strlen($tag2) == 0 +		|| ($this->existsSynonym($tag1, $tag2, $uId))) { +			return false; +		} + +		$case1 = '0'; // not in DB +		if($this->_isSynonymKey($tag1, $uId)) { +			$case1 = 'key'; +		} elseif($this->_isSynonymValue($tag1, $uId)) { +			$case1 = 'value'; +		} + +		$case2 = '0'; // not in DB +		if($this->_isSynonymKey($tag2, $uId)) { +			$case2 = 'key'; +		} elseif($this->_isSynonymValue($tag2, $uId)) { +			$case2 = 'value'; +		} +		$case = $case1.$case2; + +		// all the possible cases +		switch ($case) { +			case 'keykey': +				$values = $this->_getSynonymValues($tag2, $uId); +				$this->removeSynonymGroup($tag2, $uId); +				foreach($values as $value) { +					$this->addSynonym($tag1, $value['tag'], $uId); +				} +				$this->addSynonym($tag1, $tag2, $uId); +				break; + +			case 'valuekey': +				$key = $this->_getSynonymKey($tag1, $uId); +				$this->addSynonym($key, $tag2, $uId); +				break; + +			case 'keyvalue': +				$this->addSynonym($tag2, $tag1, $uId); +				break; +			case 'valuevalue': +				$key1 =  $this->_getSynonymKey($tag1, $uId); +				$key2 =  $this->_getSynonymKey($tag2, $uId); +				$this->addSynonym($key1, $key2, $uId); +				break; +			case '0value': +				$key = $this->_getSynonymKey($tag2, $uId); +				$this->addSynonym($key, $tag1, $uId); +				break; +			case 'value0': +				$this->addSynonym($tag2, $tag1, $uId); +				break; +			case '0key': +				$this->addSynonym($tag2, $tag1, $uId); +				break; +			default: +				$values = array('tag1' => $tag1, 'tag2' => $tag2, 'relationType'=> '=', 'uId'=> $uId); +				$query = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); +				//die($query); +				if (!($dbresult =& $this->db->sql_query($query))) { +					$this->db->sql_transaction('rollback'); +					message_die(GENERAL_ERROR, 'Could not add tag cache synonymy', '', __LINE__, __FILE__, $query, $this->db); +					return false; +				} +				$this->db->sql_transaction('commit'); +				break; +		} +	} + +	function removeSynonymGroup($tag1, $uId) {		 +		$query = 'DELETE FROM '. $this->getTableName(); +		$query.= ' WHERE 1=1'; +		$query.= ' AND tag1 = "'. $tag1 .'"'; +		$query.= ' AND relationType = "="'; +		$query.= ' AND uId = "'. $uId .'"'; + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not remove tag cache inference', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +	} + +	function _isSynonymKey($tag1, $uId) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag1 = $tagservice->normalize($tag1); + +		$query = "SELECT tag1 FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '='"; +		$query.= " AND uId = '".$uId."'"; + +		return $this->db->sql_numrows($this->db->sql_query($query)) > 0; +	} + +	function _isSynonymValue($tag2, $uId) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag2 = $tagservice->normalize($tag2); + +		$query = "SELECT tag2 FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag2 = '" .$tag2 ."'"; +		$query.= " AND relationType = '='"; +		$query.= " AND uId = '".$uId."'"; + +		return $this->db->sql_numrows($this->db->sql_query($query)) > 0; +	} + +	function getSynonyms($tag1, $uId) {	 +		$values = array();	 +		if($this->_isSynonymKey($tag1, $uId)) { +			$values = $this->_getSynonymValues($tag1, $uId); +		} elseif($this->_isSynonymValue($tag1, $uId)) { +			$key = $this->_getSynonymKey($tag1, $uId); +			$values = $this->_getSynonymValues($key, $uId, $tag1); +			$values[] = $key;			 +		} +		return $values; +	} + +	function _getSynonymKey($tag2, $uId) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag2 = $tagservice->normalize($tag2); + +		if($this->_isSynonymKey($tag2)) return $tag2; +		 +		if($tag2 == '') return false; + +		$query = "SELECT DISTINCT tag1 as 'tag'"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE relationType = '='"; +		$query.= " AND tag2 = '".$tag2."'"; +		$query.= " AND uId = '".$uId."'"; + +		//die($query); +		if (! ($dbresult =& $this->db->sql_query($query)) ){ +			message_die(GENERAL_ERROR, 'Could not get related tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$row = $this->db->sql_fetchrow($dbresult); +		return $row['tag']; +	} + +	/* +	 * Return values associated with a key. +	 * $tagExcepted allows to hide a value. +	 */ +	function _getSynonymValues($tag1, $uId, $tagExcepted = NULL) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag1 = $tagservice->normalize($tag1); +		$tagExcepted = $tagservice->normalize($tagExcepted); + +		if($tag1 == '') return false; + +		$query = "SELECT DISTINCT tag2 as 'tag'"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE relationType = '='"; +		$query.= " AND tag1 = '".$tag1."'"; +		$query.= " AND uId = '".$uId."'"; +		$query.= $tagExcepted!=''?" AND tag2!='".$tagExcepted."'":""; + +		if (! ($dbresult =& $this->db->sql_query($query)) ){ +			message_die(GENERAL_ERROR, 'Could not get related tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$rowset = $this->db->sql_fetchrowset($dbresult); + +		$output = array(); +		foreach($rowset as $row) { +			$output[] = $row['tag']; +		} +		return $output; +	} + +	function existsSynonym($tag1, $tag2, $uId) { +		if($this->_getSynonymKey($tag1, $uId) == $tag2 || $this->_getSynonymKey($tag2, $uId) == $tag1) { +			return true; +		} else { +			return false; +		} +	} + + +	function updateTag($tag1, $relationType, $otherTags, $uId) { +		if($relationType == '=') { +			if($this->getSynonyms($tag1, $uId)) {  // remove previous data avoiding unconstistency +				$this->removeSynonymGroup($tag1, $uId); +			} +				 +			foreach($otherTags as $tag2) { +				$this->addSynonym($tag1, $tag2, $uId); +			} +		} elseif($relationType == '>') { +			if(count($this->getChildren($tag1, $uId))>0) { // remove previous data avoiding unconstistency +				$this->removeChildren($tag1); +			} +			 +			foreach($otherTags as $tag2) { +				$this->addChild($tag1, $tag2, $uId); +			} +		}		 +	} + +	function deleteByUser($uId) { +		$query = 'DELETE FROM '. $this->getTableName() .' WHERE uId = '. intval($uId); + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not delete user tags cache', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		return true; + +	} + +	function deleteAll() { +		$query = 'TRUNCATE TABLE `'. $this->getTableName() .'`'; +		$this->db->sql_query($query); +	} + +	// Properties +	function getTableName()       { return $this->tablename; } +	function setTableName($value) { $this->tablename = $value; } +} +?> diff --git a/services/tagstatservice.php b/services/tagstatservice.php index ec5f814..3a08bc0 100644 --- a/services/tagstatservice.php +++ b/services/tagstatservice.php @@ -1,181 +1,181 @@  <?php  class TagStatService { -    var $db; -    var $tablename; - -    function &getInstance(&$db) { -        static $instance; -        if (!isset($instance)) -            $instance =& new TagStatService($db); -        return $instance; -    } - -    function TagStatService(&$db) { -        $this->db =& $db; -        $this->tablename = $GLOBALS['tableprefix'] .'tagsstats'; -    } - -    function getNbChildren($tag1, $relationType, $uId) { -	$tts =& ServiceFactory::getServiceInstance('Tag2TagService'); -	$query = "SELECT tag1, relationType, uId FROM `". $tts->getTableName() ."`"; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; - -        return $this->db->sql_numrows($this->db->sql_query($query)); -    } - -    function getNbDescendants($tag1, $relationType, $uId) { -	$query = "SELECT nb FROM `". $this->getTableName() ."`"; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; - -	$dbresults =& $this->db->sql_query($query); -	$row = $this->db->sql_fetchrow($dbresults); -	if($row['nb'] == null) { -	    return 0; -	} else { -	    return (int) $row['nb']; +	var $db; +	var $tablename; + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new TagStatService($db); +		return $instance;  	} -    } - -    function getMaxDepth($tag1, $relationType, $uId) { -	$query = "SELECT depth FROM `". $this->getTableName() ."`"; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; - -	$dbresults =& $this->db->sql_query($query); -	$row = $this->db->sql_fetchrow($dbresults); -	if($row['depth'] == null) { -	    return 0; -	} else { -	    return (int) $row['depth']; -	}; -    } - -    function getNbUpdates($tag1, $relationType, $uId) { -	$query = "SELECT nbupdate FROM `". $this->getTableName() ."`"; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; - -	$dbresults =& $this->db->sql_query($query); -	$row = $this->db->sql_fetchrow($dbresults); -	if($row['nbupdate'] == null) { -	    return 0; -	} else { -	    return (int) $row['nbupdate']; + +	function TagStatService(&$db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'tagsstats'; +	} + +	function getNbChildren($tag1, $relationType, $uId) { +		$tts =& ServiceFactory::getServiceInstance('Tag2TagService'); +		$query = "SELECT tag1, relationType, uId FROM `". $tts->getTableName() ."`"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; + +		return $this->db->sql_numrows($this->db->sql_query($query)); +	} + +	function getNbDescendants($tag1, $relationType, $uId) { +		$query = "SELECT nb FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; + +		$dbresults =& $this->db->sql_query($query); +		$row = $this->db->sql_fetchrow($dbresults); +		if($row['nb'] == null) { +			return 0; +		} else { +			return (int) $row['nb']; +		} +	} + +	function getMaxDepth($tag1, $relationType, $uId) { +		$query = "SELECT depth FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; + +		$dbresults =& $this->db->sql_query($query); +		$row = $this->db->sql_fetchrow($dbresults); +		if($row['depth'] == null) { +			return 0; +		} else { +			return (int) $row['depth']; +		}; +	} + +	function getNbUpdates($tag1, $relationType, $uId) { +		$query = "SELECT nbupdate FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; + +		$dbresults =& $this->db->sql_query($query); +		$row = $this->db->sql_fetchrow($dbresults); +		if($row['nbupdate'] == null) { +			return 0; +		} else { +			return (int) $row['nbupdate']; +		}  	} -    } - -    function existStat($tag1, $relationType, $uId) { -	$query = "SELECT tag1, relationType, uId FROM `". $this->getTableName() ."`"; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; - -        return $this->db->sql_numrows($this->db->sql_query($query))>0;	 -    } - -    function createStat($tag1, $relationType, $uId) { -	$query = "INSERT INTO `". $this->getTableName() ."`"; -	$query.= "(tag1, relationType, uId)"; -	$query.= " VALUES ('".$tag1."','".$relationType."','".$uId."')"; -	$this->db->sql_query($query); -    } - -    function updateStat($tag1, $relationType, $uId=null, $stoplist=array()) { -	if(in_array($tag1, $stoplist)) { -	    return false; + +	function existStat($tag1, $relationType, $uId) { +		$query = "SELECT tag1, relationType, uId FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; + +		return $this->db->sql_numrows($this->db->sql_query($query))>0;  	} -	$tts =& ServiceFactory::getServiceInstance('Tag2TagService'); -	$linkedTags = $tts->getLinkedTags($tag1, $relationType, $uId); -	$nbDescendants = 0; -	$maxDepth = 0; -	foreach($linkedTags as $linkedTag) { -	    $nbDescendants+= 1 + $this->getNbDescendants($linkedTag, $relationType, $uId); -	    $maxDepth = max($maxDepth, 1 + $this->getMaxDepth($linkedTag, $relationType, $uId)); +	function createStat($tag1, $relationType, $uId) { +		$query = "INSERT INTO `". $this->getTableName() ."`"; +		$query.= "(tag1, relationType, uId)"; +		$query.= " VALUES ('".$tag1."','".$relationType."','".$uId."')"; +		$this->db->sql_query($query);  	} -	$this->setNbDescendants($tag1, $relationType, $uId, $nbDescendants); -	$this->setMaxDepth($tag1, $relationType, $uId, $maxDepth); -	$this->increaseNbUpdate($tag1, $relationType, $uId); - -	// propagation to the precedent tags -	$linkedTags = $tts->getLinkedTags($tag1, $relationType, $uId, true); -	$stoplist[] = $tag1; -	foreach($linkedTags as $linkedTag) { -	    $this->updateStat($linkedTag, $relationType, $uId, $stoplist); + +	function updateStat($tag1, $relationType, $uId=null, $stoplist=array()) { +		if(in_array($tag1, $stoplist)) { +			return false; +		} + +		$tts =& ServiceFactory::getServiceInstance('Tag2TagService'); +		$linkedTags = $tts->getLinkedTags($tag1, $relationType, $uId); +		$nbDescendants = 0; +		$maxDepth = 0; +		foreach($linkedTags as $linkedTag) { +			$nbDescendants+= 1 + $this->getNbDescendants($linkedTag, $relationType, $uId); +			$maxDepth = max($maxDepth, 1 + $this->getMaxDepth($linkedTag, $relationType, $uId)); +		} +		$this->setNbDescendants($tag1, $relationType, $uId, $nbDescendants); +		$this->setMaxDepth($tag1, $relationType, $uId, $maxDepth); +		$this->increaseNbUpdate($tag1, $relationType, $uId); + +		// propagation to the precedent tags +		$linkedTags = $tts->getLinkedTags($tag1, $relationType, $uId, true); +		$stoplist[] = $tag1; +		foreach($linkedTags as $linkedTag) { +			$this->updateStat($linkedTag, $relationType, $uId, $stoplist); +		}  	} -    } -    function updateAllStat() { -	$tts =& ServiceFactory::getServiceInstance('Tag2TagService'); +	function updateAllStat() { +		$tts =& ServiceFactory::getServiceInstance('Tag2TagService'); -	$query = "SELECT tag1, uId FROM `". $tts->getTableName() ."`"; -	$query.= " WHERE relationType = '>'"; +		$query = "SELECT tag1, uId FROM `". $tts->getTableName() ."`"; +		$query.= " WHERE relationType = '>'"; -//die($query); +		//die($query); -        if (! ($dbresult =& $this->db->sql_query($query)) ){ -            message_die(GENERAL_ERROR, 'Could not update stats', '', __LINE__, __FILE__, $query, $this->db); -            return false; -        } +		if (! ($dbresult =& $this->db->sql_query($query)) ){ +			message_die(GENERAL_ERROR, 'Could not update stats', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$rowset = $this->db->sql_fetchrowset($dbresult); +		foreach($rowset as $row) { +			$this->updateStat($row['tag1'], '>', $row['uId']); +		} +	} -        $rowset = $this->db->sql_fetchrowset($dbresult); -	foreach($rowset as $row) { -	    $this->updateStat($row['tag1'], '>', $row['uId']); +	function setNbDescendants($tag1, $relationType, $uId, $nb) { +		if(!$this->existStat($tag1, $relationType, $uId)) { +			$this->createStat($tag1, $relationType, $uId); +		} +		$query = "UPDATE `". $this->getTableName() ."`"; +		$query.= " SET nb = ". $nb; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; +		$this->db->sql_query($query);  	} -    } -    function setNbDescendants($tag1, $relationType, $uId, $nb) { -	if(!$this->existStat($tag1, $relationType, $uId)) { -	    $this->createStat($tag1, $relationType, $uId); +	function setMaxDepth($tag1, $relationType, $uId, $depth) { +		if(!$this->existStat($tag1, $relationType, $uId)) { +			$this->createStat($tag1, $relationType, $uId); +		} +		$query = "UPDATE `". $this->getTableName() ."`"; +		$query.= " SET depth = ". $depth; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; +		$this->db->sql_query($query);  	} -	$query = "UPDATE `". $this->getTableName() ."`"; -	$query.= " SET nb = ". $nb; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; -	$this->db->sql_query($query);	 -    } - -    function setMaxDepth($tag1, $relationType, $uId, $depth) { -	if(!$this->existStat($tag1, $relationType, $uId)) { -	    $this->createStat($tag1, $relationType, $uId); + +	function increaseNbUpdate($tag1, $relationType, $uId) { +		if(!$this->existStat($tag1, $relationType, $uId)) { +			$this->createStat($tag1, $relationType, $uId); +		} +		$query = "UPDATE `". $this->getTableName() ."`"; +		$query.= " SET nbupdate = nbupdate + 1"; +		$query.= " WHERE tag1 = '" .$tag1 ."'"; +		$query.= " AND relationType = '". $relationType ."'"; +		$query.= " AND uId = '".$uId."'"; + +		//die($query); + +		$this->db->sql_query($query);  	} -	$query = "UPDATE `". $this->getTableName() ."`"; -	$query.= " SET depth = ". $depth; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; -	$this->db->sql_query($query);	 -    } - -    function increaseNbUpdate($tag1, $relationType, $uId) { -	if(!$this->existStat($tag1, $relationType, $uId)) { -	    $this->createStat($tag1, $relationType, $uId); + +	function deleteAll() { +		$query = 'TRUNCATE TABLE `'. $this->getTableName() .'`'; +		$this->db->sql_query($query);  	} -	$query = "UPDATE `". $this->getTableName() ."`"; -	$query.= " SET nbupdate = nbupdate + 1"; -	$query.= " WHERE tag1 = '" .$tag1 ."'"; -	$query.= " AND relationType = '". $relationType ."'"; -	$query.= " AND uId = '".$uId."'"; - -	//die($query); -	 -	$this->db->sql_query($query); -    } - -    function deleteAll() { -	$query = 'TRUNCATE TABLE `'. $this->getTableName() .'`'; -	$this->db->sql_query($query); -    } - -    // Properties -    function getTableName()       { return $this->tablename; } -    function setTableName($value) { $this->tablename = $value; } + +	// Properties +	function getTableName()       { return $this->tablename; } +	function setTableName($value) { $this->tablename = $value; }  }  ?>  | 
