diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 1054360..54a1df6 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -81,7 +81,9 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService /** - * Load a single bookmark and return it + * Load a single bookmark and return it. + * When a user is logged on, the returned array will contain + * keys "hasVoted" and "vote". * * @param integer $bid Bookmark ID * @param boolean $include_tags If tags shall be loaded @@ -97,18 +99,18 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $userservice = SemanticScuttle_Service_Factory::get('User'); - $query_1 = '*'; + $query_1 = 'B.*'; $query_2 = $this->getTableName() . ' as B'; //Voting system //needs to be directly after FROM bookmarks if ($GLOBALS['enableVoting'] && $userservice->isLoggedOn()) { - $currentuser = $userservice->getCurrentUser(); + $cuid = $userservice->getCurrentUserId(); $vs = SemanticScuttle_Service_Factory::get('Vote'); $query_1 .= ', !ISNULL(V.bId) as hasVoted, V.vote as vote'; $query_2 .= ' LEFT JOIN ' . $vs->getTableName() . ' AS V' . ' ON B.bId = V.bId' - . ' AND V.uId = ' . (int)$currentuser['uId']; + . ' AND V.uId = ' . (int)$cuid; } $sql = 'SELECT ' . $query_1 . ' FROM ' @@ -563,12 +565,12 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService //Voting system //needs to be directly after FROM bookmarks if ($GLOBALS['enableVoting'] && $userservice->isLoggedOn()) { - $currentuser = $userservice->getCurrentUser(); - $vs = SemanticScuttle_Service_Factory::get('Vote'); + $cuid = $userservice->getCurrentUserId(); + $vs = SemanticScuttle_Service_Factory::get('Vote'); $query_1 .= ', !ISNULL(V.bId) as hasVoted, V.vote as vote'; $query_2 .= ' LEFT JOIN ' . $vs->getTableName() . ' AS V' . ' ON B.bId = V.bId' - . ' AND V.uId = ' . (int)$currentuser['uId']; + . ' AND V.uId = ' . (int)$cuid; } switch($sortOrder) { diff --git a/src/SemanticScuttle/Service/User.php b/src/SemanticScuttle/Service/User.php index 6a5a7d5..8b72274 100644 --- a/src/SemanticScuttle/Service/User.php +++ b/src/SemanticScuttle/Service/User.php @@ -26,10 +26,23 @@ */ class SemanticScuttle_Service_User extends SemanticScuttle_DbService { + /** + * Currently logged on user from database + * + * @var array + * + * @see getCurrentUserId() + * @see getCurrentUser() + * @see setCurrentUserId() + */ + protected $currentuser = null; + protected $fields = array( 'primary' => 'uId', 'username' => 'username', - 'password' => 'password'); + 'password' => 'password' + ); + protected $profileurl; protected $sessionkey; protected $cookiekey; @@ -202,18 +215,29 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService return ($this->getCurrentUserId() !== false); } - function &getCurrentUser($refresh = FALSE, $newval = NULL) { - static $currentuser; - if (!is_null($newval)) { //internal use only: reset currentuser + /** + * Returns the current user object + * + * @param boolean $refresh Reload the user from database + * based on current user id + * @param mixed $newval New user value (used internally + * as setter method) + * + * @return array User from database + */ + public function getCurrentUser($refresh = false, $newval = null) + { + if (!is_null($newval)) { + //internal use only: reset currentuser $currentuser = $newval; - } else if ($refresh || !isset($currentuser)) { + } else if ($refresh || !isset($this->currentuser)) { if ($id = $this->getCurrentUserId()) { - $currentuser = $this->getUser($id); + $this->currentuser = $this->getUser($id); } else { - $currentuser = null; + $this->currentuser = null; } } - return $currentuser; + return $this->currentuser; } // Momentary useful in order to go to object code @@ -271,10 +295,17 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService } } - /* return current user id based on session or cookie */ - function getCurrentUserId() { + /** + * Return current user id based on session or cookie + * + * @return mixed Integer user id or boolean false when user + * could not be found or is not logged on. + */ + public 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)' @@ -285,12 +316,17 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService $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); + 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->setCurrentUserId( + $row[$this->getFieldName('primary')] + ); $this->db->sql_freeresult($dbresult); return $_SESSION[$this->getSessionKey()]; } @@ -298,6 +334,31 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService return false; } + + + /** + * Set the current user ID (i.e. when logging on) + * + * @internal + * No ID verification is being done. + * + * @param integer $user User ID or null to unset the user + * + * @return void + */ + public function setCurrentUserId($user) + { + if ($user === null) { + unset($_SESSION[$this->getSessionKey()]); + } else { + $_SESSION[$this->getSessionKey()] = (int)$user; + } + //reload user object + $this->getCurrentUser(true); + } + + + 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) .'"'; @@ -617,8 +678,32 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService return $_SESSION['sessionStable'] == 1; } - function getFieldName($field) { return $this->fields[$field]; } - function setFieldName($field, $value) { $this->fields[$field] = $value; } + /** + * Get database column name. + * + * @param string $field Field name like 'primary', 'username' + * and 'password' + * + * @return string Real field name + */ + public function getFieldName($field) + { + return $this->fields[$field]; + } + + /** + * Set field name + * + * @param string $field Field name like 'primary', 'username' + * and 'password' + * @param string $value Real database column name + * + * @return void + */ + public function setFieldName($field, $value) + { + $this->fields[$field] = $value; + } function getSessionKey() { return $this->sessionkey; } function setSessionKey($value) { $this->sessionkey = $value; } diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index 1224dfe..e5cf760 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -182,6 +182,97 @@ class BookmarkTest extends TestBase $this->assertTrue($this->vs->hasVoted($bid2, $uid)); } + + + /** + * Verify that getBookmark() does not include user voting + * data when no user is logged on. + * + * @return void + */ + public function testGetBookmarkUserVotingNoUser() + { + $uid = $this->addUser(); + $bid = $this->addBookmark($uid); + //no user + $this->us->setCurrentUserId(null); + + $bm = $this->bs->getBookmark($bid); + $this->assertArrayNotHasKey('hasVoted', $bm); + $this->assertArrayNotHasKey('vote', $bm); + } + + + + /** + * Verify that getBookmark() automatically includes + * voting data of the currently logged on user, + * even if he did not vote yet. + * + * @return void + */ + public function testGetBookmarkUserVotingWithUserNoVote() + { + $uid = $this->addUser(); + $bid = $this->addBookmark($uid); + //log user in + $this->us->setCurrentUserId($uid); + + $bm = $this->bs->getBookmark($bid); + $this->assertArrayHasKey('hasVoted', $bm); + $this->assertArrayHasKey('vote', $bm); + $this->assertEquals(0, $bm['hasVoted']); + $this->assertEquals(null, $bm['vote']); + } + + + + /** + * Verify that getBookmark() automatically includes + * voting data of the currently logged on user + * when he voted positive. + * + * @return void + */ + public function testGetBookmarkUserVotingWithUserPositiveVote() + { + $uid = $this->addUser(); + $bid = $this->addBookmark($uid); + //log user in + $this->us->setCurrentUserId($uid); + $this->assertTrue($this->vs->vote($bid, $uid, 1)); + + $bm = $this->bs->getBookmark($bid); + $this->assertArrayHasKey('hasVoted', $bm); + $this->assertArrayHasKey('vote', $bm); + $this->assertEquals(1, $bm['hasVoted']); + $this->assertEquals(1, $bm['vote']); + } + + + + /** + * Verify that getBookmark() automatically includes + * voting data of the currently logged on user + * when he voted positive. + * + * @return void + */ + public function testGetBookmarkUserVotingWithUserNegativeVote() + { + $uid = $this->addUser(); + $bid = $this->addBookmark($uid); + //log user in + $this->us->setCurrentUserId($uid); + $this->assertTrue($this->vs->vote($bid, $uid, -1)); + + $bm = $this->bs->getBookmark($bid); + $this->assertArrayHasKey('hasVoted', $bm); + $this->assertArrayHasKey('vote', $bm); + $this->assertEquals(1, $bm['hasVoted']); + $this->assertEquals(-1, $bm['vote']); + } + }