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/tagcacheservice.php | |
| 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/tagcacheservice.php')
| -rw-r--r-- | services/tagcacheservice.php | 345 | 
1 files changed, 345 insertions, 0 deletions
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; } +} +?>  | 
