diff options
Diffstat (limited to 'src/SemanticScuttle/Service')
| -rw-r--r-- | src/SemanticScuttle/Service/bookmark2tagservice.php | 478 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/bookmarkservice.php | 552 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/cacheservice.php | 38 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/commondescriptionservice.php | 167 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/searchhistoryservice.php | 124 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/servicefactory.php | 38 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/tag2tagservice.php | 377 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/tagcacheservice.php | 349 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/tagservice.php | 123 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/tagstatservice.php | 193 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/templateservice.php | 46 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/userservice.php | 665 | 
12 files changed, 3150 insertions, 0 deletions
| diff --git a/src/SemanticScuttle/Service/bookmark2tagservice.php b/src/SemanticScuttle/Service/bookmark2tagservice.php new file mode 100644 index 0000000..918fb5b --- /dev/null +++ b/src/SemanticScuttle/Service/bookmark2tagservice.php @@ -0,0 +1,478 @@ +<?php +class Bookmark2TagService { +	var $db; +	var $tablename; + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new Bookmark2TagService($db); +		return $instance; +	} + +	function Bookmark2TagService(&$db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'bookmarks2tags'; +	} + +	function isNotSystemTag($var) { +		if (utf8_substr($var, 0, 7) == 'system:') +		return false; +		else +		return true; +	} + +	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. +		 +		if (!is_array($tags)) { +			$tags = trim($tags); +			if ($tags != '') { +				if (substr($tags, -1) == ',') { +					$tags = substr($tags, 0, -1); +				} +				if ($fromApi) { +					$tags = explode(' ', $tags); +				} else { +					$tags = explode(',', $tags); +				} +			} else { +				$tags = null; +			} +		} + +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tags = $tagservice->normalize($tags); + + +		$tags_count = is_array($tags)?count($tags):0; +		 +		for ($i = 0; $i < $tags_count; $i++) { +			$tags[$i] = trim(strtolower($tags[$i])); +			if ($fromApi) { +				include_once(dirname(__FILE__) .'/../functions.inc.php'); +				$tags[$i] = convertTag($tags[$i], 'in'); +			} +		} + +		if ($tags_count > 0) { +			// Remove system tags +			$tags = array_filter($tags, array($this, "isNotSystemTag")); + +			// Eliminate any duplicate categories +			$temp = array_unique($tags); +			$tags = array_values($temp); +		} else { +			// Unfiled +			$tags[] = 'system:unfiled'; +		} + +		// 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); +			} +		} + +		// Imported +		if ($fromImport) { +			$tags[] = 'system:imported'; +		} + +		$this->db->sql_transaction('begin'); + +		if ($replace) { +			if (!$this->deleteTagsForBookmark($bookmarkid)){ +				$this->db->sql_transaction('rollback'); +				message_die(GENERAL_ERROR, 'Could not attach tags (deleting old ones failed)', '', __LINE__, __FILE__, $sql, $this->db); +				return false; +			} +		} + +		$bs =& ServiceFactory::getServiceInstance('BookmarkService'); +		$tts =& ServiceFactory::getServiceInstance('Tag2TagService'); + +		// Create links between tags +		foreach($tags as $key => $tag) { +			if(strpos($tag, '=')) { +				// case "=" +				$pieces = explode('=', $tag); +				$nbPieces = count($pieces); +				if($nbPieces > 1) { +					for($i = 0; $i < $nbPieces-1; $i++) { +						$bookmark = $bs->getBookmark($bookmarkid); +						$uId = $bookmark['uId']; +						$tts->addLinkedTags($pieces[$i], $pieces[$i+1], '=', $uId); +					} +					$tags[$key] = $pieces[0]; // Attach just the last tag to the bookmark +				} +			} else { +				// case ">" +				$pieces = explode('>', $tag); +				$nbPieces = count($pieces); +				if($nbPieces > 1) { +					for($i = 0; $i < $nbPieces-1; $i++) { +						$bookmark = $bs->getBookmark($bookmarkid); +						$uId = $bookmark['uId']; +						$tts->addLinkedTags($pieces[$i], $pieces[$i+1], '>', $uId); +					} +					$tags[$key] = $pieces[$nbPieces-1]; // Attach just the last tag to the bookmark +				} +			} + + +		} + +		// Add the categories to the DB. +		for ($i = 0; $i < count($tags); $i++) { +			if ($tags[$i] != '') { +				$values = array( +                    'bId' => intval($bookmarkid), +                    'tag' => $tags[$i] +				); + +				if (!$this->hasTag($bookmarkid, $tags[$i])) { +					$sql = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); +					if (!($dbresult =& $this->db->sql_query($sql))) { +						$this->db->sql_transaction('rollback'); +						message_die(GENERAL_ERROR, 'Could not attach tags', '', __LINE__, __FILE__, $sql, $this->db); +						return false; +					} +				} +			} +		} +		$this->db->sql_transaction('commit'); +		return true; +	} + +	function deleteTag($uId, $tag) { +		$bs =& ServiceFactory::getServiceInstance('BookmarkService'); + +		$query = 'DELETE FROM '. $this->getTableName(); +		$query.= ' USING '. $this->getTableName() .', '. $bs->getTableName(); +		$query.= ' WHERE '. $this->getTableName() .'.bId = '. $bs->getTableName() .'.bId'; +		$query.= ' AND '. $bs->getTableName() .'.uId = '. $uId; +		$query.= ' AND '. $this->getTableName() .'.tag = "'. $this->db->sql_escape($tag) .'"'; + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not delete tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		return true; +	} + +	function deleteTagsForBookmark($bookmarkid) { +		if (!is_int($bookmarkid)) { +			message_die(GENERAL_ERROR, 'Could not delete tags (invalid bookmarkid)', '', __LINE__, __FILE__, $query); +			return false; +		} + +		$query = 'DELETE FROM '. $this->getTableName() .' WHERE bId = '. intval($bookmarkid); + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not delete tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		return true; +	} + +	/* Allow deletion in admin page */ +	function deleteTagsForUser($uId) {
 +		$qmask = 'DELETE FROM %s USING %s, %s WHERE %s.bId = %s.bId AND %s.uId = %d';
 +		$query = sprintf($qmask,
 +		$this->getTableName(),
 +		$this->getTableName(),
 +		$GLOBALS['tableprefix'].'bookmarks',
 +		$this->getTableName(),
 +		$GLOBALS['tableprefix'].'bookmarks',
 +		$GLOBALS['tableprefix'].'bookmarks',
 +		$uId);
 +
 +		if (!($dbresult =& $this->db->sql_query($query))) {
 +			message_die(GENERAL_ERROR, 'Could not delete tags', '', __LINE__, __FILE__, $query, $this->db);
 +			return false;
 +		}
 +
 +		return true;
 +	} + +	function &getTagsForBookmark($bookmarkid) { +		if (!is_numeric($bookmarkid)) { +			message_die(GENERAL_ERROR, 'Could not get tags (invalid bookmarkid)', '', __LINE__, __FILE__, $query); +			return false; +		} + +		$query = 'SELECT tag FROM '. $this->getTableName() .' WHERE bId = '. intval($bookmarkid) .' AND LEFT(tag, 7) <> "system:" ORDER BY id ASC'; + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$tags = array(); +		while ($row =& $this->db->sql_fetchrow($dbresult)) { +			$tags[] = $row['tag']; +		} +		$this->db->sql_freeresult($dbresult); +		return $tags; +	} + +	function &getTags($userid = NULL) { +		$userservice =& ServiceFactory::getServiceInstance('UserService'); +		$logged_on_user = $userservice->getCurrentUserId(); + +		$query = 'SELECT T.tag, COUNT(B.bId) AS bCount FROM '. $GLOBALS['tableprefix'] .'bookmarks AS B INNER JOIN '. $userservice->getTableName() .' AS U ON B.uId = U.'. $userservice->getFieldName('primary') .' INNER JOIN '. $GLOBALS['tableprefix'] .'bookmarks2tags AS T ON B.bId = T.bId'; + +		$conditions = array(); +		if (!is_null($userid)) { +			$conditions['U.'. $userservice->getFieldName('primary')] = intval($userid); +			if ($logged_on_user != $userid) +			$conditions['B.bStatus'] = 0; +		} else { +			$conditions['B.bStatus'] = 0; +		} + +		$query .= ' WHERE '. $this->db->sql_build_array('SELECT', $conditions) .' AND LEFT(T.tag, 7) <> "system:" GROUP BY T.tag ORDER BY bCount DESC, tag'; + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$output = $this->db->sql_fetchrowset($dbresult); +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + + +	// Returns the tags related to the specified tags; i.e. attached to the same bookmarks +	function &getRelatedTags($tags, $for_user = NULL, $logged_on_user = NULL, $limit = 10) { +		$conditions = array(); +		// Only count the tags that are visible to the current user. +		if ($for_user != $logged_on_user || is_null($for_user)) +		$conditions['B.bStatus'] = 0; + +		if (!is_null($for_user)) +		$conditions['B.uId'] = $for_user; + +		// Set up the tags, if need be. +		if (is_numeric($tags)) +		$tags = NULL; +		if (!is_array($tags) and !is_null($tags)) +		$tags = explode('+', trim($tags)); + +		$tagcount = count($tags); +		for ($i = 0; $i < $tagcount; $i++) { +			$tags[$i] = trim($tags[$i]); +		} + +		// Set up the SQL query. +		$query_1 = 'SELECT DISTINCTROW T0.tag, COUNT(B.bId) AS bCount FROM '. $GLOBALS['tableprefix'] .'bookmarks AS B, '. $this->getTableName() .' AS T0'; +		$query_2 = ''; +		$query_3 = ' WHERE B.bId = T0.bId '; +		if (count($conditions) > 0) +		$query_4 = ' AND '. $this->db->sql_build_array('SELECT', $conditions); +		else +		$query_4 = ''; +		// Handle the parts of the query that depend on any tags that are present. +		for ($i = 1; $i <= $tagcount; $i++) { +			$query_2 .= ', '. $this->getTableName() .' AS T'. $i; +			$query_4 .= ' AND T'. $i .'.bId = B.bId AND T'. $i .'.tag = "'. $this->db->sql_escape($tags[$i - 1]) .'" AND T0.tag <> "'. $this->db->sql_escape($tags[$i - 1]) .'"'; +		} +		$query_5 = ' AND LEFT(T0.tag, 7) <> "system:" GROUP BY T0.tag ORDER BY bCount DESC, T0.tag'; +		$query = $query_1 . $query_2 . $query_3 . $query_4 . $query_5; + +		if (! ($dbresult =& $this->db->sql_query_limit($query, $limit)) ){ +			message_die(GENERAL_ERROR, 'Could not get related tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +		$output = $this->db->sql_fetchrowset($dbresult); +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	// Returns the most popular tags used for a particular bookmark hash +	function &getRelatedTagsByHash($hash, $limit = 20) { +		$userservice = & ServiceFactory :: getServiceInstance('UserService'); +		$sId = $userservice->getCurrentUserId(); +		// Logged in +		if ($userservice->isLoggedOn()) { +			$arrWatch = $userservice->getWatchList($sId); +			// From public bookmarks or user's own +			$privacy = ' AND ((B.bStatus = 0) OR (B.uId = '. $sId .')'; +			// From shared bookmarks in watchlist +			foreach ($arrWatch as $w) { +				$privacy .= ' OR (B.uId = '. $w .' AND B.bStatus = 1)'; +			} +			$privacy .= ') '; +			// Not logged in +		} else { +			$privacy = ' AND B.bStatus = 0 '; +		} + +		$query = 'SELECT T.tag, COUNT(T.tag) AS bCount FROM '.$GLOBALS['tableprefix'].'bookmarks AS B LEFT JOIN '.$GLOBALS['tableprefix'].'bookmarks2tags AS T ON B.bId = T.bId WHERE B.bHash = "'. $hash .'" '. $privacy .'AND LEFT(T.tag, 7) <> "system:" GROUP BY T.tag ORDER BY bCount DESC'; + +		if (!($dbresult =& $this->db->sql_query_limit($query, $limit))) { +			message_die(GENERAL_ERROR, 'Could not get related tags for this hash', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +		$output = $this->db->sql_fetchrowset($dbresult); +		$this->db->sql_freeresult($dbresult); +		return $output; +	} +	 +	function &getAdminTags($limit = 30, $logged_on_user = NULL, $days = NULL) { +		// look for admin ids +		$userservice = & ServiceFactory :: getServiceInstance('UserService'); +		$adminIds = $userservice->getAdminIds(); +		 +		// ask for their tags +		return $this->getPopularTags($adminIds, $limit, $logged_on_user, $days); +	} +	 +	function &getContactTags($user, $limit = 30, $logged_on_user = NULL, $days = NULL) { +		// look for contact ids +		$userservice = & ServiceFactory :: getServiceInstance('UserService'); +		$contacts = $userservice->getWatchlist($user); +		 +		// add the user (to show him/her also his/her tags) +		if(!is_null($logged_on_user)) { +			$contacts[] = $logged_on_user; +		} +		 +		// ask for their tags +		return $this->getPopularTags($contacts, $limit, $logged_on_user, $days); +	}	 + +	// $users can be {NULL, an id, an array of id} +	function &getPopularTags($user = NULL, $limit = 30, $logged_on_user = NULL, $days = NULL) { +		// Only count the tags that are visible to the current user. +		if (($user != $logged_on_user) || is_null($user) || ($user === false)) +		$privacy = ' AND B.bStatus = 0'; +		else +		$privacy = ''; + +		if (is_null($days) || !is_int($days)) +		$span = ''; +		else +		$span = ' AND B.bDatetime > "'. date('Y-m-d H:i:s', time() - (86400 * $days)) .'"'; + +		$query = 'SELECT T.tag, COUNT(T.bId) AS bCount FROM '. $this->getTableName() .' AS T, '. $GLOBALS['tableprefix'] .'bookmarks AS B WHERE '; +		if (is_null($user) || ($user === false)) { +			$query .= 'B.bId = T.bId AND B.bStatus = 0'; +		} elseif(is_array($user)) { +			$query .= ' (1 = 0';  //tricks +			foreach($user as $u) {			 +				$query .= ' OR B.uId = '. $this->db->sql_escape($u) .' AND B.bId = T.bId'; +			} +			$query .= ' )'; +		} else { +			$query .= 'B.uId = '. $this->db->sql_escape($user) .' AND B.bId = T.bId'. $privacy; +		} +		$query .= $span .' AND LEFT(T.tag, 7) <> "system:" GROUP BY T.tag ORDER BY bCount DESC, tag'; + +		if (!($dbresult =& $this->db->sql_query_limit($query, $limit))) { +			message_die(GENERAL_ERROR, 'Could not get popular tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$output = $this->db->sql_fetchrowset($dbresult); +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	function hasTag($bookmarkid, $tag) { +		$query = 'SELECT COUNT(*) AS tCount FROM '. $this->getTableName() .' WHERE bId = '. intval($bookmarkid) .' AND tag ="'. $this->db->sql_escape($tag) .'"'; + +		if (! ($dbresult =& $this->db->sql_query($query)) ) { +			message_die(GENERAL_ERROR, 'Could not find tag', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			if ($row['tCount'] > 0) { +				$output = true; +			} +		} +		$output = false; +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	function renameTag($userid, $old, $new, $fromApi = false) { +		$bookmarkservice =& ServiceFactory::getServiceInstance('BookmarkService'); +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); + +		if (is_null($userid) || is_null($old) || is_null($new)) +		return false; + +		// Find bookmarks with old tag +		$bookmarksInfo =& $bookmarkservice->getBookmarks(0, NULL, $userid, $old); +		$bookmarks =& $bookmarksInfo['bookmarks']; + +		// Delete old tag +		$this->deleteTag($userid, $old); + +		// Attach new tags +		$new = $tagservice->normalize($new); +		 +		foreach(array_keys($bookmarks) as $key) { +			$row =& $bookmarks[$key]; +			$this->attachTags($row['bId'], $new, $fromApi, NULL, false); +		} + +		return true; +	} + +	function &tagCloud($tags = NULL, $steps = 5, $sizemin = 90, $sizemax = 225, $sortOrder = NULL) { + +		if (is_null($tags) || count($tags) < 1) { +			$output = false; +			return $output; +		} + +		$min = $tags[count($tags) - 1]['bCount']; +		$max = $tags[0]['bCount']; + +		for ($i = 1; $i <= $steps; $i++) { +			$delta = ($max - $min) / (2 * $steps - $i); +			$limit[$i] = $i * $delta + $min; +		} +		$sizestep = ($sizemax - $sizemin) / $steps; +		foreach ($tags as $row) { +			$next = false; +			for ($i = 1; $i <= $steps; $i++) { +				if (!$next && $row['bCount'] <= $limit[$i]) { +					$size = $sizestep * ($i - 1) + $sizemin; +					$next = true; +				} +			} +			$tempArray = array('size' => $size .'%'); +			$row = array_merge($row, $tempArray); +			$output[] = $row; +		} + +		if ($sortOrder == 'alphabet_asc') { +			usort($output, create_function('$a,$b','return strcasecmp(utf8_deaccent($a["tag"]), utf8_deaccent($b["tag"]));')); +		} + +		return $output; +	} + +	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/src/SemanticScuttle/Service/bookmarkservice.php b/src/SemanticScuttle/Service/bookmarkservice.php new file mode 100644 index 0000000..f119593 --- /dev/null +++ b/src/SemanticScuttle/Service/bookmarkservice.php @@ -0,0 +1,552 @@ +<?php +class BookmarkService { +	var $db; +	var $tablename; + +	function & getInstance(& $db) { +		static $instance; +		if (!isset ($instance)) +		$instance = & new BookmarkService($db); +		return $instance; +	} + +	function BookmarkService(& $db) { +		$this->db = & $db; +		$this->tablename = $GLOBALS['tableprefix'] .'bookmarks'; +	} + +	function _getbookmark($fieldname, $value, $all = false) { +		if (!$all) { +			$userservice = & ServiceFactory :: getServiceInstance('UserService'); +			$sId = $userservice->getCurrentUserId(); +			$range = ' AND uId = '. $sId; +		} else { +			$range = ''; +		} + +		$query = 'SELECT * FROM '. $this->getTableName() .' WHERE '. $fieldname .' = "'. $this->db->sql_escape($value) .'"'. $range; + +		if (!($dbresult = & $this->db->sql_query_limit($query, 1, 0))) { +			message_die(GENERAL_ERROR, 'Could not get bookmark', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			$output = $row; +		} else { +			$output =  false; +		} +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	function & getBookmark($bid, $include_tags = false) { +		if (!is_numeric($bid)) +		return; + +		$sql = 'SELECT * FROM '. $this->getTableName() .' WHERE bId = '. $this->db->sql_escape($bid); + +		if (!($dbresult = & $this->db->sql_query($sql))) +		message_die(GENERAL_ERROR, 'Could not get vars', '', __LINE__, __FILE__, $sql, $this->db); + +		if ($row = & $this->db->sql_fetchrow($dbresult)) { +			if ($include_tags) { +				$b2tservice = & ServiceFactory :: getServiceInstance('Bookmark2TagService'); +				$row['tags'] = $b2tservice->getTagsForBookmark($bid); +			} +			$output = $row;			 +		} else { +			$output = false; +		} +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	function getBookmarkByAddress($address) { +		$hash = md5($address); +		return $this->getBookmarkByHash($hash); +	} + +	function getBookmarkByHash($hash) { +		return $this->_getbookmark('bHash', $hash, true); +	} + +	/* Counts bookmarks for a user. $range = {'public', 'shared', 'private', 'all'}*/ +	function countBookmarks($uId, $range = 'public') { +		$sql = 'SELECT COUNT(*) FROM '. $GLOBALS['tableprefix'] .'bookmarks'; +		$sql.= ' WHERE uId = '.$uId; +		switch ($range) { +			case 'all': +			//no constraints +			break; +			case 'private': +			$sql.= ' AND bStatus = 2'; +			break; +			case 'shared': +			$sql.= ' AND bStatus = 1'; +			break;			 +			case 'public': +			default: +			$sql.= ' AND bStatus = 0'; +			break; +		}			 +		 +		if (!($dbresult = & $this->db->sql_query($sql))) { +			message_die(GENERAL_ERROR, 'Could not get vars', '', __LINE__, __FILE__, $sql, $this->db); +		} +		return $this->db->sql_fetchfield(0, 0); +	} + +	/** +	 * Check if a bookmark may be edited by the current user +     * +	 * @param integer|array $bookmark Bookmark uId or bookmark array +	 * +	 * @return boolean True if allowed +	 */ +	function editAllowed($bookmark) +	{ +		if (!is_numeric($bookmark) && (!is_array($bookmark) +			|| !is_numeric($bookmark['bId'])) +		) { +			return false; +		} + +		if (!is_array($bookmark) +			 && !($bookmark = $this->getBookmark($bookmark)) +		) { +			return false; +		} + +		$userservice = & ServiceFactory::getServiceInstance('UserService'); +		$user = $userservice->getCurrentUser(); + +		//user has to be either admin, or owner +		if ($GLOBALS['adminsCanModifyBookmarksFromOtherUsers'] +			&& $userservice->isAdmin($user) +		) { +			return true; +		} else { +			return ($bookmark['uId'] == $user['uId']); +		} +	} + +	function bookmarkExists($address = false, $uid = NULL) { +		if (!$address) { +			return; +		} + +		$address = $this->normalize($address); + +		$crit = array ('bHash' => md5($address)); +		if (isset ($uid)) { +			$crit['uId'] = $uid; +		} + +		$sql = 'SELECT COUNT(*) FROM '. $GLOBALS['tableprefix'] .'bookmarks WHERE '. $this->db->sql_build_array('SELECT', $crit); +		if (!($dbresult = & $this->db->sql_query($sql))) { +			message_die(GENERAL_ERROR, 'Could not get vars', '', __LINE__, __FILE__, $sql, $this->db); +		} +		if($this->db->sql_fetchfield(0, 0) > 0) { +			$output = true;  +		} else { +			$output = false; +		} +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	// Adds a bookmark to the database. +	// Note that date is expected to be a string that's interpretable by strtotime(). +	function addBookmark($address, $title, $description, $privateNote, $status, $categories, $date = NULL, $fromApi = false, $fromImport = false, $sId = -1) { +		if($sId == -1) { +			$userservice = & ServiceFactory :: getServiceInstance('UserService'); +			$sId = $userservice->getCurrentUserId(); +		} + +		$address = $this->normalize($address); + +		// Get the client's IP address and the date; note that the date is in GMT. +		if (getenv('HTTP_CLIENT_IP')) +		$ip = getenv('HTTP_CLIENT_IP'); +		else +		if (getenv('REMOTE_ADDR')) +		$ip = getenv('REMOTE_ADDR'); +		else +		$ip = getenv('HTTP_X_FORWARDED_FOR'); + +		// Note that if date is NULL, then it's added with a date and time of now, and if it's present, +		// it's expected to be a string that's interpretable by strtotime(). +		if (is_null($date) || $date == '') +		$time = time(); +		else +		$time = strtotime($date); +		$datetime = gmdate('Y-m-d H:i:s', $time); + +		// Set up the SQL insert statement and execute it. +		$values = array('uId' => intval($sId), 'bIp' => $ip, 'bDatetime' => $datetime, 'bModified' => $datetime, 'bTitle' => $title, 'bAddress' => $address, 'bDescription' => $description, 'bPrivateNote' => $privateNote, 'bStatus' => intval($status), 'bHash' => md5($address)); +		$sql = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not insert bookmark', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} +		// Get the resultant row ID for the bookmark. +		$bId = $this->db->sql_nextid($dbresult); +		if (!isset($bId) || !is_int($bId)) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not insert bookmark', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} + +		$uriparts = explode('.', $address); +		$extension = end($uriparts); +		unset($uriparts); + +		$b2tservice = & ServiceFactory :: getServiceInstance('Bookmark2TagService'); +		if (!$b2tservice->attachTags($bId, $categories, $fromApi, $extension, false, $fromImport)) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not insert bookmark', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} +		$this->db->sql_transaction('commit'); +		// Everything worked out, so return the new bookmark's bId. +		return $bId; +	} + +	function updateBookmark($bId, $address, $title, $description, $privateNote, $status, $categories, $date = NULL, $fromApi = false) { +		if (!is_numeric($bId)) +		return false;		 + +		// Get the client's IP address and the date; note that the date is in GMT. +		if (getenv('HTTP_CLIENT_IP')) +		$ip = getenv('HTTP_CLIENT_IP'); +		else +		if (getenv('REMOTE_ADDR')) +		$ip = getenv('REMOTE_ADDR'); +		else +		$ip = getenv('HTTP_X_FORWARDED_FOR'); + +		$moddatetime = gmdate('Y-m-d H:i:s', time()); +		 +		$address = $this->normalize($address); +		 +		//check if a new address ($address) doesn't already exist for another bookmark from the same user  +		$bookmark = $this->getBookmark($bId); +		if($bookmark['bAddress'] != $address && $this->bookmarkExists($address, $bookmark['uId'])) { +			message_die(GENERAL_ERROR, 'Could not update bookmark (URL already existing = '.$address.')', '', __LINE__, __FILE__); +			return false; +		} + +		// Set up the SQL update statement and execute it. +		$updates = array('bModified' => $moddatetime, 'bTitle' => $title, 'bAddress' => $address, 'bDescription' => $description, 'bPrivateNote' => $privateNote, 'bStatus' => $status, 'bHash' => md5($address)); + +		if (!is_null($date)) { +			$datetime = gmdate('Y-m-d H:i:s', strtotime($date)); +			$updates[] = array('bDateTime' => $datetime); +		} + +		$sql = 'UPDATE '. $GLOBALS['tableprefix'] .'bookmarks SET '. $this->db->sql_build_array('UPDATE', $updates) .' WHERE bId = '. intval($bId); +		$this->db->sql_transaction('begin'); + +		if (!($dbresult = & $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not update bookmark', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} + +		$uriparts = explode('.', $address); +		$extension = end($uriparts); +		unset($uriparts); + +		$b2tservice = & ServiceFactory :: getServiceInstance('Bookmark2TagService'); +		if (!$b2tservice->attachTags($bId, $categories, $fromApi, $extension)) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not update bookmark', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} + +		$this->db->sql_transaction('commit'); +		// Everything worked out, so return true. +		return true; +	} + +	function & getBookmarks($start = 0, $perpage = NULL, $user = NULL, $tags = NULL, $terms = NULL, $sortOrder = NULL, $watched = NULL, $startdate = NULL, $enddate = NULL, $hash = NULL) { +		// Only get the bookmarks that are visible to the current user.  Our rules: +		//  - if the $user is NULL, that means get bookmarks from ALL users, so we need to make +		//    sure to check the logged-in user's watchlist and get the contacts-only bookmarks from +		//    those users. If the user isn't logged-in, just get the public bookmarks. +		//  - if the $user is set and isn't the logged-in user, then get that user's bookmarks, and +		//    if that user is on the logged-in user's watchlist, get the public AND contacts-only +		//    bookmarks; otherwise, just get the public bookmarks. +		//  - if the $user is set and IS the logged-in user, then get all bookmarks. + +		$userservice =& ServiceFactory::getServiceInstance('UserService'); +		$b2tservice =& ServiceFactory::getServiceInstance('Bookmark2TagService'); +		$tag2tagservice =& ServiceFactory::getServiceInstance('Tag2TagService'); +		$sId = $userservice->getCurrentUserId(); + +		if ($userservice->isLoggedOn()) { +			// All public bookmarks, user's own bookmarks and any shared with user +			$privacy = ' AND ((B.bStatus = 0) OR (B.uId = '. $sId .')'; +			$watchnames = $userservice->getWatchNames($sId, true); +			foreach($watchnames as $watchuser) { +				$privacy .= ' OR (U.username = "'. $watchuser .'" AND B.bStatus = 1)'; +			} +			$privacy .= ')'; +		} else { +			// Just public bookmarks +			$privacy = ' AND B.bStatus = 0'; +		} + +		// Set up the tags, if need be. +		if (!is_array($tags) && !is_null($tags)) { +			$tags = explode('+', trim($tags)); +		} + +		$tagcount = count($tags); +		for ($i = 0; $i < $tagcount; $i ++) { +			$tags[$i] = trim($tags[$i]); +		} + +		// Set up the SQL query. +		$query_1 = 'SELECT DISTINCT '; +		if (SQL_LAYER == 'mysql4') { +			$query_1 .= 'SQL_CALC_FOUND_ROWS '; +		} +		$query_1 .= 'B.*, U.'. $userservice->getFieldName('username'); + +		$query_2 = ' FROM '. $userservice->getTableName() .' AS U, '. $this->getTableName() .' AS B'; + +		$query_3 = ' WHERE B.uId = U.'. $userservice->getFieldName('primary') . $privacy; +		if (is_null($watched)) { +			if (!is_null($user)) { +				$query_3 .= ' AND B.uId = '. $user; +			} +		} else { +			$arrWatch = $userservice->getWatchlist($user); +			if (count($arrWatch) > 0) { +				$query_3_1 = ''; +				foreach($arrWatch as $row) { +					$query_3_1 .= 'B.uId = '. intval($row) .' OR '; +				} +				$query_3_1 = substr($query_3_1, 0, -3); +			} else { +				$query_3_1 = 'B.uId = -1'; +			} +			$query_3 .= ' AND ('. $query_3_1 .') AND B.bStatus IN (0, 1)'; +		} + +		$query_5 = ''; +		if($hash == null) { +			$query_5.= ' GROUP BY B.bHash'; +		} + +		switch($sortOrder) { +			case 'date_asc': +				$query_5.= ' ORDER BY B.bModified ASC '; +				break; +			case 'title_desc': +				$query_5.= ' ORDER BY B.bTitle DESC '; +				break; +			case 'title_asc': +				$query_5.= ' ORDER BY B.bTitle ASC '; +				break; +			case 'url_desc': +				$query_5.= ' ORDER BY B.bAddress DESC '; +				break; +			case 'url_asc': +				$query_5.= ' ORDER BY B.bAddress ASC '; +				break; +			default: +				$query_5.= ' ORDER BY B.bModified DESC '; +		} + +		// Handle the parts of the query that depend on any tags that are present. +		$query_4 = ''; +		for ($i = 0; $i < $tagcount; $i ++) { +			$query_2 .= ', '. $b2tservice->getTableName() .' AS T'. $i; +			$query_4 .= ' AND ('; + +			$allLinkedTags = $tag2tagservice->getAllLinkedTags($this->db->sql_escape($tags[$i]), '>', $user); + +			while (is_array($allLinkedTags) && count($allLinkedTags)>0) { +				$query_4 .= ' T'. $i .'.tag = "'. array_pop($allLinkedTags) .'"'; +				$query_4 .= ' OR'; +			} + +			$query_4 .= ' T'. $i .'.tag = "'. $this->db->sql_escape($tags[$i]) .'"'; + +			$query_4 .= ') AND T'. $i .'.bId = B.bId'; +			//die($query_4); +		} + +		// Search terms +		if ($terms) { +			// Multiple search terms okay +			$aTerms = explode(' ', $terms); +			$aTerms = array_map('trim', $aTerms);	 + +			// Search terms in tags as well when none given +			if (!count($tags)) { +				$query_2 .= ' LEFT JOIN '. $b2tservice->getTableName() .' AS T ON B.bId = T.bId'; +				$dotags = true; +			} else { +				$dotags = false; +			} + +			$query_4 = ''; +			for ($i = 0; $i < count($aTerms); $i++) { +				$query_4 .= ' AND (B.bTitle LIKE "%'. $this->db->sql_escape($aTerms[$i]) .'%"'; +				$query_4 .= ' OR B.bDescription LIKE "%'. $this->db->sql_escape($aTerms[$i]) .'%"'; +				$query_4 .= ' OR B.bPrivateNote LIKE "'. $this->db->sql_escape($aTerms[$i]) .'%"'; //warning : search in private notes of everybody but private notes won't appear if not allowed. +				$query_4 .= ' OR U.username = "'. $this->db->sql_escape($aTerms[$i]) .'"'; //exact match for username				 +				if ($dotags) { +					$query_4 .= ' OR T.tag LIKE "'. $this->db->sql_escape($aTerms[$i]) .'%"'; +				} +				$query_4 .= ')'; +			} +		} + +		// Start and end dates +		if ($startdate) { +			$query_4 .= ' AND B.bDatetime > "'. $startdate .'"'; +		} +		if ($enddate) { +			$query_4 .= ' AND B.bDatetime < "'. $enddate .'"'; +		} + +		// Hash +		if ($hash) { +			$query_4 .= ' AND B.bHash = "'. $hash .'"'; +		} +		$query = $query_1 . $query_2 . $query_3 . $query_4 . $query_5; + +		if (!($dbresult = & $this->db->sql_query_limit($query, intval($perpage), intval($start)))) { +			message_die(GENERAL_ERROR, 'Could not get bookmarks', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if (SQL_LAYER == 'mysql4') { +			$totalquery = 'SELECT FOUND_ROWS() AS total'; +		} else { +			if ($hash) { +				$totalquery = 'SELECT COUNT(*) AS total'. $query_2 . $query_3 . $query_4; +			} else { +				$totalquery = 'SELECT COUNT(DISTINCT bAddress) AS total'. $query_2 . $query_3 . $query_4; +			} +		} + +		if (!($totalresult = & $this->db->sql_query($totalquery)) || (!($row = & $this->db->sql_fetchrow($totalresult)))) { +			message_die(GENERAL_ERROR, 'Could not get total bookmarks', '', __LINE__, __FILE__, $totalquery, $this->db); +			return false; +		} + +		$total = $row['total']; +		$this->db->sql_freeresult($totalresult); + +		$bookmarks = array(); +		while ($row = & $this->db->sql_fetchrow($dbresult)) { +			$row['tags'] = $b2tservice->getTagsForBookmark(intval($row['bId'])); +			$bookmarks[] = $row; +		} + +		$this->db->sql_freeresult($dbresult); +		$output = array ('bookmarks' => $bookmarks, 'total' => $total); +		return $output; +	} + +	function deleteBookmark($bookmarkid) { +		$query = 'DELETE FROM '. $GLOBALS['tableprefix'] .'bookmarks WHERE bId = '. intval($bookmarkid); +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($query))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not delete bookmarks', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +		 +		 + +		$query = 'DELETE FROM '. $GLOBALS['tableprefix'] .'bookmarks2tags WHERE bId = '. intval($bookmarkid); +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($query))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not delete bookmarks', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$this->db->sql_transaction('commit'); +		return true; +	} + +	function deleteBookmarksForUser($uId) {
 +		$query = 'DELETE FROM '. $GLOBALS['tableprefix'] .'bookmarks WHERE uId = '. intval($uId);
 +
 +		if (!($dbresult = & $this->db->sql_query($query))) {
 +			message_die(GENERAL_ERROR, 'Could not delete bookmarks', '', __LINE__, __FILE__, $query, $this->db);
 +			return false;
 +		}
 +
 +		return true;
 +	} + +	function countOthers($address) { +		if (!$address) { +			return false; +		} + +		$userservice = & ServiceFactory :: getServiceInstance('UserService'); +		$sId = $userservice->getCurrentUserId(); + +		if ($userservice->isLoggedOn()) { +			// All public bookmarks, user's own bookmarks and any shared with user +			$privacy = ' AND ((B.bStatus = 0) OR (B.uId = '. $sId .')'; +			$watchnames = $userservice->getWatchNames($sId, true); +			foreach($watchnames as $watchuser) { +				$privacy .= ' OR (U.username = "'. $watchuser .'" AND B.bStatus = 1)'; +			} +			$privacy .= ')'; +		} else { +			// Just public bookmarks +			$privacy = ' AND B.bStatus = 0'; +		} + +		$sql = 'SELECT COUNT(*) FROM '. $userservice->getTableName() .' AS U, '. $GLOBALS['tableprefix'] .'bookmarks AS B WHERE U.'. $userservice->getFieldName('primary') .' = B.uId AND B.bHash = "'. md5($address) .'"'. $privacy; +		if (!($dbresult = & $this->db->sql_query($sql))) { +			message_die(GENERAL_ERROR, 'Could not get vars', '', __LINE__, __FILE__, $sql, $this->db); +		} +		 +		$output = $this->db->sql_fetchfield(0, 0) - 1; +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	function normalize($address) { +		// If bookmark address doesn't contain ":", add "http://" to the start as a default protocol +		if (strpos($address, ':') === false) { +			$address = 'http://'. $address; +		} + +		// Delete final / +		if (substr($address, -1) == '/') { +			$address = substr($address, 0, count($address)-2); +		} + +		return $address; +	} + +	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/src/SemanticScuttle/Service/cacheservice.php b/src/SemanticScuttle/Service/cacheservice.php new file mode 100644 index 0000000..fe66d38 --- /dev/null +++ b/src/SemanticScuttle/Service/cacheservice.php @@ -0,0 +1,38 @@ +<?php +class CacheService { +    var $basedir; +    var $fileextension = '.cache'; + +    function &getInstance() { +        static $instance; +         +        if (!isset($instance)) +            $instance =& new CacheService(); + +        return $instance; +    } + +    function CacheService() { +        $this->basedir = $GLOBALS['dir_cache'];     +    } + +    function Start($hash, $time = 300) { +        $cachefile = $this->basedir .'/'. $hash . $this->fileextension; +        if (file_exists($cachefile) && time() < filemtime($cachefile) + $time) { +            @readfile($cachefile); +            echo "\n<!-- Cached: ". date('r', filemtime($cachefile)) ." -->\n"; +            unset($cachefile); +            exit; +        } +        ob_start("ob_gzhandler"); +    } + +    function End($hash) { +        $cachefile = $this->basedir .'/'. $hash . $this->fileextension;       +        $handle = fopen($cachefile, 'w'); +        fwrite($handle, ob_get_contents()); +        fclose($handle); +        ob_flush(); +    } +} +?>
\ No newline at end of file diff --git a/src/SemanticScuttle/Service/commondescriptionservice.php b/src/SemanticScuttle/Service/commondescriptionservice.php new file mode 100644 index 0000000..86e0c0f --- /dev/null +++ b/src/SemanticScuttle/Service/commondescriptionservice.php @@ -0,0 +1,167 @@ +<?php +class CommonDescriptionService { +	var $db; +	var $tablename; + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new CommonDescriptionService($db); +		return $instance; +	} + +	function CommonDescriptionService(&$db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'commondescription'; +	} + +	function addTagDescription($tag, $desc, $uId, $time) { +		// Check if no modification +		$lastDesc = $this->getLastTagDescription($tag); +		if($lastDesc['cdDescription'] == $desc) { +			return true; +		} + +		// If modification +		$datetime = gmdate('Y-m-d H:i:s', $time); +		$values = array('tag'=>$tag, 'cdDescription'=>$desc, 'uId'=>$uId, 'cdDatetime'=>$datetime); +		$sql = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); + +		if (!($dbresult =& $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not add tag description', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} + +		return true; +	} + +	function getLastTagDescription($tag) { +		$query = "SELECT *"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag='".$tag."'"; +		$query.= " ORDER BY cdDatetime DESC"; + +		if (!($dbresult = & $this->db->sql_query_limit($query, 1, 0))) { +			message_die(GENERAL_ERROR, 'Could not get tag description', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			return $row; +		} else { +			return false; +		} +	} + +	function getAllTagsDescription($tag) { +		$query = "SELECT *"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE tag='".$tag."'"; +		$query.= " ORDER BY cdDatetime DESC"; + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get tag descriptions', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		return $this->db->sql_fetchrowset($dbresult); + +	} + +	function getDescriptionById($cdId) { +		$query = "SELECT *"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE cdId='".$cdId."'"; + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get tag descriptions', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			return $row; +		} else { +			return false; +		} + +	} + +	function addBookmarkDescription($bHash, $title, $desc, $uId, $time) { +		// Check if no modification +		$lastDesc = $this->getLastBookmarkDescription($bHash); +		if($lastDesc['cdTitle'] == $title && $lastDesc['cdDescription'] == $desc) { +			return true; +		} + +		// If modification +		$datetime = gmdate('Y-m-d H:i:s', $time); +		$values = array('bHash'=>$bHash, 'cdTitle'=>$title, 'cdDescription'=>$desc, 'uId'=>$uId, 'cdDatetime'=>$datetime); +		$sql = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); + +		if (!($dbresult =& $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not add bookmark description', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} +		return true; +	} + +	function getLastBookmarkDescription($bHash) { +		$query = "SELECT *"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE bHash='".$bHash."'"; +		$query.= " ORDER BY cdDatetime DESC"; + +		if (!($dbresult = & $this->db->sql_query_limit($query, 1, 0))) { +			message_die(GENERAL_ERROR, 'Could not get bookmark description', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			return $row; +		} else { +			return false; +		} +	} + +	function getAllBookmarksDescription($bHash) { +		$query = "SELECT *"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE bHash='".$bHash."'"; +		$query.= " ORDER BY cdDatetime DESC"; + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get bookmark descriptions', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		return $this->db->sql_fetchrowset($dbresult); + +	} + +	function deleteDescriptionsForUser($uId){ +		$query = 'DELETE FROM '. $this->getTableName() . ' WHERE uId = '. intval($uId); + +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($query))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not delete user descriptions', '', +			__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/src/SemanticScuttle/Service/searchhistoryservice.php b/src/SemanticScuttle/Service/searchhistoryservice.php new file mode 100644 index 0000000..91457e8 --- /dev/null +++ b/src/SemanticScuttle/Service/searchhistoryservice.php @@ -0,0 +1,124 @@ +<?php +class SearchHistoryService { +	var $db; +	var $tablename; +	var $sizeSearchHistory; + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new SearchHistoryService($db); +		return $instance; +	} + +	function SearchHistoryService(& $db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'searchhistory'; +		if(isset($GLOBALS['sizeSearchHistory'])) { +			$this->sizeSearchHistory = $GLOBALS['sizeSearchHistory']; +		} else { +			$this->sizeSearchHistory = 10; +		} +	} + +	function addSearch($terms, $range, $nbResults, $uId=0) { +		if(strlen($terms) == 0) { +			return false; +		} +		$datetime = gmdate('Y-m-d H:i:s', time()); + +		//Insert values +		$values = array('shTerms'=>$terms, 'shRange'=>$range, 'shDatetime'=>$datetime, 'shNbResults'=>$nbResults, 'uId'=>$uId); +		$sql = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not insert search history', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} + +		if($this->sizeSearchHistory != -1 && +		$this->countSearches() > $this->sizeSearchHistory) { +			$this->deleteOldestSearch(); +		} +	} + +	function getAllSearches($range = NULL, $uId = NULL, $nb = NULL, $start = NULL, $distinct = false, $withResults = false) { +		$sql = 'SELECT DISTINCT(shTerms), shId, shRange, shNbResults, shDatetime, uId'; +		$sql.= ' FROM '. $this->getTableName(); +		$sql.= ' WHERE 1=1'; +		if($range != NULL) { +			$sql.= ' AND shRange = "'.$range.'"'; +		} else { +			$sql.= ' AND shRange = "all"'; +		} +		if($uId != NULL) { +			$sql.= ' AND uId = '.$uId; +		} +		if($withResults = true) { +			$sql.= ' AND shNbResults > 0'; +		} +		if($distinct) { +			$sql.= ' GROUP BY shTerms'; +		} +		$sql.= ' ORDER BY shId DESC'; + +		if (!($dbresult = & $this->db->sql_query_limit($sql, $nb, $start))) { +			message_die(GENERAL_ERROR, 'Could not get searches', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} + +		$searches = array(); +		while ($row = & $this->db->sql_fetchrow($dbresult)) { +			$searches[] = $row; +		} +		$this->db->sql_freeresult($dbresult); +		return $searches; +	} + +	function countSearches() { +		$sql = 'SELECT COUNT(*) AS `total` FROM '. $this->getTableName(); +		if (!($dbresult = & $this->db->sql_query($sql)) || (!($row = & $this->db->sql_fetchrow($dbresult)))) { +			message_die(GENERAL_ERROR, 'Could not get total searches', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} +		$this->db->sql_freeresult($dbresult); +		return $row['total']; +	} + +	/* This function allows to limit the number of saved searches +	 by deleting the oldest one */ +	function deleteOldestSearch() { +		$sql = 'DELETE FROM '.$this->getTableName(); +		$sql.= ' ORDER BY shId ASC LIMIT 1';  // warning: here the limit is important + +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not delete bookmarks', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +	} + +	function deleteSearchHistoryForUser($uId) { +		$query = 'DELETE FROM '. $this->getTableName() .' WHERE uId = '.		intval($uId); + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not delete search history', '', +			__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/src/SemanticScuttle/Service/servicefactory.php b/src/SemanticScuttle/Service/servicefactory.php new file mode 100644 index 0000000..b5215e3 --- /dev/null +++ b/src/SemanticScuttle/Service/servicefactory.php @@ -0,0 +1,38 @@ +<?php +/* Connect to the database and build services */ + +class ServiceFactory { +	function ServiceFactory(&$db, $serviceoverrules = array()) { +	} + +	function &getServiceInstance($name, $servicedir = NULL) { +		global $dbhost, $dbuser, $dbpass, $dbname, $dbport, $dbpersist, $dbtype; +		static $instances = array(); +		static $db; +		if (!isset($db)) { +			require_once(dirname(__FILE__) .'/../includes/db/'. $dbtype .'.php'); +			$db = new sql_db(); +			$db->sql_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, $dbpersist); +			if(!$db->db_connect_id) { +				message_die(CRITICAL_ERROR, "Could not connect to the database", $db); +			} +			$db->sql_query("SET NAMES UTF8");  +		}		 +		 +		if (!isset($instances[$name])) { +			if (isset($serviceoverrules[$name])) { +				$name = $serviceoverrules[$name]; +			} +			if (!class_exists($name)) { +				if (!isset($servicedir)) { +					$servicedir = dirname(__FILE__) .'/'; +				} +								 +				require_once($servicedir . strtolower($name) . '.php'); +			} +			$instances[$name] = call_user_func(array($name, 'getInstance'), $db); +		} +		return $instances[$name]; +	} +} +?> diff --git a/src/SemanticScuttle/Service/tag2tagservice.php b/src/SemanticScuttle/Service/tag2tagservice.php new file mode 100644 index 0000000..956fd49 --- /dev/null +++ b/src/SemanticScuttle/Service/tag2tagservice.php @@ -0,0 +1,377 @@ +<?php +class Tag2TagService { +	var $db; +	var $tablename; + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new Tag2TagService($db); +		return $instance; +	} + +	function Tag2TagService(&$db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'tags2tags'; +	} + +	function addLinkedTags($tag1, $tag2, $relationType, $uId) { +		$tagservice =& ServiceFactory::getServiceInstance('TagService'); +		$tag1 = $tagservice->normalize($tag1); +		$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); +		if (!($dbresult =& $this->db->sql_query($query))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not attach tag to tag', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +		$this->db->sql_transaction('commit'); + +		// Update stats and cache +		$this->update($tag1, $tag2, $relationType, $uId); + +		return true; +	} + +	// Return linked tags just for admin users +	function getAdminLinkedTags($tag, $relationType, $inverseRelation = false, $stopList = array()) { +		// look for admin ids +		$userservice = & ServiceFactory :: getServiceInstance('UserService'); +		$adminIds = $userservice->getAdminIds(); +		 +		//ask for their linked tags +		return $this->getLinkedTags($tag, $relationType, $adminIds, $inverseRelation, $stopList); +	} +	 +	// Return the target linked tags. If inverseRelation is true, return the source linked tags. +	function getLinkedTags($tag, $relationType, $uId = null, $inverseRelation = false, $stopList = array()) { +		// Set up the SQL query. +		if($inverseRelation) { +			$queriedTag = "tag1"; +			$givenTag = "tag2"; +		} else { +			$queriedTag = "tag2"; +			$givenTag = "tag1"; +		} + +		$query = "SELECT DISTINCT ". $queriedTag ." as 'tag'"; +		$query.= " FROM `". $this->getTableName() ."`"; +		$query.= " WHERE 1=1"; +		if($tag !=null) { +			$query.= " AND ". $givenTag ." = '". $tag ."'"; +		} +		if($relationType) { +			$query.= " AND relationType = '". $relationType ."'"; +		} +		if(is_array($uId)) { +			$query.= " AND ( 1=0 "; //tricks always false			 +			foreach($uId as $u) { +				$query.= " OR uId = '".$u."'"; +			} +			$query.= " ) ";  +		} elseif($uId != null) { +			$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) { +			if(!in_array($row['tag'], $stopList)) { +				$output[] = $row['tag']; +			} +		} + +		//bijective case for '=' +		if($relationType == '=' && $inverseRelation == false) { +			//$stopList[] = $tag; +			$bijectiveOutput = $this->getLinkedTags($tag, $relationType, $uId, true, $stopList); +			$output = array_merge($output, $bijectiveOutput); +			//$output = array_unique($output); // remove duplication +		} + +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	/* +	 * 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 { +			// 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, $stopList); +				$output[] = $linkedTag; +				if(is_array($allLinkedTags)) { +					$output = array_merge($output, $allLinkedTags); +				} else { +					$output[] = $allLinkedTags; +				} +			} + +			// and save in cache +			if($activatedCache == true && $uId>0) { +				$tcs->updateTag($tag1, $relationType, $output, $uId); +			} +				 +			//$output = array_unique($output); // remove duplication +			return $output; + +		} +	} + +	function getOrphewTags($relationType, $uId = 0, $limit = null, $orderBy = null) { +		$query = "SELECT DISTINCT tts.tag1 as tag"; +		$query.= " FROM `". $this->getTableName() ."` tts"; +		if($orderBy != null) { +			$tsts =& ServiceFactory::getServiceInstance('TagStatService'); +			$query.= ", ".$tsts->getTableName() ." tsts"; +		} +		$query.= " WHERE tts.tag1 <> ALL"; +		$query.= " (SELECT DISTINCT tag2 FROM `". $this->getTableName() ."`"; +		$query.= " WHERE relationType = '".$relationType."'"; +		if($uId > 0) { +			$query.= " AND uId = '".$uId."'"; +		} +		$query.= ")"; +		if($uId > 0) { +			$query.= " AND tts.uId = '".$uId."'"; +		} + +		switch($orderBy) { +	  case "nb": +	  	$query.= " AND tts.tag1 = tsts.tag1"; +	  	$query.= " AND tsts.relationType = '".$relationType."'"; +	  	if($uId > 0) { +	  		$query.= " AND tsts.uId = ".$uId; +	  	} +	  	$query.= " ORDER BY tsts.nb DESC"; +	  	break; +	  case "depth": // by nb of descendants +	  	$query.= " AND tts.tag1 = tsts.tag1"; +	  	$query.= " AND tsts.relationType = '".$relationType."'"; +	  	if($uId > 0) { +	  		$query.= " AND tsts.uId = ".$uId; +	  	} +	  	$query.= " ORDER BY tsts.depth DESC"; +	  	break; +	  case "nbupdate": +	  	$query.= " AND tts.tag1 = tsts.tag1"; +	  	$query.= " AND tsts.relationType = '".$relationType."'"; +	  	if($uId > 0) { +	  		$query.= " AND tsts.uId = ".$uId; +	  	} +	  	$query.= " ORDER BY tsts.nbupdate DESC"; +	  	break; +		} + +		if($limit != null) { +			$query.= " LIMIT 0,".$limit; +		} + +		if (! ($dbresult =& $this->db->sql_query($query)) ){ +			message_die(GENERAL_ERROR, 'Could not get linked tags', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +		$output = $this->db->sql_fetchrowset($dbresult); +		$this->db->sql_freeresult($dbresult); +		return $output; +	} + +	function getMenuTags($uId) { +		if(strlen($GLOBALS['menuTag']) < 1) { +			return array(); +		} else { +			// we don't use the getAllLinkedTags function in order to improve performance +			$query = "SELECT tag2 as 'tag', COUNT(tag2) as 'count'"; +			$query.= " FROM `". $this->getTableName() ."`"; +			$query.= " WHERE tag1 = '".$GLOBALS['menuTag']."'"; +			$query.= " AND relationType = '>'"; +			if($uId > 0) { +				$query.= " AND uId = '".$uId."'"; +			} +			$query.= " GROUP BY tag2"; +			$query.= " ORDER BY count DESC"; +			$query.= " LIMIT 0, ".$GLOBALS['maxSizeMenuBlock']; + +			if (! ($dbresult =& $this->db->sql_query($query)) ){ +				message_die(GENERAL_ERROR, 'Could not get linked tags', '', __LINE__, __FILE__, $query, $this->db); +				return false; +			} +			$output = $this->db->sql_fetchrowset($dbresult); +			$this->db->sql_freeresult($dbresult); +			return $output; +		} +	} + + +	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; +	} + +	function getLinks($uId) { +		$query = "SELECT tag1, tag2, relationType, uId FROM `". $this->getTableName() ."`"; +		$query.= " WHERE 1=1"; +		if($uId > 0) { +			$query.= " AND uId = '".$uId."'"; +		} + +		return $this->db->sql_fetchrowset($this->db->sql_query($query)); +	} + +	function removeLinkedTags($tag1, $tag2, $relationType, $uId) { +		if(($tag1 != '' && $tag1 == $tag2) || +		($relationType != ">" && $relationType != "=" && $relationType != "") || +		($tag1 == '' && $tag2 == '')) { +			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.= strlen($relationType)>0 ? ' AND relationType = "'. $relationType .'"' : ''; +		$query.= strlen($uId)>0 ? ' AND uId = "'. $uId .'"' : ''; + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not remove tag relation', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + + +		// Update stats and cache +		$this->update($tag1, $tag2, $relationType, $uId); +		 +		$this->db->sql_freeresult($dbresult); +		return true; +	} +	 +	function removeLinkedTagsForUser($uId) { +		$query = 'DELETE FROM '. $this->getTableName(); +		$query.= ' WHERE uId = "'. $uId .'"'; + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not remove tag relation', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + + +		// Update stats and cache +		$this->update('', '', '', $uId); +		 +		$this->db->sql_freeresult($dbresult); +		return true; +	}	 + +	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.'"'; +		$query.= ' AND uId="'.$uId.'"'; +		$this->db->sql_query($query); + +		$query = 'UPDATE `'. $this->getTableName() .'`'; +		$query.= ' SET tag2="'.$newName.'"'; +		$query.= ' WHERE tag2="'.$oldName.'"'; +		$query.= ' AND uId="'.$uId.'"'; +		$this->db->sql_query($query); + + +		// 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); + +		$tsts =& ServiceFactory::getServiceInstance('TagStatService'); +		$tsts->deleteAll(); +	} + +	// Properties +	function getTableName()       { return $this->tablename; } +	function setTableName($value) { $this->tablename = $value; } +} +?> diff --git a/src/SemanticScuttle/Service/tagcacheservice.php b/src/SemanticScuttle/Service/tagcacheservice.php new file mode 100644 index 0000000..ed2eefc --- /dev/null +++ b/src/SemanticScuttle/Service/tagcacheservice.php @@ -0,0 +1,349 @@ +<?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']; +		} + +		$this->db->sql_freeresult($dbresult); +		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); +		$this->db->sql_freeresult($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']; +		} +		 +		$this->db->sql_freeresult($dbresult); +		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/src/SemanticScuttle/Service/tagservice.php b/src/SemanticScuttle/Service/tagservice.php new file mode 100644 index 0000000..fc44a99 --- /dev/null +++ b/src/SemanticScuttle/Service/tagservice.php @@ -0,0 +1,123 @@ +<?php +class TagService { +	var $db; +	var $tablename; + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new TagService($db); +		return $instance; +	} + +	function TagService(&$db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'tags'; +	} + +	function getDescription($tag, $uId) { +		$query = 'SELECT tag, uId, tDescription'; +		$query.= ' FROM '.$this->getTableName(); +		$query.= ' WHERE tag = "'.$tag.'"'; +		$query.= ' AND uId = "'.$uId.'"'; + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get tag description', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			return $row; +		} else { +			return array('tDescription'=>''); +		} +	} +	 +	function existsDescription($tag, $uId) { +			$query = 'SELECT tag, uId, tDescription'; +		$query.= ' FROM '.$this->getTableName(); +		$query.= ' WHERE tag = "'.$tag.'"'; +		$query.= ' AND uId = "'.$uId.'"'; + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get tag description', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			return true; +		} else { +			return false; +		} +	} + +	function getAllDescriptions($tag) { +		$query = 'SELECT tag, uId, tDescription'; +		$query.= ' FROM '.$this->getTableName(); +		$query.= ' WHERE tag = "'.$tag.'"'; + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get tag description', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		return $this->db->sql_fetchrowset($dbresult); +	} + +	function updateDescription($tag, $uId, $desc) { +		if($this->existsDescription($tag, $uId)) { +			$query = 'UPDATE '.$this->getTableName(); +			$query.= ' SET tDescription="'.$this->db->sql_escape($desc).'"'; +			$query.= ' WHERE tag="'.$tag.'" AND uId="'.$uId.'"'; +		} else { +			$values = array('tag'=>$tag, 'uId'=>$uId, 'tDescription'=>$desc); +			$query = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); +		} + +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($query))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not delete bookmarks', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} +		$this->db->sql_transaction('commit'); +		return true; +	} + +	function renameTag($uId, $oldName, $newName) { +		$newname = $this->normalize($newname); +		 +		$query = 'UPDATE `'. $this->getTableName() .'`'; +		$query.= ' SET tag="'.$newName.'"'; +		$query.= ' WHERE tag="'.$oldName.'"'; +		$query.= ' AND uId="'.$uId.'"'; +		$this->db->sql_query($query); +		return true; +	} +	 +	/* normalize the input tags which could be a string or an array*/ +	function normalize($tags) { +		//clean tags from strange characters +		$tags = str_replace(array('"', '\'', '/'), "_", $tags); +		 +		//normalize +		if(!is_array($tags)) { +			$tags = strtolower(trim($tags)); +		} else { +			for($i=0; $i<count($tags); $i++) { +				$tags[$i] = strtolower(trim($tags[$i]));  +			} +		} +		return $tags; +	} + +	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/src/SemanticScuttle/Service/tagstatservice.php b/src/SemanticScuttle/Service/tagstatservice.php new file mode 100644 index 0000000..9d3ca5d --- /dev/null +++ b/src/SemanticScuttle/Service/tagstatservice.php @@ -0,0 +1,193 @@ +<?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']; +		} +	} + +	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; +		} + +		$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'); + +		$query = "SELECT tag1, uId FROM `". $tts->getTableName() ."`"; +		$query.= " WHERE relationType = '>'"; + +		//die($query); + +		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']); +		} +	} + +	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 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); +	} + +	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); +	} + +	function deleteTagStatForUser($uId) { +		$query = 'DELETE FROM '. $this->getTableName() .' WHERE uId = '.		intval($uId); + +		if (!($dbresult = & $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not delete tag stats', '', __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/src/SemanticScuttle/Service/templateservice.php b/src/SemanticScuttle/Service/templateservice.php new file mode 100644 index 0000000..05e494c --- /dev/null +++ b/src/SemanticScuttle/Service/templateservice.php @@ -0,0 +1,46 @@ +<?php +class TemplateService { +	var $basedir; + +	function &getInstance() { +		static $instance; +		if (!isset($instance)) +		$instance =& new TemplateService(); +		return $instance; +	} + +	function TemplateService() { +		$this->basedir = $GLOBALS['TEMPLATES_DIR']; +	} + +	function loadTemplate($template, $vars = NULL) { +		if (substr($template, -4) != '.php') +		$template .= '.php'; +		$tpl =& new Template($this->basedir .'/'. $template, $vars, $this); +		$tpl->parse(); +		return $tpl; +	} +} + +class Template { +	var $vars = array(); +	var $file = ''; +	var $templateservice; + +	function Template($file, $vars = NULL, &$templateservice) { +		$this->vars = $vars; +		$this->file = $file; +		$this->templateservice = $templateservice; +	} + +	function parse() { +		if (isset($this->vars)) +		extract($this->vars); +		include($this->file); +	} + +	function includeTemplate($name) { +		return $this->templateservice->loadTemplate($name, $this->vars); +	} +} +?>
\ No newline at end of file diff --git a/src/SemanticScuttle/Service/userservice.php b/src/SemanticScuttle/Service/userservice.php new file mode 100644 index 0000000..407632b --- /dev/null +++ b/src/SemanticScuttle/Service/userservice.php @@ -0,0 +1,665 @@ +<?php +class UserService { +	var $db; +	var $fields = array( +        'primary'   =>  'uId', +        'username'  =>  'username', +        'password'  =>  'password'); +	var $profileurl; +	var $tablename; +	var $sessionkey; +	var $cookiekey; +	var $cookietime = 1209600; // 2 weeks + +	function &getInstance(&$db) { +		static $instance; +		if (!isset($instance)) +		$instance =& new UserService($db); +		return $instance; +	} + +	function UserService(& $db) { +		$this->db =& $db; +		$this->tablename = $GLOBALS['tableprefix'] .'users'; +		$this->sessionkey = INSTALLATION_ID.'-currentuserid'; +		$this->cookiekey = INSTALLATION_ID.'-login'; +		$this->profileurl = createURL('profile', '%2$s'); +		$this->updateSessionStability(); +	} + +	function _checkdns($host) { +		if (function_exists('checkdnsrr')) { +			return checkdnsrr($host); +		} else { +			return $this->_checkdnsrr($host); +		} +	} + +	function _checkdnsrr($host, $type = "MX") { +		if(!empty($host)) { +			@exec("nslookup -type=$type $host", $output); +			while(list($k, $line) = each($output)) { +				if(eregi("^$host", $line)) { +					return true; +				} +			} +			return false; +		} +	} + +	function _getuser($fieldname, $value) { +		$query = 'SELECT * FROM '. $this->getTableName() .' WHERE '. $fieldname .' = "'. $this->db->sql_escape($value) .'"'; + +		if (! ($dbresult =& $this->db->sql_query($query)) ) { +			message_die(GENERAL_ERROR, 'Could not get user', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$row =& $this->db->sql_fetchrow($dbresult); +		$this->db->sql_freeresult($dbresult); +		if ($row) { +			return $row; +		} else { +			return false; +		} +	} + +	function & getUsers($nb=0) { +		$query = 'SELECT * FROM '. $this->getTableName() .' ORDER BY `uId` DESC'; +		if($nb>0) { +			$query .= ' LIMIT 0, '.$nb; +		} +		if (! ($dbresult =& $this->db->sql_query($query)) ) { +			message_die(GENERAL_ERROR, 'Could not get user', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		while ($row = & $this->db->sql_fetchrow($dbresult)) { +			$users[] = $row; +		} +		$this->db->sql_freeresult($dbresult); +		return $users; +	} + +	function & getObjectUsers($nb=0) { +		$query = 'SELECT * FROM '. $this->getTableName() .' ORDER BY `uId` DESC'; +		if($nb>0) { +			$query .= ' LIMIT 0, '.$nb; +		} +		if (! ($dbresult =& $this->db->sql_query($query)) ) { +			message_die(GENERAL_ERROR, 'Could not get user', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		while ($row = & $this->db->sql_fetchrow($dbresult)) { +			$users[] = new User($row[$this->getFieldName('primary')], $row[$this->getFieldName('username')]); +		} +		$this->db->sql_freeresult($dbresult); +		return $users; +	} + +	function _randompassword() { +		$seed = (integer) md5(microtime()); +		mt_srand($seed); +		$password = mt_rand(1, 99999999); +		$password = substr(md5($password), mt_rand(0, 19), mt_rand(6, 12)); +		return $password; +	} + +	function _updateuser($uId, $fieldname, $value) { +		$updates = array ($fieldname => $value); +		$sql = 'UPDATE '. $this->getTableName() .' SET '. $this->db->sql_build_array('UPDATE', $updates) .' WHERE '. $this->getFieldName('primary') .'='. intval($uId); + +		// Execute the statement. +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not update user', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} +		$this->db->sql_transaction('commit'); + +		// Everything worked out, so return true. +		return true; +	} + +	function getProfileUrl($id, $username) { +		return sprintf($this->profileurl, urlencode($id), urlencode($username)); +	} + +	function getUserByUsername($username) { +		return $this->_getuser($this->getFieldName('username'), $username); +	} + +	function getObjectUserByUsername($username) { +		$user = $this->_getuser($this->getFieldName('username'), $username); +		if($user != false) { +			return new User($user[$this->getFieldName('primary')], $username); +		} else { +			return NULL; +		} +	} + +	/* Takes an numerical "id" or a string "username" +	 and returns the numerical "id" if the user exists else returns NULL */ +	function getIdFromUser($user) { +		if (is_int($user)) { +			return intval($user); +		} else { +			$objectUser = $this->getObjectUserByUsername($user); +			if($objectUser != NULL) { +				return $objectUser->getId(); +			} +		} +		return NULL; +	} + +	function getUser($id) { +		return $this->_getuser($this->getFieldName('primary'), $id); +	} + +	// Momentary useful in order to go to object code +	function getObjectUser($id) { +		$user = $this->_getuser($this->getFieldName('primary'), $id); +		return new User($id, $user[$this->getFieldName('username')]); +	} + +	function isLoggedOn() { +		return ($this->getCurrentUserId() !== false); +	} + +	function &getCurrentUser($refresh = FALSE, $newval = NULL) { +		static $currentuser; +		if (!is_null($newval)) { //internal use only: reset currentuser +			$currentuser = $newval; +		} else if ($refresh || !isset($currentuser)) { +			if ($id = $this->getCurrentUserId()) { +				$currentuser = $this->getUser($id); +			} else { +				$currentuser = null; +			} +		} +		return $currentuser; +	} + +	// Momentary useful in order to go to object code +	function getCurrentObjectUser($refresh = FALSE, $newval = NULL) { +		static $currentObjectUser; +		if (!is_null($newval)) { //internal use only: reset currentuser +			$currentObjectUser = $newval; +		} else if ($refresh || !isset($currentObjectUser)) { +			if ($id = $this->getCurrentUserId()) { +				$currentObjectUser = $this->getObjectUser($id); +			} else { +				$currentObjectUser = null; +			} +		} +		return $currentObjectUser; +	} + +	function existsUserWithUsername($username) { +		if($this->getUserByUsername($username) != '') { +			return true; +		} else { +			return false; +		} +	} + +	function existsUser($id) { +		if($this->getUser($id) != '') { +			return true; +		} else { +			return false; +		} +	} + +	/** +	 * Checks if the given user is an administrator. +	 * Uses global admin_users property containing admin +	 * user names +	 * +	 * @param integer|array $user User ID or user row from DB +	 * +	 * @return boolean True if the user is admin +	 */ +	function isAdmin($user) +	{ +		if (is_numeric($user)) { +			$user = $this->getUser($user); +		} + +		if (isset($GLOBALS['admin_users']) +			&& in_array($user['username'], $GLOBALS['admin_users']) +		) { +			return true; +		} else { +			return false; +		} +	} + +	/* return current user id based on session or cookie */ +	function getCurrentUserId() { +		if (isset($_SESSION[$this->getSessionKey()])) { +			return $_SESSION[$this->getSessionKey()]; +		} else if (isset($_COOKIE[$this->getCookieKey()])) { +			$cook = split(':', $_COOKIE[$this->getCookieKey()]); +			//cookie looks like this: 'id:md5(username+password)' +			$query = 'SELECT * FROM '. $this->getTableName() . +                     ' WHERE MD5(CONCAT('.$this->getFieldName('username') . +                                     ', '.$this->getFieldName('password') . +                     ')) = \''.$this->db->sql_escape($cook[1]).'\' AND '. +			$this->getFieldName('primary'). ' = '. $this->db->sql_escape($cook[0]); + +			if (! ($dbresult =& $this->db->sql_query($query)) ) { +				message_die(GENERAL_ERROR, 'Could not get user', '', __LINE__, __FILE__, $query, $this->db); +				return false; +			} + +			if ($row = $this->db->sql_fetchrow($dbresult)) { +				$_SESSION[$this->getSessionKey()] = $row[$this->getFieldName('primary')]; +				$this->db->sql_freeresult($dbresult); +				return $_SESSION[$this->getSessionKey()]; +			} +		} +		return false; +	} + +	function login($username, $password, $remember = FALSE) { +		$password = $this->sanitisePassword($password); +		$query = 'SELECT '. $this->getFieldName('primary') .' FROM '. $this->getTableName() .' WHERE '. $this->getFieldName('username') .' = "'. $this->db->sql_escape($username) .'" AND '. $this->getFieldName('password') .' = "'. $this->db->sql_escape($password) .'"'; + +		if (! ($dbresult =& $this->db->sql_query($query)) ) { +			message_die(GENERAL_ERROR, 'Could not get user', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		if ($row =& $this->db->sql_fetchrow($dbresult)) { +			$id = $_SESSION[$this->getSessionKey()] = $row[$this->getFieldName('primary')]; +			if ($remember) { +				$cookie = $id .':'. md5($username.$password); +				setcookie($this->cookiekey, $cookie, time() + $this->cookietime, '/'); +			} +			$this->db->sql_freeresult($dbresult); +			return true; +		} else { +			return false; +		} +	} + +	function logout() { +		@setcookie($this->getCookiekey(), '', time() - 1, '/'); +		unset($_COOKIE[$this->getCookiekey()]); +		session_unset(); +		$this->getCurrentUser(TRUE, false); +	} + +	function getWatchlist($uId) { +		// Gets the list of user IDs being watched by the given user. +		$query = 'SELECT watched FROM '. $GLOBALS['tableprefix'] .'watched WHERE uId = '. intval($uId); + +		if (! ($dbresult =& $this->db->sql_query($query)) ) { +			message_die(GENERAL_ERROR, 'Could not get watchlist', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$arrWatch = array(); +		if ($this->db->sql_numrows($dbresult) == 0) { +			$this->db->sql_freeresult($dbresult); +			return $arrWatch; +		} +		while ($row =& $this->db->sql_fetchrow($dbresult)) { +			$arrWatch[] = $row['watched']; +		} +		$this->db->sql_freeresult($dbresult); +		return $arrWatch; +	} + +	function getWatchNames($uId, $watchedby = false) { +		// Gets the list of user names being watched by the given user. +		// - If $watchedby is false get the list of users that $uId watches +		// - If $watchedby is true get the list of users that watch $uId +		if ($watchedby) { +			$table1 = 'b'; +			$table2 = 'a'; +		} else { +			$table1 = 'a'; +			$table2 = 'b'; +		} +		$query = 'SELECT '. $table1 .'.'. $this->getFieldName('username') .' FROM '. $GLOBALS['tableprefix'] .'watched AS W, '. $this->getTableName() .' AS a, '. $this->getTableName() .' AS b WHERE W.watched = a.'. $this->getFieldName('primary') .' AND W.uId = b.'. $this->getFieldName('primary') .' AND '. $table2 .'.'. $this->getFieldName('primary') .' = '. intval($uId) .' ORDER BY '. $table1 .'.'. $this->getFieldName('username'); + +		if (!($dbresult =& $this->db->sql_query($query))) { +			message_die(GENERAL_ERROR, 'Could not get watchlist', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$arrWatch = array(); +		if ($this->db->sql_numrows($dbresult) == 0) { +			$this->db->sql_freeresult($dbresult); +			return $arrWatch; +		} +		while ($row =& $this->db->sql_fetchrow($dbresult)) { +			$arrWatch[] = $row[$this->getFieldName('username')]; +		} +		$this->db->sql_freeresult($dbresult); +		return $arrWatch; +	} + +	function getWatchStatus($watcheduser, $currentuser) { +		// Returns true if the current user is watching the given user, and false otherwise. +		$query = 'SELECT watched FROM '. $GLOBALS['tableprefix'] .'watched AS W INNER JOIN '. $this->getTableName() .' AS U ON U.'. $this->getFieldName('primary') .' = W.watched WHERE U.'. $this->getFieldName('primary') .' = '. intval($watcheduser) .' AND W.uId = '. intval($currentuser); + +		if (! ($dbresult =& $this->db->sql_query($query)) ) { +			message_die(GENERAL_ERROR, 'Could not get watchstatus', '', __LINE__, __FILE__, $query, $this->db); +			return false; +		} + +		$arrWatch = array(); +		if ($this->db->sql_numrows($dbresult) == 0) +		return false; +		else +		return true; +	} + +	function setWatchStatus($subjectUserID) { +		if (!is_numeric($subjectUserID)) +		return false; + +		$currentUserID = $this->getCurrentUserId(); +		$watched = $this->getWatchStatus($subjectUserID, $currentUserID); + +		if ($watched) { +			$sql = 'DELETE FROM '. $GLOBALS['tableprefix'] .'watched WHERE uId = '. intval($currentUserID) .' AND watched = '. intval($subjectUserID); +			if (!($dbresult =& $this->db->sql_query($sql))) { +				$this->db->sql_transaction('rollback'); +				message_die(GENERAL_ERROR, 'Could not add user to watch list', '', __LINE__, __FILE__, $sql, $this->db); +				return false; +			} +		} else { +			$values = array( +                'uId' => intval($currentUserID), +                'watched' => intval($subjectUserID) +			); +			$sql = 'INSERT INTO '. $GLOBALS['tableprefix'] .'watched '. $this->db->sql_build_array('INSERT', $values); +			if (!($dbresult =& $this->db->sql_query($sql))) { +				$this->db->sql_transaction('rollback'); +				message_die(GENERAL_ERROR, 'Could not add user to watch list', '', __LINE__, __FILE__, $sql, $this->db); +				return false; +			} +		} + +		$this->db->sql_transaction('commit'); +		return true; +	} + +	function addUser($username, $password, $email) { +		// Set up the SQL UPDATE statement. +		$datetime = gmdate('Y-m-d H:i:s', time()); +		$password = $this->sanitisePassword($password); +		$values = array('username' => $username, 'password' => $password, 'email' => $email, 'uDatetime' => $datetime, 'uModified' => $datetime); +		$sql = 'INSERT INTO '. $this->getTableName() .' '. $this->db->sql_build_array('INSERT', $values); + +		// Execute the statement. +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not insert user', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} +		$this->db->sql_transaction('commit'); + +		// Everything worked out, so return true. +		return true; +	} + +	function updateUser($uId, $password, $name, $email, $homepage, $uContent) { +		if (!is_numeric($uId)) +		return false; + +		// Set up the SQL UPDATE statement. +		$moddatetime = gmdate('Y-m-d H:i:s', time()); +		if ($password == '') +		$updates = array ('uModified' => $moddatetime, 'name' => $name, 'email' => $email, 'homepage' => $homepage, 'uContent' => $uContent); +		else +		$updates = array ('uModified' => $moddatetime, 'password' => $this->sanitisePassword($password), 'name' => $name, 'email' => $email, 'homepage' => $homepage, 'uContent' => $uContent); +		$sql = 'UPDATE '. $this->getTableName() .' SET '. $this->db->sql_build_array('UPDATE', $updates) .' WHERE '. $this->getFieldName('primary') .'='. intval($uId); + +		// Execute the statement. +		$this->db->sql_transaction('begin'); +		if (!($dbresult = & $this->db->sql_query($sql))) { +			$this->db->sql_transaction('rollback'); +			message_die(GENERAL_ERROR, 'Could not update user', '', __LINE__, __FILE__, $sql, $this->db); +			return false; +		} +		$this->db->sql_transaction('commit'); + +		// Everything worked out, so return true. +		return true; +	} + +	function getAllUsers ( ) {
 +		$query = 'SELECT * FROM '. $this->getTableName();
 +
 +		if (! ($dbresult =& $this->db->sql_query($query)) ) {
 +			message_die(GENERAL_ERROR, 'Could not get users', '', __LINE__, __FILE__, $query, $this->db);
 +			return false;
 +		}
 +
 +		$rows = array();
 +
 +		while ( $row = $this->db->sql_fetchrow($dbresult) ) {
 +			$rows[] = $row;
 +		}
 +		$this->db->sql_freeresult($dbresult);
 +		return $rows;
 +	} +	 +	// Returns an array with admin uIds +	function getAdminIds() { +		$admins = array(); +		foreach($GLOBALS['admin_users'] as $adminName) { +			if($this->getIdFromUser($adminName) != NULL) +			$admins[] = $this->getIdFromUser($adminName);  +		} +		return $admins; +	}
 +
 +	function deleteUser($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', '', __LINE__, __FILE__, $query, $this->db);
 +			return false;
 +		}
 +
 +		return true;
 +	}
 + + +	function sanitisePassword($password) { +		return sha1(trim($password)); +	} + +	function generatePassword($uId) { +		if (!is_numeric($uId)) +		return false; + +		$password = $this->_randompassword(); + +		if ($this->_updateuser($uId, $this->getFieldName('password'), $this->sanitisePassword($password))) +		return $password; +		else +		return false; +	} + +	function isReserved($username) { +		if (in_array($username, $GLOBALS['reservedusers'])) { +			return true; +		} else { +			return false; +		} +	} + +	function isValidUsername($username) { +		if (strlen($username) < 4) { +			return false; +		}elseif (strlen($username) > 24) { +			// too long usernames are cut by database and may cause bugs when compared +			return false; +		} elseif (preg_match('/(\W)/', $username) > 0) { +			// forbidden non-alphanumeric characters +			return false; +		} +		return true; +	} + + + +	function isValidEmail($email) { +		if (eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,6})$", $email)) { +			list($emailUser, $emailDomain) = split("@", $email); + +			// Check if the email domain has a DNS record +			//if ($this->_checkdns($emailDomain)) { +			return true; +			//} +		} +		return false; +	} + +	/** +	 * Sets a session variable. +	 * Updates it when it is already set. +	 * This is used to detect if cookies work. +	 * +	 * @return void +	 * +	 * @see isSessionStable() +	 */ +	function updateSessionStability() { +		//find out if we have cookies enabled +		if (!isset($_SESSION['sessionStable'])) { +			$_SESSION['sessionStable'] = 0; +		} else { +			$_SESSION['sessionStable'] = 1; +		} +	} + +	/** +    	 * Tells you if the session is fresh or old. +    	 * If the session is fresh, it's the first page +    	 * call with that session id. If the session is old, +    	 * we know that cookies (or session persistance) works +    	 *  +    	 * @return boolean True if the  +    	 * +    	 * @see updateSessionStability() +    	 */ +	function isSessionStable() { +		return $_SESSION['sessionStable'] == 1; +	} + +	// Properties +	function getTableName()       { return $this->tablename; } +	function setTableName($value) { $this->tablename = $value; } + +	function getFieldName($field)         { return $this->fields[$field]; } +	function setFieldName($field, $value) { $this->fields[$field] = $value; } + +	function getSessionKey()       { return $this->sessionkey; } +	function setSessionKey($value) { $this->sessionkey = $value; } + +	function getCookieKey()       { return $this->cookiekey; } +	function setCookieKey($value) { $this->cookiekey = $value; } +} + + +/* Defines a user. Rare fields are filled if required. */ +class User { + +	var $id; +	var $username; +	var $name; +	var $email; +	var $homepage; +	var $content; +	var $datetime; +	var $isAdmin; + +	function User($id, $username) { +		$this->id = $id; +		$this->username = $username; +	} + +	function getId() { +		return $this->id; +	} + +	function getUsername() { +		return $this->username; +	} + +	function getName() { +		// Look for value only if not already set +		if(!isset($this->name)) { +			$userservice =& ServiceFactory::getServiceInstance('UserService'); +			$user = $userservice->getUser($this->id); +			$this->name = $user['name']; +		} +		return $this->name; +	} + +	function getEmail() { +		// Look for value only if not already set +		if(!isset($this->email)) { +			$userservice =& ServiceFactory::getServiceInstance('UserService'); +			$user = $userservice->getUser($this->id); +			$this->email = $user['email']; +		} +		return $this->email; +	} + +	function getHomepage() { +		// Look for value only if not already set +		if(!isset($this->homepage)) { +			$userservice =& ServiceFactory::getServiceInstance('UserService'); +			$user = $userservice->getUser($this->id); +			$this->homepage = $user['homepage']; +		} +		return $this->homepage; +	} + +	function getContent() { +		// Look for value only if not already set +		if(!isset($this->content)) { +			$userservice =& ServiceFactory::getServiceInstance('UserService'); +			$user = $userservice->getUser($this->id); +			$this->content = $user['uContent']; +		} +		return $this->content; +	} + +	function getDatetime() { +		// Look for value only if not already set +		if(!isset($this->content)) { +			$userservice =& ServiceFactory::getServiceInstance('UserService'); +			$user = $userservice->getUser($this->id); +			$this->datetime = $user['uDatetime']; +		} +		return $this->datetime; +	} + +	function isAdmin() { +		// Look for value only if not already set +		if(!isset($this->isAdmin)) { +			$userservice =& ServiceFactory::getServiceInstance('UserService'); +			$this->isAdmin = $userservice->isAdmin($this->id); +		} +		return $this->isAdmin; +	} +	 +	function getNbBookmarks($range = 'public') { +		$bookmarkservice =& ServiceFactory::getServiceInstance('BookmarkService'); +		return $bookmarkservice->countBookmarks($this->getId(), $range); +	} +} +?> | 
