Merge branch '5.3'
authorTim Düsterhus <duesterhus@woltlab.com>
Tue, 16 Feb 2021 08:20:38 +0000 (09:20 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Tue, 16 Feb 2021 08:20:38 +0000 (09:20 +0100)
1  2 
wcfsetup/install/files/lib/system/worker/UserContentRemoveWorker.class.php

index 472389328011d8ae74757624ef3e997dee9ed0bd,a2ba81f9a1ddeff424188689b7f49438bad00949..9f4773dcda16a59e66799b274bc8c75ec99eb85e
@@@ -15,259 -10,206 +15,261 @@@ use wcf\system\WCF
  /**
   * Worker implementation for updating users.
   *
 - * @author    Joshua Ruesweg
 - * @copyright 2001-2019 WoltLab GmbH
 - * @license   GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 - * @package   WoltLabSuite\Core\System\Worker
 - * @since     5.2
 + * @author  Joshua Ruesweg
 + * @copyright   2001-2019 WoltLab GmbH
 + * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 + * @package WoltLabSuite\Core\System\Worker
 + * @since   5.2
   */
 -class UserContentRemoveWorker extends AbstractWorker {
 -      /**
 -       * variable name for the session to store the data
 -       */
 -      const USER_CONTENT_REMOVE_WORKER_SESSION_NAME = 'userContentRemoveWorkerData';
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      protected $limit = 10;
 -      
 -      /**
 -       * user
 -       * @var User
 -       */
 -      protected $user = null;
 -      
 -      /**
 -       * data
 -       * @var mixed 
 -       */
 -      protected $data = null;
 -      
 -      /**
 -       * 
 -       * @var null 
 -       */
 -      public $contentProvider = null;
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      public function validate() {
 -              if (!isset($this->parameters['userID'])) {
 -                      throw new \InvalidArgumentException('userID missing');
 -              }
 -              
 -              $this->user = new User($this->parameters['userID']);
 -              
 -              if (!$this->user->userID) {
 -                      throw new \InvalidArgumentException('userID is unknown.');
 -              }
 -              
 -              if (!$this->user->canEdit()) {
 -                      throw new PermissionDeniedException();
 -              }
 -              
 -              if (isset($this->parameters['contentProvider'])) {
 -                      if (!is_array($this->parameters['contentProvider'])) {
 -                              throw new \InvalidArgumentException('The parameter `contentProvider` must be an array.');
 -                      }
 -                      
 -                      $knownContentProvider = array_map(function ($contentProvider) {
 -                              return $contentProvider->objectType;
 -                      }, ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.content.userContentProvider'));
 -                      
 -                      $unknownContentProvider = array_diff($this->parameters['contentProvider'], $knownContentProvider);
 -                      if (!empty($unknownContentProvider)) {
 -                              throw new \InvalidArgumentException('The parameter `contentProvider` contains unknown objectTypes ('. implode(', ', $unknownContentProvider) .').');
 -                      }
 -                      
 -                      $this->contentProvider = $this->parameters['contentProvider'];
 -              }
 -              
 -              if ($this->loopCount === 0) {
 -                      $this->generateData();
 -              }
 -              else {
 -                      $data = WCF::getSession()->getVar(self::USER_CONTENT_REMOVE_WORKER_SESSION_NAME);
 -                      
 -                      if (!is_array($data) || !isset($data[$this->user->userID])) {
 -                              throw new \RuntimeException('`data` variable in session is invalid or missing.');
 -                      }
 -                      
 -                      $this->data = $data[$this->user->userID];
 -              }
 -      }
 -      
 -      /**
 -       * Generate the data variable. 
 -       */
 -      private function generateData() {
 -              $this->data = [
 -                      'provider' => [],
 -                      'count' => 0
 -              ];
 -              
 -              $contentProviders = ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.content.userContentProvider');
 -              
 -              // add the required object types for the select content provider
 -              if (is_array($this->contentProvider)) {
 -                      foreach ($this->contentProvider as $contentProvider) {
 -                              $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.content.userContentProvider', $contentProvider);
 -                              
 -                              if ($objectType->requiredobjecttype !== null) {
 -                                      $objectTypeNames = explode(',', $objectType->requiredobjecttype);
 -                                      
 -                                      foreach ($objectTypeNames as $objectTypeName) {
 -                                              $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.content.userContentProvider', $objectTypeName);
 -                                              
 -                                              if ($objectType === null) {
 -                                                      throw new \RuntimeException('Unknown required object type "' . $objectTypeName . '" for object type "' . $contentProvider . '" given.');
 -                                              }
 -                                              
 -                                              $this->contentProvider[] = $objectTypeName;
 -                                      }
 -                              }
 -                      }
 -              }
 -              
 -              foreach ($contentProviders as $contentProvider) {
 -                      if ($this->contentProvider === null || (is_array($this->contentProvider) && in_array($contentProvider->objectType, $this->contentProvider))) {
 -                              /** @var IUserContentProvider $processor */
 -                              $processor = $contentProvider->getProcessor();
 -                              $contentList = $processor->getContentListForUser($this->user);
 -                              $count = $contentList->countObjects();
 -                              
 -                              if ($count) {
 -                                      $this->data['provider'][$contentProvider->objectType] = [
 -                                              'count' => $count,
 -                                              'objectTypeID' => $contentProvider->objectTypeID,
 -                                              'nicevalue' => $contentProvider->nicevalue ?: 0
 -                                      ];
 -                                      
 -                                      $this->data['count'] += ceil($count / $this->limit) * $this->limit;
 -                              }
 -                      }
 -              }
 -              
 -              // sort object types
 -              uasort($this->data['provider'], function ($a, $b) {
 -                      $niceValueA = ($a['nicevalue'] ?: 0);
 -                      $niceValueB = ($b['nicevalue'] ?: 0);
 -                      
 -                      return $niceValueA <=> $niceValueB;
 -              });
 -      }
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      protected function countObjects() {
 -              $this->count = $this->data['count'];
 -      }
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      public function execute() {
 -              if (empty($this->data['provider'])) {
 -                      return;
 -              }
 -              
 -              $values = array_keys($this->data['provider']);
 -              $providerObjectType = array_shift($values);
 -              
 -              /** @var IUserContentProvider $processor */
 -              $processor = ObjectTypeCache::getInstance()->getObjectType($this->data['provider'][$providerObjectType]['objectTypeID'])->getProcessor();
 -              
 -              $objectList = $processor->getContentListForUser($this->user);
 -              $objectList->sqlLimit = $this->limit;
 -              $objectList->readObjectIDs();
 -              if (!empty($objectList->objectIDs)) {
 -                      $processor->deleteContent($objectList->objectIDs);
 -              }
 -              
 -              $this->data['provider'][$providerObjectType]['count'] -= $this->limit;
 -              
 -              if ($this->data['provider'][$providerObjectType]['count'] <= 0) {
 -                      unset($this->data['provider'][$providerObjectType]);
 -              }
 -      }
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      public function finalize() {
 -              parent::finalize();
 -              
 -              $dataArray = WCF::getSession()->getVar(self::USER_CONTENT_REMOVE_WORKER_SESSION_NAME);
 -              
 -              if (!is_array($dataArray)) {
 -                      $dataArray = [];
 -              }
 -              
 -              $dataArray[$this->user->userID] = $this->data;
 -              
 -              WCF::getSession()->register(self::USER_CONTENT_REMOVE_WORKER_SESSION_NAME, $dataArray);
 -      }
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      public function getProceedURL() {
 -              return LinkHandler::getInstance()->getLink('UserList');
 -      }
 +class UserContentRemoveWorker extends AbstractWorker
 +{
 +    /**
 +     * variable name for the session to store the data
 +     */
 +    const USER_CONTENT_REMOVE_WORKER_SESSION_NAME = 'userContentRemoveWorkerData';
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    protected $limit = 10;
 +
 +    /**
 +     * @var User[]
 +     */
 +    protected $users = [];
 +
 +    /**
 +     * data
 +     * @var mixed
 +     */
 +    protected $data;
 +
 +    /**
 +     * @var null
 +     */
 +    public $contentProviders;
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    public function validate()
 +    {
 +        if (isset($this->parameters['userID']) && !isset($this->parameters['userIDs'])) {
 +            $this->parameters['userIDs'] = [$this->parameters['userID']];
 +        }
 +
 +        if (
 +            isset($this->parameters['userIDs'])
 +            && \is_array($this->parameters['userIDs'])
 +            && !empty($this->parameters['userIDs'])
 +        ) {
 +            $userList = new UserList();
 +            $userList->setObjectIDs($this->parameters['userIDs']);
 +            $userList->readObjects();
 +
 +            if ($userList->count() !== \count($this->parameters['userIDs'])) {
 +                $diff = \array_diff($this->parameters['userIDs'], \array_column($userList->getObjects(), 'userID'));
 +
 +                throw new \InvalidArgumentException(
 +                    'The parameter `userIDs` contains unknown values (' . \implode(', ', $diff) . ').'
 +                );
 +            }
 +
 +            foreach ($userList as $user) {
 +                if (!$user->canEdit()) {
 +                    throw new PermissionDeniedException();
 +                }
 +
 +                $this->users[] = $user;
 +            }
 +        }
 +
 +        if (empty($this->users)) {
 +            throw new \InvalidArgumentException('The parameter `userIDs` is empty.');
 +        }
 +
 +        if (isset($this->parameters['contentProvider'])) {
 +            if (!\is_array($this->parameters['contentProvider'])) {
 +                throw new \InvalidArgumentException('The parameter `contentProvider` must be an array.');
 +            }
 +
 +            $unknownContentProvider = \array_diff(
 +                $this->parameters['contentProvider'],
 +                \array_column(
 +                    ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.content.userContentProvider'),
 +                    'objectType'
 +                )
 +            );
 +            if (!empty($unknownContentProvider)) {
 +                throw new \InvalidArgumentException('The parameter `contentProvider` contains unknown objectTypes (' . \implode(
 +                    ', ',
 +                    $unknownContentProvider
 +                ) . ').');
 +            }
 +
 +            $this->contentProviders = $this->parameters['contentProvider'];
 +        }
 +
 +        if ($this->loopCount === 0) {
 +            $this->generateData();
 +        } else {
 +            $data = WCF::getSession()->getVar(self::USER_CONTENT_REMOVE_WORKER_SESSION_NAME);
 +
 +            if (!\is_array($data) || !isset($data[$this->generateKey()])) {
 +                throw new \RuntimeException('`data` variable in session is invalid or missing.');
 +            }
 +
 +            $this->data = $data[$this->generateKey()];
 +        }
 +    }
 +
 +    /**
 +     * Generate the data variable.
 +     */
 +    private function generateData()
 +    {
 +        $this->data = [
 +            'provider' => [],
 +            'count' => 0,
 +        ];
 +
 +        /** @var ObjectType[] $contentProviders */
 +        $contentProviders = [];
 +
 +        // add the required object types for the select content provider
 +        if (\is_array($this->contentProviders)) {
 +            foreach ($this->contentProviders as $contentProvider) {
 +                $objectType = ObjectTypeCache::getInstance()
 +                    ->getObjectTypeByName('com.woltlab.wcf.content.userContentProvider', $contentProvider);
 +                $contentProviders[] = $objectType;
 +
 +                if ($objectType->requiredobjecttype !== null) {
 +                    $objectTypeNames = \explode(',', $objectType->requiredobjecttype);
 +
 +                    foreach ($objectTypeNames as $objectTypeName) {
 +                        $objectType = ObjectTypeCache::getInstance()
 +                            ->getObjectTypeByName('com.woltlab.wcf.content.userContentProvider', $objectTypeName);
 +
 +                        if ($objectType === null) {
 +                            throw new \RuntimeException('Unknown required object type "' . $objectTypeName . '" for object type "' . $contentProvider . '" given.');
 +                        }
 +
 +                        $this->contentProviders[] = $objectTypeName;
 +                        $contentProviders[] = $objectType;
 +                    }
 +                }
 +            }
 +        } else {
 +            $contentProviders = ObjectTypeCache::getInstance()
 +                ->getObjectTypes('com.woltlab.wcf.content.userContentProvider');
 +        }
 +
 +        // sort object types
 +        \uasort($contentProviders, static function ($a, $b) {
 +            $niceValueA = ($a->nicevalue ?: 0);
 +            $niceValueB = ($b->nicevalue ?: 0);
 +
 +            return $niceValueA <=> $niceValueB;
 +        });
 +
 +        foreach ($contentProviders as $contentProvider) {
 +            foreach ($this->users as $user) {
 +                /** @var IUserContentProvider $processor */
 +                $processor = $contentProvider->getProcessor();
 +                $contentList = $processor->getContentListForUser($user);
 +                $count = $contentList->countObjects();
 +
 +                if ($count) {
 +                    $this->data['provider'][] = [
 +                        'userID' => $user->userID,
 +                        'objectTypeID' => $contentProvider->objectTypeID,
 +                        'count' => $count,
 +                    ];
 +
 +                    $this->data['count'] += \ceil($count / $this->limit) * $this->limit;
 +                }
 +            }
 +        }
 +    }
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    protected function countObjects()
 +    {
 +        $this->count = $this->data['count'];
 +    }
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    public function execute()
 +    {
 +        if (empty($this->data['provider'])) {
 +            return;
 +        }
 +
 +        $providerIDs = \array_keys($this->data['provider']);
 +        $provideKey = \array_shift($providerIDs);
 +        $currentItem = $this->data['provider'][$provideKey];
 +
 +        /** @var IUserContentProvider $processor */
 +        $processor = ObjectTypeCache::getInstance()->getObjectType($currentItem['objectTypeID'])->getProcessor();
 +        $user = new User($currentItem['userID']);
 +
 +        $objectList = $processor->getContentListForUser($user);
 +        $objectList->sqlLimit = $this->limit;
 +        $objectList->readObjectIDs();
-         $processor->deleteContent($objectList->objectIDs);
++        if (!empty($objectList->objectIDs)) {
++            $processor->deleteContent($objectList->objectIDs);
++        }
 +
 +        $this->data['provider'][$provideKey]['count'] -= $this->limit;
 +
 +        if ($this->data['provider'][$provideKey]['count'] <= 0) {
 +            unset($this->data['provider'][$provideKey]);
 +        }
 +    }
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    public function finalize()
 +    {
 +        parent::finalize();
 +
 +        $dataArray = WCF::getSession()->getVar(self::USER_CONTENT_REMOVE_WORKER_SESSION_NAME);
 +
 +        if (!\is_array($dataArray)) {
 +            $dataArray = [];
 +        }
 +
 +        $dataArray[$this->generateKey()] = $this->data;
 +
 +        WCF::getSession()->register(self::USER_CONTENT_REMOVE_WORKER_SESSION_NAME, $dataArray);
 +
 +        ClipboardHandler::getInstance()->unmark(
 +            \array_column($this->users, 'userID'),
 +            ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.user')
 +        );
 +    }
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    public function getProceedURL()
 +    {
 +        return LinkHandler::getInstance()->getLink('UserList');
 +    }
 +
 +    /**
 +     * Generates a key for session data saving.
 +     */
 +    protected function generateKey(): string
 +    {
 +        $userIDs = \array_column($this->users, 'userID');
 +        \sort($userIDs);
 +
 +        return \sha1(\implode(';', $userIDs));
 +    }
  }