From b3cfacf19243a486a86de70ab0b0c2c23e84eae6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Joshua=20R=C3=BCsweg?= Date: Tue, 7 Aug 2018 20:14:46 +0200 Subject: [PATCH] Refine documentation See #2665 --- .../lib/acp/form/TrophyAddForm.class.php | 2 +- .../files/lib/data/trophy/Trophy.class.php | 2 +- .../TrophyConditionHandler.class.php | 31 ++++++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php b/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php index bef3441182..9831ee2ad9 100644 --- a/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php @@ -120,7 +120,7 @@ class TrophyAddForm extends AbstractAcpForm { public $awardAutomatically = 0; /** - * `1` if the trophy is automatically revoked, if the conditions are not longer fulfilled + * `1` if the trophy should be automatically revoked once the conditions are no longer met. * @var int */ public $revokeAutomatically = 0; diff --git a/wcfsetup/install/files/lib/data/trophy/Trophy.class.php b/wcfsetup/install/files/lib/data/trophy/Trophy.class.php index 5bcde024c4..278f7f8f2f 100644 --- a/wcfsetup/install/files/lib/data/trophy/Trophy.class.php +++ b/wcfsetup/install/files/lib/data/trophy/Trophy.class.php @@ -32,7 +32,7 @@ use wcf\util\StringUtil; * @property-read string $badgeColor the icon badge color * @property-read integer $isDisabled `1` if the trophy is disabled * @property-read integer $awardAutomatically `1` if the trophy is awarded automatically - * @property-read integer $revokeAutomatically `1` if the trophy is automatically revoked, if the conditions are not longer fulfilled + * @property-read integer $revokeAutomatically `1` if the trophy should be automatically revoked once the conditions are no longer met. * @property-read integer $trophyUseHtml `1` if the trophy use a html description * @property-read integer $showOrder position of the trophy in relation to the other trophies at the same location */ diff --git a/wcfsetup/install/files/lib/system/trophy/condition/TrophyConditionHandler.class.php b/wcfsetup/install/files/lib/system/trophy/condition/TrophyConditionHandler.class.php index 4f060da0d0..d8fbe3d7e0 100644 --- a/wcfsetup/install/files/lib/system/trophy/condition/TrophyConditionHandler.class.php +++ b/wcfsetup/install/files/lib/system/trophy/condition/TrophyConditionHandler.class.php @@ -99,7 +99,7 @@ class TrophyConditionHandler extends SingletonFactory { $i = 0; foreach ($trophyList as $trophy) { - $userTrophyIDs = $this->getRevocableUserTrophyIDs($trophy); + $userTrophyIDs = $this->getRevocableUserTrophyIDs($trophy, $maxRevokes - $i); $i += count($userTrophyIDs); @@ -137,27 +137,50 @@ class TrophyConditionHandler extends SingletonFactory { * @param Trophy $trophy * @return integer[] */ - private function getRevocableUserTrophyIDs(Trophy $trophy) { + private function getRevocableUserTrophyIDs(Trophy $trophy, $maxTrophyIDs) { + // Unfortunately, the condition system does not support negated conditions. + // Therefore, we need to build our own SQL query. To get to the conditions + // that must be fulfilled for earning a specific trophy, we first create + // a pseudo DBOList element to pass them to the condition handler. Then we + // extract the condition builder from the object. $pseudoUserList = new UserList(); - $pseudoUserList->sqlConditionJoins .= " LEFT JOIN wcf".WCF_N."_user_option_value user_option_value ON (user_option_value.userID = user_table.userID)"; + // Assign the condition to the pseudo DBOList object $conditions = $trophy->getConditions(); foreach ($conditions as $condition) { $condition->getObjectType()->getProcessor()->addUserCondition($condition, $pseudoUserList); } + // Now we create our own query to find out which users no longer meet the conditions. + // For this we use a UserList object again and transfer basic data from the pseudo object. $userList = new UserList(); - $userList->sqlConditionJoins = $pseudoUserList->sqlConditionJoins; $userList->sqlOrderBy = $pseudoUserList->sqlOrderBy; + $userList->sqlLimit = $maxTrophyIDs; + + // Now we copy the sql joins from the pseudo object to the new one if a condition + // has joined a table. $userList->sqlJoins = $pseudoUserList->sqlJoins; + + // We joining the user_trophy table to receive the userTrophyID, which should be deleted. $userList->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_trophy user_trophy ON (user_table.userID = user_trophy.userID)"; + + // We do not need the complete user object, but only the userTrophyID. + // So that the UserList object can also assign the users (which is used + // as an array index), we also get the userID. $userList->useQualifiedShorthand = false; $userList->sqlSelects = "user_trophy.userTrophyID, user_table.userID"; + + // Now we transfer the old conditions to our new object. To avoid having two WHERE keywords, + // we deactivate it in the pseudo-object. $pseudoUserList->getConditionBuilder()->enableWhereKeyword(false); $userList->getConditionBuilder()->add('NOT('. $pseudoUserList->getConditionBuilder() .')', $pseudoUserList->getConditionBuilder()->getParameters()); + + // In order not to get all users who do not fulfill the conditions (in case of + // doubt there can be many), we filter for users who have received the trophy. $userList->getConditionBuilder()->add('user_table.userID IN (SELECT userID FROM wcf'.WCF_N.'_user_trophy WHERE trophyID IN (?))', [$trophy->trophyID]); $userList->readObjects(); + // We now return an array of userTrophyIDs instead of user objects to remove them directly via DBOAction. return array_map(function($object) { return $object->userTrophyID; }, $userList->getObjects()); -- 2.20.1