<?php
namespace wcf\system\user\activity\point;
+use wcf\data\object\type\ObjectType;
+
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\user\activity\point\event\UserActivityPointEventAction;
use wcf\data\user\UserProfileAction;
if ($userID === null) $userID = WCF::getUser()->userID;
if (!$userID) throw new SystemException("Cannot fire user activity point events for guests");
- $objectAction = new UserActivityPointEventAction(array(), 'create', array(
- 'data' => array(
- 'objectTypeID' => $objectTypeObj->objectTypeID,
- 'objectID' => $objectID,
- 'userID' => $userID,
- 'additionalData' => serialize($additionalData)
- )
+ // update user_activity_point
+ $sql = "INSERT INTO wcf".WCF_N."_user_activity_point
+ (userID, objectTypeID, activityPoints, items)
+ VALUES (?, ?, ?, 1)
+ ON DUPLICATE KEY
+ UPDATE activityPoints = activityPoints + VALUES(activityPoints),
+ items = items + 1";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute(array(
+ $userID,
+ $objectType->objectTypeID,
+ $objectType->points
));
- $returnValues = $objectAction->executeAction();
- $event = $returnValues['returnValues'];
- $this->updateUser($userID, $objectType);
+ $sql = "UPDATE wcf".WCF_N."_user
+ SET activityPoints = activityPoints + ?
+ WHERE userID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute(array(
+ $objectType->points,
+ $userID
+ ));
- return $event;
+ // update user ranks
+ $this->updateUserRanks(array($userID));
}
/**
throw new SystemException("Object type '".$objectType."' is not valid for object type definition 'com.woltlab.wcf.user.activityPointEvent'");
}
- $sql = "INSERT INTO wcf".WCF_N."_user_activity_point_event
- (objectTypeID, objectID, userID, additionalData)
- VALUES (?, ?, ?, ?)";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- WCF::getDB()->beginTransaction();
- $userIDs = array();
- foreach ($data as $objectID => $objectData) {
- $statement->execute(array(
- $objectTypeObj->objectTypeID,
- $objectID,
- $objectData['userID'],
- (isset($objectData['additionalData']) ? serialize($objectData['additionalData']) : '')
- ));
+ // update user_activity_point
+ $values = '';
+ $parameters = $userIDs = array();
+ foreach ($data as $event) {
+ if (!empty($values)) $values .= ',';
+ $values .= '(?, ?, ?)';
+ $parameters[] = $event['userID'];
+ $parameters[] = $objectTypeObj->objectTypeID;
+ $parameters[] = $objectTypeObj->points;
- $userIDs[] = $objectData['userID'];
+ $userIDs[] = $event['userID'];
}
- WCF::getDB()->commitTransaction();
+ $sql = "INSERT INTO wcf".WCF_N."_user_activity_point
+ (userID, objectTypeID, activityPoints, items)
+ VALUES ".$values."
+ ON DUPLICATE KEY
+ UPDATE activityPoints = activityPoints + VALUES(activityPoints),
+ items = items + 1";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($parameters);
+
+ // update activity points for given user ids
$userIDs = array_unique($userIDs);
- $this->updateUsers($userIDs, $objectType);
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("userID IN (?)", array($userIDs));
+
+ $sql = "UPDATE wcf".WCF_N."_user user_table
+ SET activityPoints = COALESCE((
+ SELECT SUM(activityPoints) AS activityPoints
+ FROM wcf".WCF_N."_user_activity_point
+ WHERE userID = user_table.userID
+ GROUP BY userID
+ ), 0)
+ ".$conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+
+ // update user ranks
+ $this->updateUserRanks($userIDs);
}
/**
* Removes activity point events.
*
* @param string $objectType
- * @param array<integer> $objectIDs
+ * @param array<integer> $userToItems
*/
- public function removeEvents($objectType, array $objectIDs) {
- if (empty($objectIDs)) return;
+ public function removeEvents($objectType, array $userToItems) {
+ // ignore values for guests
+ if (isset($userToItems[0])) {
+ unset($userToItems[0]);
+ }
+
+ if (empty($userToItems)) return;
// get and validate object type
$objectTypeObj = $this->getObjectTypeByName($objectType);
throw new SystemException("Object type '".$objectType."' is not valid for object type definition 'com.woltlab.wcf.user.activityPointEvent'");
}
- // get user ids
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("objectTypeID = ?", array($objectTypeObj->objectTypeID));
- $conditions->add("objectID IN (?)", array($objectIDs));
- $sql = "SELECT DISTINCT userID
- FROM wcf".WCF_N."_user_activity_point_event
- ".$conditions;
+ // remove activity points
+ $sql = "UPDATE wcf".WCF_N."_user_activity_point
+ SET activityPoints = activityPoints - ?,
+ items = items - ?
+ WHERE objectTypeID = ?
+ AND userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- $userIDs = array();
- while ($row = $statement->fetchArray()) {
- $userIDs[] = $row['userID'];
+ foreach ($userToItems as $userID => $items) {
+ $statement->execute(array(
+ ($items * $objectTypeObj->points),
+ $items,
+ $objectTypeObj->objectTypeID,
+ $userID
+ ));
}
- // delete events
- $sql = "DELETE FROM wcf".WCF_N."_user_activity_point_event
+ // update total activity points per user
+ $userIDs = array_keys($userIDs);
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("userID IN (?)", array($userIDs));
+
+ $sql = "UPDATE wcf".WCF_N."_user user_table
+ SET activityPoints = COALESCE((
+ SELECT SUM(activityPoints) AS activityPoints
+ FROM wcf".WCF_N."_user_activity_point
+ WHERE userID = user_table.userID
+ GROUP BY userID
+ ), 0)
".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
-
- if (!empty($userIDs)) {
- $this->updateUsers($userIDs, $objectType);
- }
}
/**
return null;
}
- /**
- * Updates the caches for the given user.
- *
- * @param integer $userID
- * @param string $objectType
- */
- public function updateUser($userID, $objectType) {
- $objectType = $this->getObjectTypeByName($objectType);
-
- // update user_activity_point
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_user_activity_point
- WHERE userID = ?
- AND objectTypeID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- $userID,
- $objectType->objectTypeID
- ));
- $row = $statement->fetchArray();
-
- // update existing entry
- if ($row['count']) {
- $sql = "UPDATE wcf".WCF_N."_user_activity_point
- SET activityPoints = activityPoints + ?
- WHERE userID = ?
- AND objectTypeID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- $objectType->points,
- $userID,
- $objectType->objectTypeID
- ));
- }
- else {
- // create new entry
- $sql = "INSERT INTO wcf".WCF_N."_user_activity_point
- (userID, objectTypeID, activityPoints)
- VALUES (?, ?, ?)";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- $userID,
- $objectType->objectTypeID,
- $objectType->points
- ));
- }
-
- $sql = "UPDATE wcf".WCF_N."_user
- SET activityPoints = activityPoints + ?
- WHERE userID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- $objectType->points,
- $userID
- ));
-
- // update user ranks
- $this->updateUserRanks(array($userID));
- }
-
- /**
- * Updates activity points for given user ids and object type.
- *
- * @param array<integer> $userIDs
- * @param string $objectType
- */
- public function updateUsers(array $userIDs, $objectType = null) {
- $objectTypes = array();
- if ($objectType === null) {
- $objectTypes = $this->objectTypes;
- }
- else {
- $objectTypeObj = $this->getObjectTypeByName($objectType);
- if ($objectTypeObj === null) {
- throw new SystemException("Object type '".$objectType."' is not valid for object type definition 'com.woltlab.wcf.user.activityPointEvent'");
- }
- $objectTypes[] = $objectTypeObj;
- }
-
- $objectTypeIDs = array();
- foreach ($objectTypes as $objectType) {
- $objectTypeIDs[] = $objectType->objectTypeID;
- }
-
- // remove cached values first
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("userID IN (?)", array($userIDs));
- $conditions->add("objectTypeID IN (?)", array($objectTypeIDs));
- $sql = "DELETE FROM wcf".WCF_N."_user_activity_point
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- // update users for every given object type
- WCF::getDB()->beginTransaction();
- foreach ($objectTypes as $objectType) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("userID IN (?)", array($userIDs));
- $conditions->add("objectTypeID = ?", array($objectType->objectTypeID));
-
- $parameters = $conditions->getParameters();
- array_unshift($parameters, $objectType->points);
-
- $sql = "INSERT INTO wcf".WCF_N."_user_activity_point
- (userID, objectTypeID, activityPoints)
- SELECT userID, objectTypeID, (COUNT(*) * ?) AS activityPoints
- FROM wcf".WCF_N."_user_activity_point_event
- ".$conditions."
- GROUP BY userID, objectTypeID";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($parameters);
- }
- WCF::getDB()->commitTransaction();
-
- // update activity points for given user ids
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("userID IN (?)", array($userIDs));
-
- $sql = "UPDATE wcf".WCF_N."_user user_table
- SET activityPoints = COALESCE((
- SELECT SUM(activityPoints) AS activityPoints
- FROM wcf".WCF_N."_user_activity_point
- WHERE userID = user_table.userID
- GROUP BY userID
- ), 0)
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- // update user ranks
- $this->updateUserRanks($userIDs);
- }
-
/**
* Updates the user ranks for the given users.
*