diff options
Diffstat (limited to 'src/SemanticScuttle/Service')
-rw-r--r-- | src/SemanticScuttle/Service/Bookmark.php | 228 | ||||
-rw-r--r-- | src/SemanticScuttle/Service/Bookmark2Tag.php | 75 | ||||
-rw-r--r-- | src/SemanticScuttle/Service/Factory.php | 6 | ||||
-rw-r--r-- | src/SemanticScuttle/Service/User.php | 38 |
4 files changed, 285 insertions, 62 deletions
diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 0ac1855..364b1a0 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -178,8 +178,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService */ public function getBookmarkByAddress($address) { - $hash = md5($address); - return $this->getBookmarkByHash($hash); + return $this->getBookmarkByHash($this->getHash($address)); } @@ -188,10 +187,12 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService * Retrieves a bookmark with the given hash. * DOES NOT RESPECT PRIVACY SETTINGS! * - * @param string $hash URL hash (MD5) + * @param string $hash URL hash * * @return mixed Array with bookmark data or false in case * of an error (i.e. not found). + * + * @see getHash() */ public function getBookmarkByHash($hash) { @@ -201,6 +202,25 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService /** + * Returns the hash value of a given address. + * + * @param string $address URL to hash + * @param boolean $bNormalize If the address shall be normalized before + * being hashed + * + * @return string Hash value + */ + public function getHash($address, $bNormalize = true) + { + if ($bNormalize) { + $address = $this->normalize($address); + } + return md5($address); + } + + + + /** * Retrieves a bookmark that has a given short * name. * @@ -284,15 +304,18 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService } $userservice = SemanticScuttle_Service_Factory::get('User'); - $user = $userservice->getCurrentUser(); + $user = $userservice->getCurrentObjectUser(); + if ($user === null) { + return false; + } //user has to be either admin, or owner if ($GLOBALS['adminsCanModifyBookmarksFromOtherUsers'] - && $userservice->isAdmin($user) + && $userservice->isAdmin($user->username) ) { return true; } else { - return ($bookmark['uId'] == $user['uId']); + return ($bookmark['uId'] == $user->id); } } @@ -309,20 +332,20 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService * @return boolean True when the bookmark with the given URL * exists for the user, false if not. */ - function bookmarkExists($address = false, $uid = null) + public function bookmarkExists($address = false, $uid = null) { if (!$address) { return false; } - $address = $this->normalize($address); - - $crit = array('bHash' => md5($address)); + $crit = array('bHash' => $this->getHash($address)); if (isset ($uid)) { $crit['uId'] = $uid; } - $sql = 'SELECT COUNT(*) as "0" FROM '. $GLOBALS['tableprefix'] .'bookmarks WHERE '. $this->db->sql_build_array('SELECT', $crit); + $sql = 'SELECT COUNT(*) as "0" FROM ' + . $GLOBALS['tableprefix'] . 'bookmarks' + . ' WHERE '. $this->db->sql_build_array('SELECT', $crit); if (!($dbresult = $this->db->sql_query($sql))) { message_die( @@ -342,6 +365,60 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService /** + * Checks if the given addresses exist + * + * @param array $addresses Array of addresses + * @param integer $uid User ID the addresses shall belong to + * + * @return array Array with addresses as keys, true/false for existence + * as value + */ + public function bookmarksExist($addresses, $uid = null) + { + if (count($addresses) == 0) { + return array(); + } + + $hashes = array(); + $sql = '(0'; + foreach ($addresses as $key => $address) { + $hash = $this->getHash($address); + $hashes[$hash] = $address; + $sql .= ' OR bHash = "' + . $this->db->sql_escape($hash) + . '"'; + } + $sql .= ')'; + if ($uid !== null) { + $sql .= ' AND uId = ' . intval($uid); + } + + $sql = 'SELECT bHash, COUNT(*) as "count" FROM ' + . $this->getTableName() + . ' WHERE ' . $sql + . ' GROUP BY bHash'; + + if (!($dbresult = $this->db->sql_query($sql))) { + message_die( + GENERAL_ERROR, 'Could not get bookmark counts', '', + __LINE__, __FILE__, $sql, $this->db + ); + } + + $existence = array_combine( + $addresses, + array_fill(0, count($addresses), false) + ); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $existence[$hashes[$row['bHash']]] = $row['count'] > 0; + } + + return $existence; + } + + + + /** * Adds a bookmark to the database. * * @param string $address Full URL of the bookmark @@ -402,17 +479,17 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService // Set up the SQL insert statement and execute it. $values = array( - 'uId' => intval($sId), - 'bIp' => $ip, - 'bDatetime' => $datetime, - 'bModified' => $datetime, - 'bTitle' => $title, - 'bAddress' => $address, + 'uId' => intval($sId), + 'bIp' => $ip, + 'bDatetime' => $datetime, + 'bModified' => $datetime, + 'bTitle' => $title, + 'bAddress' => $address, 'bDescription' => $description, 'bPrivateNote' => $privateNote, - 'bStatus' => intval($status), - 'bHash' => md5($address), - 'bShort' => $short + 'bStatus' => intval($status), + 'bHash' => $this->getHash($address), + 'bShort' => $short ); $sql = 'INSERT INTO '. $this->getTableName() @@ -522,14 +599,14 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService // Set up the SQL update statement and execute it. $updates = array( - 'bModified' => $moddatetime, - 'bTitle' => $title, - 'bAddress' => $address, + 'bModified' => $moddatetime, + 'bTitle' => $title, + 'bAddress' => $address, 'bDescription' => $description, 'bPrivateNote' => $privateNote, - 'bStatus' => $status, - 'bHash' => md5($address), - 'bShort' => $short + 'bStatus' => $status, + 'bHash' => $this->getHash($address, false), + 'bShort' => $short ); if (!is_null($date)) { @@ -804,10 +881,17 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $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; + $bookmarks = array(); + $bookmarkids = array(); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $bookmarks[] = $row; + $bookmarkids[] = $row['bId']; + } + if (count($bookmarkids)) { + $tags = $b2tservice->getTagsForBookmarks($bookmarkids); + foreach ($bookmarks as &$bookmark) { + $bookmark['tags'] = $tags[$bookmark['bId']]; + } } $this->db->sql_freeresult($dbresult); @@ -889,36 +973,88 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService - function countOthers($address) + /** + * Counts the number of bookmarks that have the same address + * as the given address. + * + * @internal + * We do support fetching counts for multiple addresses at once + * because that allows us to reduce the number of queries + * we need in the web interface when displaying i.e. + * 10 bookmarks - only one SQL query is needed then. + * + * @param string|array $addresses Address/URL to look for, string + * of one address or array with + * multiple ones + * + * @return integer Number of bookmarks minus one that have the address. + * In case $addresses was an array, key-value array + * with key being the address, value said number of + * bookmarks + */ + public function countOthers($addresses) { - if (!$address) { + if (!$addresses) { return false; } + $bArray = is_array($addresses); - $userservice = SemanticScuttle_Service_Factory :: get('User'); - $sId = $userservice->getCurrentUserId(); + $us = SemanticScuttle_Service_Factory::get('User'); + $sId = (int)$us->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)'; + if ($us->isLoggedOn()) { + //All public bookmarks, user's own bookmarks + // and any shared with our user + $privacy = ' AND ((B.bStatus = 0) OR (B.uId = ' . $sId . ')'; + $watchnames = $us->getWatchNames($sId, true); + foreach ($watchnames as $watchuser) { + $privacy .= ' OR (U.username = "' + . $this->db->sql_escape($watchuser) + . '" AND B.bStatus = 1)'; } $privacy .= ')'; } else { - // Just public bookmarks + //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); + $addressesSql = ' AND (0'; + foreach ((array)$addresses as $address) { + $addressesSql .= ' OR B.bHash = "' + . $this->db->sql_escape($this->getHash($address)) + . '"'; + } + $addressesSql .= ')'; + + + $sql = 'SELECT B.bAddress, COUNT(*) as count FROM ' + . $us->getTableName() . ' AS U' + . ', '. $GLOBALS['tableprefix'] . 'bookmarks AS B' + . ' WHERE U.'. $us->getFieldName('primary') .' = B.uId' + . $addressesSql + . $privacy + . ' GROUP BY B.bHash'; + + if (!($dbresult = $this->db->sql_query($sql))) { + message_die( + GENERAL_ERROR, 'Could not get other count', + '', __LINE__, __FILE__, $sql, $this->db + ); } - $output = $this->db->sql_fetchfield(0, 0) - 1; + //be sure we also list urls in our array + // that are not found in the database + $counts = array_combine( + (array)$addresses, + array_fill(0, count((array)$addresses), 0) + ); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $counts[$row['bAddress']] + = $row['count'] > 0 ? $row['count'] - 1 : 0; + } $this->db->sql_freeresult($dbresult); - return $output; + + return $bArray ? $counts : reset($counts); } diff --git a/src/SemanticScuttle/Service/Bookmark2Tag.php b/src/SemanticScuttle/Service/Bookmark2Tag.php index 8e5cb22..4d2c969 100644 --- a/src/SemanticScuttle/Service/Bookmark2Tag.php +++ b/src/SemanticScuttle/Service/Bookmark2Tag.php @@ -266,27 +266,90 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService return true; } - function &getTagsForBookmark($bookmarkid) { + + /** + * Retrieves all tags for a given bookmark except system tags. + * + * @param integer $bookmarkid ID of the bookmark + * + * @return array Array of tags + */ + public function getTagsForBookmark($bookmarkid) + { if (!is_numeric($bookmarkid)) { - message_die(GENERAL_ERROR, 'Could not get tags (invalid bookmarkid)', '', __LINE__, __FILE__, $query); + 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'; + $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); + 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)) { + while ($row = $this->db->sql_fetchrow($dbresult)) { $tags[] = $row['tag']; } $this->db->sql_freeresult($dbresult); return $tags; } + + /** + * Retrieves all tags for an array of bookmark IDs + * + * @param array $bookmarkids Array of bookmark IDs + * + * @return array Array of tag arrays. Key is bookmark ID. + */ + public function getTagsForBookmarks($bookmarkids) + { + if (!is_array($bookmarkids)) { + message_die( + GENERAL_ERROR, 'Could not get tags (invalid bookmarkids)', + '', __LINE__, __FILE__, $query + ); + return false; + } else if (count($bookmarkids) == 0) { + return array(); + } + + $query = 'SELECT tag, bId FROM ' . $this->getTableName() + . ' WHERE bId IN (' . implode(',', $bookmarkids) . ')' + . ' AND LEFT(tag, 7) <> "system:"' + . ' ORDER BY id, bId 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_combine( + $bookmarkids, + array_fill(0, count($bookmarkids), array()) + ); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $tags[$row['bId']][] = $row['tag']; + } + $this->db->sql_freeresult($dbresult); + return $tags; + } + + function &getTags($userid = NULL) { $userservice =SemanticScuttle_Service_Factory::get('User'); $logged_on_user = $userservice->getCurrentUserId(); diff --git a/src/SemanticScuttle/Service/Factory.php b/src/SemanticScuttle/Service/Factory.php index 9b79e6c..d7ff1d4 100644 --- a/src/SemanticScuttle/Service/Factory.php +++ b/src/SemanticScuttle/Service/Factory.php @@ -113,7 +113,7 @@ class SemanticScuttle_Service_Factory protected static function loadDb() { global $dbhost, $dbuser, $dbpass, $dbname, - $dbport, $dbpersist, $dbtype; + $dbport, $dbpersist, $dbtype, $dbneedssetnames; if (self::$db !== null) { return; @@ -130,7 +130,9 @@ class SemanticScuttle_Service_Factory self::$db ); } - $db->sql_query('SET NAMES UTF8'); + + $dbneedssetnames && $db->sql_query('SET NAMES UTF8'); + self::$db = $db; } diff --git a/src/SemanticScuttle/Service/User.php b/src/SemanticScuttle/Service/User.php index cedde92..281c18c 100644 --- a/src/SemanticScuttle/Service/User.php +++ b/src/SemanticScuttle/Service/User.php @@ -76,15 +76,28 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService $this->updateSessionStability(); } - function _getuser($fieldname, $value) { - $query = 'SELECT * FROM '. $this->getTableName() .' WHERE '. $fieldname .' = "'. $this->db->sql_escape($value) .'"'; + /** + * Fetches the desired user row from database, specified by column and value + * + * @param string $fieldname Name of database column to identify user + * @param string $value Value of $fieldname + * + * @return array Database row or boolean false + */ + protected 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); + 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); + $row = $this->db->sql_fetchrow($dbresult); $this->db->sql_freeresult($dbresult); if ($row) { return $row; @@ -305,9 +318,14 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService /** * Checks if the given user is an administrator. * Uses global admin_users property containing admin - * user names + * user names. + * + * Passing the user id makes this function load the user + * from database. For efficiency reasons, try to pass + * the user name or database row. * - * @param integer|array $user User ID or user row from DB + * @param integer|array|string $user User ID or user row from DB + * or user name * * @return boolean True if the user is admin */ @@ -315,10 +333,13 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService { if (is_numeric($user)) { $user = $this->getUser($user); + $user = $user['username']; + } else if (is_array($user)) { + $user = $user['username']; } if (isset($GLOBALS['admin_users']) - && in_array($user['username'], $GLOBALS['admin_users']) + && in_array($user, $GLOBALS['admin_users']) ) { return true; } else { @@ -386,6 +407,7 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService } //reload user object $this->getCurrentUser(true); + $this->getCurrentObjectUser(true); } |