diff options
author | Christian Weiske <cweiske@cweiske.de> | 2010-08-12 20:49:35 +0200 |
---|---|---|
committer | Christian Weiske <cweiske@cweiske.de> | 2010-08-12 20:49:35 +0200 |
commit | 0a8dadf87e660e9bf205581f12f7af87bfabf6ca (patch) | |
tree | a1218f869401a1ffff764a58c28a0be674ba5362 /src | |
parent | b25290cef48251a31cb0f693a53677b566c1b1a4 (diff) | |
parent | 31570df64ce6543de407e7b9d751ba9033d930de (diff) | |
download | semanticscuttle-0a8dadf87e660e9bf205581f12f7af87bfabf6ca.tar.gz semanticscuttle-0a8dadf87e660e9bf205581f12f7af87bfabf6ca.tar.bz2 |
Merge branch 'master' into pearpkg
Diffstat (limited to 'src')
-rw-r--r-- | src/SemanticScuttle/Model/User.php | 2 | ||||
-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 | ||||
-rw-r--r-- | src/SemanticScuttle/db/mysqli.php | 2 | ||||
-rw-r--r-- | src/SemanticScuttle/functions.php | 36 | ||||
-rw-r--r-- | src/SemanticScuttle/header.php | 8 |
8 files changed, 325 insertions, 70 deletions
diff --git a/src/SemanticScuttle/Model/User.php b/src/SemanticScuttle/Model/User.php index 03af5c7..ed9f454 100644 --- a/src/SemanticScuttle/Model/User.php +++ b/src/SemanticScuttle/Model/User.php @@ -158,7 +158,7 @@ class SemanticScuttle_Model_User // Look for value only if not already set if(!isset($this->isAdmin)) { $us = SemanticScuttle_Service_Factory::get('User'); - $this->isAdmin = $us->isAdmin($this->id); + $this->isAdmin = $us->isAdmin($this->username); } return $this->isAdmin; } 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); } diff --git a/src/SemanticScuttle/db/mysqli.php b/src/SemanticScuttle/db/mysqli.php index 27814a7..03b36ea 100644 --- a/src/SemanticScuttle/db/mysqli.php +++ b/src/SemanticScuttle/db/mysqli.php @@ -440,7 +440,7 @@ class sql_db echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8869-1"><meta http-equiv="Content-Style-Type" content="text/css"><link rel="stylesheet" href="' . $phpbb_root_path . 'adm/subSilver.css" type="text/css"><style type="text/css">' . "\n"; echo 'th { background-image: url(\'' . $phpbb_root_path . 'adm/images/cellpic3.gif\') }' . "\n"; echo 'td.cat { background-image: url(\'' . $phpbb_root_path . 'adm/images/cellpic1.gif\') }' . "\n"; - echo '</style><title>' . $msg_title . '</title></head><body>'; + echo '</style><title>DB query explanation</title></head><body>'; echo '<table width="100%" cellspacing="0" cellpadding="0" border="0"><tr><td><a href="' . htmlspecialchars(preg_replace('/&explain=([^&]*)/', '', $_SERVER['REQUEST_URI'])) . '"><img src="' . $phpbb_root_path . 'adm/images/header_left.jpg" width="200" height="60" alt="phpBB Logo" title="phpBB Logo" border="0"/></a></td><td width="100%" background="' . $phpbb_root_path . 'adm/images/header_bg.jpg" height="60" align="right" nowrap="nowrap"><span class="maintitle">SQL Report</span> </td></tr></table><br clear="all"/><table width="95%" cellspacing="1" cellpadding="4" border="0" align="center"><tr><td height="40" align="center" valign="middle"><b>Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries} queries" . (($cache_num_queries) ? " + $cache_num_queries " . (($cache_num_queries == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '</b></td></tr><tr><td align="center" nowrap="nowrap">Time spent on MySQL queries: <b>' . round($this->sql_time, 5) . 's</b> | Time spent on PHP: <b>' . round($totaltime - $this->sql_time, 5) . 's</b></td></tr></table><table width="95%" cellspacing="1" cellpadding="4" border="0" align="center"><tr><td>'; echo $sql_report; echo '</td></tr></table><br /></body></html>'; diff --git a/src/SemanticScuttle/functions.php b/src/SemanticScuttle/functions.php index d21a094..84e9c5f 100644 --- a/src/SemanticScuttle/functions.php +++ b/src/SemanticScuttle/functions.php @@ -1,6 +1,19 @@ <?php -/* Define functions used into the application */ - +/** + * Defines some commonly used functions. + * + * SemanticScuttle - your social bookmark manager. + * + * PHP version 5. + * + * @category Bookmarking + * @package SemanticScuttle + * @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net> + * @author Christian Weiske <cweiske@cweiske.de> + * @author Eric Dane <ericdane@users.sourceforge.net> + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ // Converts tags: // - direction = out: convert spaces to underscores; @@ -35,10 +48,23 @@ function filter($data, $type = NULL) { return $data; } -function getPerPageCount($userObject = null) { +/** + * Returns the number of bookmarks that shall be displayed on one page. + * + * @param SemanticScuttle_Model_User $userObject Object of the current user + * + * @return integer Number of bookmarks per page + * + * @uses $defaultPerPage + * @uses $defaultPerPageForAdmins + */ +function getPerPageCount($userObject = null) +{ global $defaultPerPage, $defaultPerPageForAdmins; - - if(isset($defaultPerPageForAdmins) && $userObject != null && $userObject->isAdmin()) { + + if (isset($defaultPerPageForAdmins) + && $userObject != null && $userObject->isAdmin() + ) { return $defaultPerPageForAdmins; } else { return $defaultPerPage; diff --git a/src/SemanticScuttle/header.php b/src/SemanticScuttle/header.php index 12c1f72..ef36e83 100644 --- a/src/SemanticScuttle/header.php +++ b/src/SemanticScuttle/header.php @@ -107,6 +107,12 @@ $tplVars['userservice'] = $userservice; // 6 // Force UTF-8 behaviour for server (cannot be moved into top.inc.php which is not included into every file) if (!defined('UNIT_TEST_MODE')) { - header('Content-Type: text/html; charset=utf-8'); + //API files define that, so we need a way to support both of them + if (!isset($httpContentType)) { + $httpContentType = 'text/html'; + } + if ($httpContentType !== false) { + header('Content-Type: ' . $httpContentType . '; charset=utf-8'); + } } ?> |