--- /dev/null
+<?php
+namespace wcf\data\user\trophy;
+use wcf\data\DatabaseObject;
+use wcf\data\trophy\Trophy;
+use wcf\data\trophy\TrophyCache;
+use wcf\data\user\User;
+use wcf\data\user\UserProfile;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
+use wcf\system\event\EventHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Represents a user trophy.
+ *
+ * @author Joshua Ruesweg
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\User\Trophy
+ * @since 3.1
+ *
+ * @property-read integer $userTrophyID unique id of the user trophy
+ * @property-read integer $trophyID trophy id
+ * @property-read integer $userID user id
+ * @property-read integer $time the time when the trophy was rewarded
+ * @property-read string $description the custom trophy description
+ * @property-read string $useCustomDescription `1`, iif the trophy use a custom description
+ */
+class UserTrophy extends DatabaseObject {
+ /**
+ * Returns the trophy for the user trophy.
+ *
+ * @return Trophy
+ */
+ public function getTrophy() {
+ return TrophyCache::getInstance()->getTrophyByID($this->trophyID);
+ }
+
+ /**
+ * Returns the user profile for the user trophy.
+ *
+ * @return UserProfile
+ */
+ public function getUserProfile() {
+ return UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+ }
+
+ /**
+ * Returns the parsed description.
+ *
+ * @return string
+ */
+ public function getDescription() {
+ if (!$this->useCustomDescription) {
+ return $this->getTrophy()->getDescription();
+ }
+
+ $replacements = [
+ '{$username}' => $this->getUserProfile()->username
+ ];
+
+ $parameters = ['replacements' => $replacements];
+
+ EventHandler::getInstance()->fireAction($this, 'getDescription', $parameters);
+
+ $replacements = $parameters['replacements'];
+
+ return nl2br(StringUtil::encodeHTML(strtr($this->description, $replacements)));
+ }
+
+ /**
+ * Returns true, if the given user can see this user trophy.
+ *
+ * @param User $user
+ * @return bool
+ * @throws SystemException
+ */
+ public function canSee(User $user = null) {
+ if ($user === null) {
+ $user = WCF::getUser();
+ }
+
+ if (!$user->userID) {
+ $userProfile = new UserProfile(new User(null, []));
+ } else {
+ $userProfile = UserProfileRuntimeCache::getInstance()->getObject($user->userID);
+ }
+
+ if (!$userProfile->getPermission('user.profile.trophy.canSeeTrophies')) {
+ return false;
+ }
+
+ if ($this->getTrophy()->isDisabled()) {
+ return false;
+ }
+
+ // @TODO check user option canViewTrophies
+ return true;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\user\trophy;
+use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\user\UserAction;
+
+/**
+ * Provides user trophy actions.
+ *
+ * @author Joshua Ruesweg
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\User\Trophy
+ * @since 3.1
+ */
+class UserTrophyAction extends AbstractDatabaseObjectAction {
+ /**
+ * @inheritDoc
+ */
+ protected $permissionsDelete = ['admin.trophy.canAwardTrophy'];
+
+ /**
+ * @inheritDoc
+ */
+ public function create() {
+ $returnValues = parent::create();
+
+ (new UserAction([$returnValues->userID], 'update', [
+ 'counters' => [
+ 'trophyPoints' => 1
+ ]
+ ]))->executeAction();
+
+ return $returnValues;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function delete() {
+ $returnValues = parent::delete();
+
+ $updateUserTrophies = [];
+
+ /** @var $object UserTrophyEditor */
+ foreach ($this->objects as $object) {
+ if (!isset($updateUserTrophies[$object->userID])) $updateUserTrophies[$object->userID] = 0;
+ $updateUserTrophies[$object->userID]--;
+ }
+
+ foreach ($updateUserTrophies as $userID => $count) {
+ (new UserAction([$userID], 'update', [
+ 'counters' => [
+ 'trophies' => $count
+ ]
+ ]))->executeAction();
+ }
+
+ return $returnValues;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\user\trophy;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides database related trophy actions.
+ *
+ * @author Joshua Ruesweg
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\User\Trophy
+ * @since 3.1
+ * @mixin UserTrophy
+ */
+class UserTrophyEditor extends DatabaseObjectEditor {
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = UserTrophy::class;
+}
--- /dev/null
+<?php
+namespace wcf\data\user\trophy;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Provides a user trophy list.
+ *
+ * @author Joshua Ruesweg
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\User\Trophy
+ * @since 3.1
+ *
+ * @method UserTrophy current()
+ * @method UserTrophy[] getObjects()
+ * @method UserTrophy|null search($objectID)
+ * @property UserTrophy[] $objects
+ */
+class UserTrophyList extends DatabaseObjectList {
+ /**
+ * Returns a user trophy list for a certain users.
+ *
+ * @param integer[] $userIDs
+ * @param boolean $includeDisabled
+ * @return UserTrophy[][]
+ */
+ public static function getUserTrophies(array $userIDs, $includeDisabled = false) {
+ if (empty($userIDs)) {
+ throw new \InvalidArgumentException('UserIDs cannot be empty.');
+ }
+
+ $trophyList = new self();
+ $trophyList->getConditionBuilder()->add('user_trophy.userID IN (?)', [$userIDs]);
+
+ if (!$includeDisabled) {
+ if (!empty($trophyList->sqlJoins)) $trophyList->sqlJoins .= ' ';
+ if (!empty($trophyList->sqlConditionJoins)) $trophyList->sqlConditionJoins .= ' ';
+ $trophyList->sqlJoins .= 'LEFT JOIN wcf'. WCF_N . '_trophy trophy ON user_trophy.trophyID = trophy.trophyID';
+ $trophyList->sqlConditionJoins .= 'LEFT JOIN wcf'. WCF_N . '_trophy trophy ON user_trophy.trophyID = trophy.trophyID';
+
+ // trophy category join
+ $trophyList->sqlJoins .= ' LEFT JOIN wcf'. WCF_N . '_category category ON trophy.categoryID = category.categoryID';
+ $trophyList->sqlConditionJoins .= ' LEFT JOIN wcf'. WCF_N . '_category category ON trophy.categoryID = category.categoryID';
+
+ $trophyList->getConditionBuilder()->add('trophy.isDisabled = ?', [0]);
+ $trophyList->getConditionBuilder()->add('category.isDisabled = ?', [0]);
+ }
+
+ $trophyList->readObjects();
+
+ $returnValues = [];
+ foreach ($userIDs as $userID) {
+ $returnValues[$userID] = [];
+ }
+
+ foreach ($trophyList as $trophy) {
+ $returnValues[$trophy->userID][$trophy->getObjectID()] = $trophy;
+ }
+
+ return $returnValues;
+ }
+}
notificationMailToken VARCHAR(20) NOT NULL DEFAULT '',
authData VARCHAR(191) NOT NULL DEFAULT '',
likesReceived MEDIUMINT(7) NOT NULL DEFAULT 0,
+ trophyPoints INT(10) NOT NULL DEFAULT 0,
KEY username (username),
KEY email (email),
KEY registrationData (registrationIpAddress, registrationDate),
KEY activityPoints (activityPoints),
KEY likesReceived (likesReceived),
- KEY authData (authData)
+ KEY authData (authData),
+ KEY trophyPoints (trophyPoints)
);
DROP TABLE IF EXISTS wcf1_user_activity_event;
UNIQUE KEY (userID, ignoreUserID)
);
+DROP TABLE IF EXISTS wcf1_user_trophy;
+CREATE TABLE wcf1_user_trophy(
+ userTrophyID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ trophyID INT(10) NOT NULL,
+ userID INT(10) NOT NULL,
+ time INT(10) NOT NULL DEFAULT 0,
+ description MEDIUMTEXT,
+ useCustomDescription TINYINT(1) NOT NULL DEFAULT 0,
+ KEY(trophyID, time)
+);
+
DROP TABLE IF EXISTS wcf1_user_menu_item;
CREATE TABLE wcf1_user_menu_item (
menuItemID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
ALTER TABLE wcf1_user_to_language ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_to_language ADD FOREIGN KEY (languageID) REFERENCES wcf1_language (languageID) ON DELETE CASCADE;
+ALTER TABLE wcf1_user_trophy ADD FOREIGN KEY (trophyID) REFERENCES wcf1_trophy (trophyID) ON DELETE CASCADE;
+ALTER TABLE wcf1_user_trophy ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
+
ALTER TABLE wcf1_import_mapping ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
ALTER TABLE wcf1_tracked_visit ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;