Merge branch '5.3' into 5.4
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / user / trophy / UserTrophyAction.class.php
index 8e84d34a089d49fc0dc94de49d0a6ec469741888..d4d89e13bbd33b6d37b745c905f83ff6ba133a08 100644 (file)
@@ -1,7 +1,9 @@
 <?php
+
 namespace wcf\data\user\trophy;
-use wcf\data\user\UserAction;
+
 use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\user\UserAction;
 use wcf\data\user\UserProfile;
 use wcf\data\user\UserProfileAction;
 use wcf\system\cache\runtime\UserProfileRuntimeCache;
@@ -16,205 +18,245 @@ use wcf\system\user\storage\UserStorageHandler;
 use wcf\system\WCF;
 
 /**
- * Provides user trophy actions. 
+ * Provides user trophy actions.
  *
- * @author     Joshua Ruesweg
- * @copyright  2001-2019 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    WoltLabSuite\Core\Data\User\Trophy
- * @since      3.1
+ * @author  Joshua Ruesweg
+ * @copyright   2001-2019 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     UserTrophyEditor[]              getObjects()
- * @method     UserTrophyEditor                getSingleObject()
+ * @method  UserTrophyEditor[]      getObjects()
+ * @method  UserTrophyEditor        getSingleObject()
  */
-class UserTrophyAction extends AbstractDatabaseObjectAction {
-       /**
-        * @inheritDoc
-        */
-       protected $permissionsDelete = ['admin.trophy.canAwardTrophy'];
-       
-       /**
-        * @inheritDoc
-        */
-       protected $allowGuestAccess = ['getGroupedUserTrophyList'];
-       
-       /**
-        * @var UserProfile
-        */
-       public $userProfile;
-       
-       /**
-        * @inheritDoc
-        */
-       public function create() {
-               /** @var UserTrophy $userTrophy */
-               $userTrophy = parent::create();
-               
-               if (!$userTrophy->getTrophy()->isDisabled()) {
-                       $userAction = new UserAction([$userTrophy->userID], 'update', [
-                               'counters' => [
-                                       'trophyPoints' => 1
-                               ]
-                       ]); 
-                       $userAction->executeAction(); 
-                       
-                       // checks if the user still has space to add special trophies
-                       if (count($userTrophy->getUserProfile()->getSpecialTrophies()) < $userTrophy->getUserProfile()->getPermission('user.profile.trophy.maxUserSpecialTrophies')) {
-                               $hasTrophy = false;
-                               foreach (UserTrophyList::getUserTrophies([$userTrophy->getUserProfile()->userID])[$userTrophy->getUserProfile()->userID] as $trophy) {
-                                       if ($trophy->trophyID == $userTrophy->trophyID && $trophy->userTrophyID !== $userTrophy->userTrophyID) {
-                                               $hasTrophy = true; 
-                                               break; 
-                                       }
-                               }
-                               
-                               if (!$hasTrophy) {
-                                       $userProfileAction = new UserProfileAction([$userTrophy->getUserProfile()->getDecoratedObject()], 'updateSpecialTrophies', [
-                                               'trophyIDs' => array_unique(array_merge(array_map(function($trophy) {
-                                                       return $trophy->trophyID;
-                                               }, $userTrophy->getUserProfile()->getSpecialTrophies()), [$userTrophy->trophyID]))
-                                       ]);
-                                       $userProfileAction->executeAction();
-                               }
-                       }
-               }
-               
-               UserActivityEventHandler::getInstance()->fireEvent('com.woltlab.wcf.userTrophy.recentActivityEvent.trophyReceived', $userTrophy->getObjectID(), null, $userTrophy->userID);
-               
-               UserNotificationHandler::getInstance()->fireEvent('received', 'com.woltlab.wcf.userTrophy.notification', new UserTrophyNotificationObject($userTrophy), [
-                       $userTrophy->userID
-               ]);
-               
-               return $userTrophy; 
-       }
-       
-       /**
-        * @inheritDoc
-        */
-       public function validateDelete() {
-               parent::validateDelete();
-               
-               /** @var UserTrophy $object */
-               foreach ($this->objects as $object) {
-                       if ($object->getTrophy()->awardAutomatically) {
-                               throw new PermissionDeniedException(); 
-                       }
-               }
-       }
-       
-       /**
-        * @inheritDoc
-        */
-       public function delete() {
-               if (empty($this->objects)) {
-                       $this->readObjects();
-               }
-               
-               $trophyIDs = $userIDs = []; 
-               foreach ($this->getObjects() as $object) {
-                       $trophyIDs[] = $object->trophyID; 
-                       $userIDs[] = $object->userID; 
-               }
-               
-               $returnValues = parent::delete();
-               
-               if (!empty($this->objects)) {
-                       // update user special trophies trophies
-                       $userTrophies = UserTrophyList::getUserTrophies($userIDs);
-                       
-                       foreach ($userTrophies as $userID => $trophies) {
-                               $userTrophyIDs = [];
-                               foreach ($trophies as $trophy) {
-                                       $userTrophyIDs[] = $trophy->trophyID;
-                               }
-                               
-                               $conditionBuilder = new PreparedStatementConditionBuilder();
-                               if (!empty($userTrophyIDs)) $conditionBuilder->add('trophyID NOT IN (?)', [array_unique($userTrophyIDs)]);
-                               $conditionBuilder->add('userID = ?', [$userID]);
-                               
-                               $sql = "DELETE FROM wcf". WCF_N ."_user_special_trophy ". $conditionBuilder;
-                               $statement = WCF::getDB()->prepareStatement($sql);
-                               $statement->execute($conditionBuilder->getParameters());
-                               
-                               UserStorageHandler::getInstance()->reset([$userID], 'specialTrophies');
-                       }
-                       
-                       $updateUserTrophies = [];
-                       foreach ($this->getObjects() as $object) {
-                               if (!$object->getTrophy()->isDisabled()) {
-                                       if (!isset($updateUserTrophies[$object->userID])) $updateUserTrophies[$object->userID] = 0;
-                                       $updateUserTrophies[$object->userID]--;
-                               }
-                       }
-                       
-                       foreach ($updateUserTrophies as $userID => $count) {
-                               $userAction = new UserAction([$userID], 'update', [
-                                       'counters' => [
-                                               'trophyPoints' => $count
-                                       ]
-                               ]);
-                               $userAction->executeAction();
-                       }
-               }
-               
-               return $returnValues;
-       }
-       
-       /**
-        * Validates the getGroupedUserTrophyList method. 
-        */
-       public function validateGetGroupedUserTrophyList() {
-               if (!MODULE_TROPHY) {
-                       throw new IllegalLinkException();
-               }
-               
-               WCF::getSession()->checkPermissions(['user.profile.trophy.canSeeTrophies']);
-               
-               $this->readInteger('pageNo');
-               $this->readInteger('userID');
-               
-               $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->parameters['userID']);
-               if (!$this->userProfile) {
-                       throw new UserInputException('userID');
-               }
-               if (!$this->userProfile->isAccessible('canViewTrophies') && $this->userProfile->userID != WCF::getSession()->userID) {
-                       throw new PermissionDeniedException();
-               }
-
-               if ($this->parameters['pageNo'] < 1) {
-                       throw new UserInputException('pageNo');
-               }
-       }
-       
-       /**
-        * Returns a viewable user trophy list for a specific user. 
-        */
-       public function getGroupedUserTrophyList() {
-               $userTrophyList = new UserTrophyList();
-               $userTrophyList->getConditionBuilder()->add('userID = ?', [$this->parameters['userID']]);
-               if (!empty($userTrophyList->sqlJoins)) $userTrophyList->sqlJoins .= ' ';
-               if (!empty($userTrophyList->sqlConditionJoins)) $userTrophyList->sqlConditionJoins .= ' ';
-               $userTrophyList->sqlJoins .= 'LEFT JOIN wcf'. WCF_N . '_trophy trophy ON user_trophy.trophyID = trophy.trophyID';
-               $userTrophyList->sqlConditionJoins .= 'LEFT JOIN wcf'. WCF_N . '_trophy trophy ON user_trophy.trophyID = trophy.trophyID';
-               
-               // trophy category join
-               $userTrophyList->sqlJoins .= ' LEFT JOIN wcf'. WCF_N . '_category category ON trophy.categoryID = category.categoryID';
-               $userTrophyList->sqlConditionJoins .= ' LEFT JOIN wcf'. WCF_N . '_category category ON trophy.categoryID = category.categoryID';
-               
-               $userTrophyList->getConditionBuilder()->add('trophy.isDisabled = ?', [0]);
-               $userTrophyList->getConditionBuilder()->add('category.isDisabled = ?', [0]);
-               $userTrophyList->sqlLimit = 10; 
-               $userTrophyList->sqlOffset = ($this->parameters['pageNo'] - 1) * 10;
-               $userTrophyList->sqlOrderBy = 'time DESC';
-               $pageCount = ceil($userTrophyList->countObjects() / 10);
-               $userTrophyList->readObjects();
-               
-               return [
-                       'pageCount' => $pageCount,
-                       'title' => WCF::getLanguage()->getDynamicVariable('wcf.user.trophy.dialogTitle', ['username' => $this->userProfile->username]),
-                       'template' => WCF::getTPL()->fetch('groupedUserTrophyList', 'wcf', [
-                               'userTrophyList' => $userTrophyList
-                       ])
-               ];
-       }
+class UserTrophyAction extends AbstractDatabaseObjectAction
+{
+    /**
+     * @inheritDoc
+     */
+    protected $permissionsDelete = ['admin.trophy.canAwardTrophy'];
+
+    /**
+     * @inheritDoc
+     */
+    protected $allowGuestAccess = ['getGroupedUserTrophyList'];
+
+    /**
+     * @var UserProfile
+     */
+    public $userProfile;
+
+    /**
+     * @inheritDoc
+     */
+    public function create()
+    {
+        /** @var UserTrophy $userTrophy */
+        $userTrophy = parent::create();
+
+        if (!$userTrophy->getTrophy()->isDisabled()) {
+            $userAction = new UserAction([$userTrophy->userID], 'update', [
+                'counters' => [
+                    'trophyPoints' => 1,
+                ],
+            ]);
+            $userAction->executeAction();
+
+            // checks if the user still has space to add special trophies
+            if (\count($userTrophy->getUserProfile()->getSpecialTrophies()) < $userTrophy->getUserProfile()->getPermission('user.profile.trophy.maxUserSpecialTrophies')) {
+                $hasTrophy = false;
+                foreach (UserTrophyList::getUserTrophies([$userTrophy->getUserProfile()->userID])[$userTrophy->getUserProfile()->userID] as $trophy) {
+                    if ($trophy->trophyID == $userTrophy->trophyID && $trophy->userTrophyID !== $userTrophy->userTrophyID) {
+                        $hasTrophy = true;
+                        break;
+                    }
+                }
+
+                if (!$hasTrophy) {
+                    $userProfileAction = new UserProfileAction(
+                        [$userTrophy->getUserProfile()->getDecoratedObject()],
+                        'updateSpecialTrophies',
+                        [
+                            'trophyIDs' => \array_unique(\array_merge(\array_map(static function ($trophy) {
+                                return $trophy->trophyID;
+                            }, $userTrophy->getUserProfile()->getSpecialTrophies()), [$userTrophy->trophyID])),
+                        ]
+                    );
+                    $userProfileAction->executeAction();
+                }
+            }
+        }
+
+        UserActivityEventHandler::getInstance()->fireEvent(
+            'com.woltlab.wcf.userTrophy.recentActivityEvent.trophyReceived',
+            $userTrophy->getObjectID(),
+            null,
+            $userTrophy->userID
+        );
+
+        UserNotificationHandler::getInstance()->fireEvent(
+            'received',
+            'com.woltlab.wcf.userTrophy.notification',
+            new UserTrophyNotificationObject($userTrophy),
+            [
+                $userTrophy->userID,
+            ]
+        );
+
+        return $userTrophy;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function validateDelete()
+    {
+        parent::validateDelete();
+
+        /** @var UserTrophy $object */
+        foreach ($this->objects as $object) {
+            if ($object->getTrophy()->awardAutomatically) {
+                throw new PermissionDeniedException();
+            }
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function delete()
+    {
+        if (empty($this->objects)) {
+            $this->readObjects();
+        }
+
+        $trophyIDs = $userIDs = [];
+        foreach ($this->getObjects() as $object) {
+            $trophyIDs[] = $object->trophyID;
+            $userIDs[] = $object->userID;
+        }
+
+        $returnValues = parent::delete();
+
+        if (!empty($this->objects)) {
+            // update user special trophies trophies
+            $userTrophies = UserTrophyList::getUserTrophies($userIDs);
+
+            foreach ($userTrophies as $userID => $trophies) {
+                $userTrophyIDs = [];
+                foreach ($trophies as $trophy) {
+                    $userTrophyIDs[] = $trophy->trophyID;
+                }
+
+                $conditionBuilder = new PreparedStatementConditionBuilder();
+                if (!empty($userTrophyIDs)) {
+                    $conditionBuilder->add('trophyID NOT IN (?)', [\array_unique($userTrophyIDs)]);
+                }
+                $conditionBuilder->add('userID = ?', [$userID]);
+
+                $sql = "DELETE FROM wcf" . WCF_N . "_user_special_trophy
+                        " . $conditionBuilder;
+                $statement = WCF::getDB()->prepareStatement($sql);
+                $statement->execute($conditionBuilder->getParameters());
+
+                UserStorageHandler::getInstance()->reset([$userID], 'specialTrophies');
+            }
+
+            $updateUserTrophies = [];
+            foreach ($this->getObjects() as $object) {
+                if (!$object->getTrophy()->isDisabled()) {
+                    if (!isset($updateUserTrophies[$object->userID])) {
+                        $updateUserTrophies[$object->userID] = 0;
+                    }
+                    $updateUserTrophies[$object->userID]--;
+                }
+            }
+
+            foreach ($updateUserTrophies as $userID => $count) {
+                $userAction = new UserAction([$userID], 'update', [
+                    'counters' => [
+                        'trophyPoints' => $count,
+                    ],
+                ]);
+                $userAction->executeAction();
+            }
+        }
+
+        return $returnValues;
+    }
+
+    /**
+     * Validates the getGroupedUserTrophyList method.
+     */
+    public function validateGetGroupedUserTrophyList()
+    {
+        if (!MODULE_TROPHY) {
+            throw new IllegalLinkException();
+        }
+
+        WCF::getSession()->checkPermissions(['user.profile.trophy.canSeeTrophies']);
+
+        $this->readInteger('pageNo');
+        $this->readInteger('userID');
+
+        $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->parameters['userID']);
+        if (!$this->userProfile) {
+            throw new UserInputException('userID');
+        }
+        if (!$this->userProfile->isAccessible('canViewTrophies') && $this->userProfile->userID != WCF::getSession()->userID) {
+            throw new PermissionDeniedException();
+        }
+
+        if ($this->parameters['pageNo'] < 1) {
+            throw new UserInputException('pageNo');
+        }
+    }
+
+    /**
+     * Returns a viewable user trophy list for a specific user.
+     */
+    public function getGroupedUserTrophyList()
+    {
+        $userTrophyList = new UserTrophyList();
+        $userTrophyList->getConditionBuilder()->add('userID = ?', [$this->parameters['userID']]);
+        if (!empty($userTrophyList->sqlJoins)) {
+            $userTrophyList->sqlJoins .= ' ';
+        }
+        if (!empty($userTrophyList->sqlConditionJoins)) {
+            $userTrophyList->sqlConditionJoins .= ' ';
+        }
+        $userTrophyList->sqlJoins .= '
+            LEFT JOIN   wcf' . WCF_N . '_trophy trophy
+            ON          user_trophy.trophyID = trophy.trophyID';
+        $userTrophyList->sqlConditionJoins .= '
+            LEFT JOIN   wcf' . WCF_N . '_trophy trophy
+            ON          user_trophy.trophyID = trophy.trophyID';
+
+        // trophy category join
+        $userTrophyList->sqlJoins .= '
+            LEFT JOIN   wcf' . WCF_N . '_category category
+            ON          trophy.categoryID = category.categoryID';
+        $userTrophyList->sqlConditionJoins .= '
+            LEFT JOIN   wcf' . WCF_N . '_category category
+            ON          trophy.categoryID = category.categoryID';
+
+        $userTrophyList->getConditionBuilder()->add('trophy.isDisabled = ?', [0]);
+        $userTrophyList->getConditionBuilder()->add('category.isDisabled = ?', [0]);
+        $userTrophyList->sqlLimit = 10;
+        $userTrophyList->sqlOffset = ($this->parameters['pageNo'] - 1) * 10;
+        $userTrophyList->sqlOrderBy = 'time DESC';
+        $pageCount = \ceil($userTrophyList->countObjects() / 10);
+        $userTrophyList->readObjects();
+
+        return [
+            'pageCount' => $pageCount,
+            'title' => WCF::getLanguage()->getDynamicVariable(
+                'wcf.user.trophy.dialogTitle',
+                ['username' => $this->userProfile->username]
+            ),
+            'template' => WCF::getTPL()->fetch('groupedUserTrophyList', 'wcf', [
+                'userTrophyList' => $userTrophyList,
+            ]),
+        ];
+    }
 }