From: Joshua Rüsweg Date: Tue, 7 Aug 2018 13:12:54 +0000 (+0200) Subject: Add support for revocable trophies X-Git-Tag: 5.2.0_Alpha_1~364^2~102^2~3 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=411ea67f33b3997ca6d732e26c8d67f37ae43a64;p=GitHub%2FWoltLab%2FWCF.git Add support for revocable trophies See #2665 --- diff --git a/wcfsetup/install/files/acp/templates/trophyAdd.tpl b/wcfsetup/install/files/acp/templates/trophyAdd.tpl index c62a82ce1f..64a9b883be 100644 --- a/wcfsetup/install/files/acp/templates/trophyAdd.tpl +++ b/wcfsetup/install/files/acp/templates/trophyAdd.tpl @@ -31,6 +31,13 @@ elBySel('input[name=awardAutomatically]').addEventListener('change', function () { var awardAutomatically = elBySel('input[name=awardAutomatically]').checked; elBySelAll('.conditionSection', null, window[(awardAutomatically ? 'elShow' : 'elHide')]); + + if (awardAutomatically) { + elShow(elById('revokeAutomaticallyDL')); + } + else { + elHide(elById('revokeAutomaticallyDL')); + } }); BadgeHandler.init(); @@ -143,6 +150,13 @@ + +
diff --git a/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php b/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php index 04c1a46ee4..bef3441182 100644 --- a/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/TrophyAddForm.class.php @@ -119,6 +119,12 @@ class TrophyAddForm extends AbstractAcpForm { */ public $awardAutomatically = 0; + /** + * `1` if the trophy is automatically revoked, if the conditions are not longer fulfilled + * @var int + */ + public $revokeAutomatically = 0; + /** * `1` if the trophy contains html in the description * @var int @@ -183,6 +189,7 @@ class TrophyAddForm extends AbstractAcpForm { if (isset($_POST['iconColor'])) $this->iconColor = $_POST['iconColor']; if (isset($_POST['badgeColor'])) $this->badgeColor = $_POST['badgeColor']; if (isset($_POST['awardAutomatically'])) $this->awardAutomatically = 1; + if (isset($_POST['revokeAutomatically']) && $this->awardAutomatically) $this->revokeAutomatically = 1; if (isset($_POST['trophyUseHtml'])) $this->trophyUseHtml = 1; if (isset($_POST['showOrder'])) $this->showOrder = intval($_POST['showOrder']); @@ -295,6 +302,7 @@ class TrophyAddForm extends AbstractAcpForm { 'type' => $this->type, 'isDisabled' => $this->isDisabled, 'awardAutomatically' => $this->awardAutomatically, + 'revokeAutomatically' => $this->revokeAutomatically, 'trophyUseHtml' => $this->trophyUseHtml, 'showOrder' => $this->showOrder ]), @@ -328,7 +336,7 @@ class TrophyAddForm extends AbstractAcpForm { public function reset() { parent::reset(); - $this->isDisabled = $this->awardAutomatically = $this->categoryID = $this->trophyUseHtml = $this->showOrder = 0; + $this->isDisabled = $this->awardAutomatically = $this->categoryID = $this->trophyUseHtml = $this->showOrder = $this->revokeAutomatically = 0; $this->type = Trophy::TYPE_BADGE; $this->iconName = $this->uploadedImageURL = ''; $this->iconColor = 'rgba(255, 255, 255, 1)'; @@ -359,6 +367,7 @@ class TrophyAddForm extends AbstractAcpForm { 'trophyCategories' => TrophyCategoryCache::getInstance()->getCategories(), 'groupedObjectTypes' => $this->conditions, 'awardAutomatically' => $this->awardAutomatically, + 'revokeAutomatically' => $this->revokeAutomatically, 'availableTypes' => $this->availableTypes, 'tmpHash' => $this->tmpHash, 'uploadedImageURL' => $this->uploadedImageURL, diff --git a/wcfsetup/install/files/lib/acp/form/TrophyEditForm.class.php b/wcfsetup/install/files/lib/acp/form/TrophyEditForm.class.php index 69bb1d0e6e..55a456ed5a 100644 --- a/wcfsetup/install/files/lib/acp/form/TrophyEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/TrophyEditForm.class.php @@ -74,6 +74,7 @@ class TrophyEditForm extends TrophyAddForm { $this->iconColor = $this->trophy->iconColor; $this->badgeColor = $this->trophy->badgeColor; $this->awardAutomatically = $this->trophy->awardAutomatically; + $this->revokeAutomatically = $this->trophy->revokeAutomatically; $this->trophyUseHtml = $this->trophy->trophyUseHtml; $this->showOrder = $this->trophy->showOrder; @@ -167,6 +168,7 @@ class TrophyEditForm extends TrophyAddForm { 'type' => $this->type, 'isDisabled' => $this->isDisabled, 'awardAutomatically' => $this->awardAutomatically, + 'revokeAutomatically' => $this->revokeAutomatically, 'trophyUseHtml' => $this->trophyUseHtml, 'showOrder' => $this->showOrder ])]); diff --git a/wcfsetup/install/files/lib/data/trophy/Trophy.class.php b/wcfsetup/install/files/lib/data/trophy/Trophy.class.php index 5d5310fe6b..5bcde024c4 100644 --- a/wcfsetup/install/files/lib/data/trophy/Trophy.class.php +++ b/wcfsetup/install/files/lib/data/trophy/Trophy.class.php @@ -32,7 +32,8 @@ 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 $trophyUseHtml `1`, if the trophy use a html description + * @property-read integer $revokeAutomatically `1` if the trophy is automatically revoked, if the conditions are not longer fulfilled + * @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 */ class Trophy extends DatabaseObject implements ITitledLinkObject, IRouteController { diff --git a/wcfsetup/install/files/lib/data/user/trophy/UserTrophyAction.class.php b/wcfsetup/install/files/lib/data/user/trophy/UserTrophyAction.class.php index ad87909eec..7c4b18b8ee 100644 --- a/wcfsetup/install/files/lib/data/user/trophy/UserTrophyAction.class.php +++ b/wcfsetup/install/files/lib/data/user/trophy/UserTrophyAction.class.php @@ -99,6 +99,10 @@ class UserTrophyAction extends AbstractDatabaseObjectAction { * @inheritDoc */ public function delete() { + if (empty($this->objects)) { + $this->readObjects(); + } + $trophyIDs = $userIDs = []; foreach ($this->getObjects() as $object) { $trophyIDs[] = $object->trophyID; diff --git a/wcfsetup/install/files/lib/system/cronjob/AssignTrophiesCronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/AssignTrophiesCronjob.class.php index 93031400db..27f1495fd1 100644 --- a/wcfsetup/install/files/lib/system/cronjob/AssignTrophiesCronjob.class.php +++ b/wcfsetup/install/files/lib/system/cronjob/AssignTrophiesCronjob.class.php @@ -21,6 +21,7 @@ class AssignTrophiesCronjob extends AbstractCronjob { if (MODULE_TROPHY) { TrophyConditionHandler::getInstance()->assignTrophies(100); + TrophyConditionHandler::getInstance()->revokeTrophies(100); } } } 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 f3237a07f4..ac4dd048aa 100644 --- a/wcfsetup/install/files/lib/system/trophy/condition/TrophyConditionHandler.class.php +++ b/wcfsetup/install/files/lib/system/trophy/condition/TrophyConditionHandler.class.php @@ -85,6 +85,30 @@ class TrophyConditionHandler extends SingletonFactory { } } + /** + * Revoke user trophies which are not longer fulfills the conditions. + * + * @param integer $maxRevokes + */ + public function revokeTrophies($maxRevokes = 500) { + $trophyList = new TrophyList(); + $trophyList->getConditionBuilder()->add('awardAutomatically = ?', [1]); + $trophyList->getConditionBuilder()->add('revokeAutomatically = ?', [1]); + $trophyList->getConditionBuilder()->add('isDisabled = ?', [0]); + $trophyList->readObjects(); + + $i = 0; + foreach ($trophyList as $trophy) { + $userTrophyIDs = $this->getRevocableUserTrophyIDs($trophy); + + $i += count($userTrophyIDs); + + (new UserTrophyAction($userTrophyIDs, 'delete'))->executeAction(); + + if ($i >= $maxRevokes) return; + } + } + /** * Returns the users who fulfill all conditions of the given trophy. * @@ -106,4 +130,35 @@ class TrophyConditionHandler extends SingletonFactory { return $userList->getObjectIDs(); } + + /** + * Returns the userTrophyIDs of the users, which no longer fulfills the trophy conditions. + * + * @param Trophy $trophy + * @return integer[] + */ + private function getRevocableUserTrophyIDs(Trophy $trophy) { + $pseudoUserList = new UserList(); + $pseudoUserList->sqlConditionJoins .= " LEFT JOIN wcf".WCF_N."_user_option_value user_option_value ON (user_option_value.userID = user_table.userID)"; + + $conditions = $trophy->getConditions(); + foreach ($conditions as $condition) { + $condition->getObjectType()->getProcessor()->addUserCondition($condition, $pseudoUserList); + } + + $userList = new UserList(); + $userList->sqlConditionJoins = $pseudoUserList->sqlConditionJoins; + $userList->sqlOrderBy = $pseudoUserList->sqlOrderBy; + $userList->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_trophy user_trophy ON (user_table.userID = user_trophy.userID)"; + $userList->useQualifiedShorthand = false; + $userList->sqlSelects = "user_trophy.userTrophyID, user_table.userID"; + $pseudoUserList->getConditionBuilder()->enableWhereKeyword(false); + $userList->getConditionBuilder()->add('NOT('. $pseudoUserList->getConditionBuilder() .')', $pseudoUserList->getConditionBuilder()->getParameters()); + $userList->getConditionBuilder()->add('user_table.userID IN (SELECT userID FROM wcf'.WCF_N.'_user_trophy WHERE trophyID IN (?))', [$trophy->trophyID]); + $userList->readObjects(); + + return array_map(function($object) { + return $object->userTrophyID; + }, $userList->getObjects()); + } } diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index cd0854353e..b70afd3bb6 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -3857,6 +3857,7 @@ Die E-Mail-Adresse des neuen Benutzers lautet: {@$user->email} + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index a850c5b920..153cd68021 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -3850,6 +3850,7 @@ Open the link below to access the user profile: + diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index 572e29fb26..4f07945112 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -1382,6 +1382,7 @@ CREATE TABLE wcf1_trophy( badgeColor VARCHAR(255), isDisabled TINYINT(1) NOT NULL DEFAULT 0, awardAutomatically TINYINT(1) NOT NULL DEFAULT 0, + revokeAutomatically TINYINT(1) NOT NULL DEFAULT 0, trophyUseHtml TINYINT(1) NOT NULL DEFAULT 0, showOrder INT(10) NOT NULL DEFAULT 0, KEY(categoryID)