From: Tim Düsterhus Date: Tue, 16 Feb 2021 08:20:38 +0000 (+0100) Subject: Merge branch '5.3' X-Git-Tag: 5.4.0_Alpha_1~268^2~3 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f922a74bbcc2812b4bdae6a2ae4ea5205c54c633;p=GitHub%2FWoltLab%2FWCF.git Merge branch '5.3' --- f922a74bbcc2812b4bdae6a2ae4ea5205c54c633 diff --cc wcfsetup/install/files/lib/system/worker/UserContentRemoveWorker.class.php index 4723893280,a2ba81f9a1..9f4773dcda --- a/wcfsetup/install/files/lib/system/worker/UserContentRemoveWorker.class.php +++ b/wcfsetup/install/files/lib/system/worker/UserContentRemoveWorker.class.php @@@ -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 - * @package WoltLabSuite\Core\System\Worker - * @since 5.2 + * @author Joshua Ruesweg + * @copyright 2001-2019 WoltLab GmbH + * @license GNU Lesser General Public License + * @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)); + } }