/** * Saves the like of an object. * * @param \wcf\data\like\object\ILikeObject $likeable * @param \wcf\data\user\User $user * @param integer $likeValue * @param integer $time * @return array */ public function like(ILikeObject $likeable, User $user, $likeValue, $time = TIME_NOW) { // verify if object is already liked by user $like = Like::getLike($likeable->getObjectType()->objectTypeID, $likeable->getObjectID(), $user->userID); // get like object $likeObject = LikeObject::getLikeObject($likeable->getObjectType()->objectTypeID, $likeable->getObjectID()); // if vote is identically just revert the vote if ($like->likeID && $like->likeValue == $likeValue) { return $this->revertLike($like, $likeable, $likeObject, $user); } try { WCF::getDB()->beginTransaction(); // like data $cumulativeLikes = 0; $newValue = $oldValue = null; $users = array(); // update existing object if ($likeObject->likeObjectID) { $likes = $likeObject->likes; $dislikes = $likeObject->dislikes; $cumulativeLikes = $likeObject->cumulativeLikes; // previous (dis-)like already exists if ($like->likeID) { $oldValue = $like->likeValue; // revert like and replace it with a dislike if ($like->likeValue == Like::LIKE) { $likes--; $dislikes++; $cumulativeLikes -= 2; $newValue = Like::DISLIKE; } else { // revert dislike and replace it with a like $likes++; $dislikes--; $cumulativeLikes += 2; $newValue = Like::LIKE; } } else { if ($likeValue == Like::LIKE) { $likes++; $cumulativeLikes++; $newValue = Like::LIKE; } else { $dislikes++; $cumulativeLikes--; $newValue = Like::DISLIKE; } } // build update date $updateData = array('likes' => $likes, 'dislikes' => $dislikes, 'cumulativeLikes' => $cumulativeLikes); if ($likeValue == 1) { $users = unserialize($likeObject->cachedUsers); if (count($users) < 3) { $users[$user->userID] = array('userID' => $user->userID, 'username' => $user->username); $updateData['cachedUsers'] = serialize($users); } } else { if ($likeValue == -1) { $users = unserialize($likeObject->cachedUsers); if (isset($users[$user->userID])) { unset($users[$user->userID]); $updateData['cachedUsers'] = serialize($users); } } } // update data $likeObjectEditor = new LikeObjectEditor($likeObject); $likeObjectEditor->update($updateData); } else { $cumulativeLikes = $likeValue; $newValue = $likeValue; $users = array(); if ($likeValue == 1) { $users = array($user->userID => array('userID' => $user->userID, 'username' => $user->username)); } // create cache $likeObject = LikeObjectEditor::create(array('objectTypeID' => $likeable->getObjectType()->objectTypeID, 'objectID' => $likeable->getObjectID(), 'objectUserID' => $likeable->getUserID() ?: null, 'likes' => $likeValue == Like::LIKE ? 1 : 0, 'dislikes' => $likeValue == Like::DISLIKE ? 1 : 0, 'cumulativeLikes' => $cumulativeLikes, 'cachedUsers' => serialize($users))); } // update owner's like counter if ($likeable->getUserID()) { if ($like->likeID) { $userEditor = new UserEditor(new User($likeable->getUserID())); $userEditor->updateCounters(array('likesReceived' => $like->likeValue == Like::LIKE ? -1 : 1)); } else { if ($likeValue == Like::LIKE) { $userEditor = new UserEditor(new User($likeable->getUserID())); $userEditor->updateCounters(array('likesReceived' => 1)); } } } if (!$like->likeID) { // save like $like = LikeEditor::create(array('objectID' => $likeable->getObjectID(), 'objectTypeID' => $likeable->getObjectType()->objectTypeID, 'objectUserID' => $likeable->getUserID() ?: null, 'userID' => $user->userID, 'time' => $time, 'likeValue' => $likeValue)); if ($likeValue == Like::LIKE && $likeable->getUserID()) { UserActivityPointHandler::getInstance()->fireEvent('com.woltlab.wcf.like.activityPointEvent.receivedLikes', $like->likeID, $likeable->getUserID()); $likeable->sendNotification($like); } } else { $likeEditor = new LikeEditor($like); $likeEditor->update(array('time' => $time, 'likeValue' => $likeValue)); if ($likeable->getUserID()) { if ($likeValue == Like::DISLIKE) { UserActivityPointHandler::getInstance()->removeEvents('com.woltlab.wcf.like.activityPointEvent.receivedLikes', array($likeable->getUserID() => 1)); } else { UserActivityPointHandler::getInstance()->fireEvent('com.woltlab.wcf.like.activityPointEvent.receivedLikes', $like->likeID, $likeable->getUserID()); $likeable->sendNotification($like); } } } // update object's like counter $likeable->updateLikeCounter($cumulativeLikes); WCF::getDB()->commitTransaction(); } catch (DatabaseException $e) { WCF::getDB()->rollBackTransaction(); } return array('data' => $this->loadLikeStatus($likeObject, $user), 'like' => $like, 'newValue' => $newValue, 'oldValue' => $oldValue, 'users' => $users); }