diff --git a/wcfsetup/install/files/acp/templates/noticeList.tpl b/wcfsetup/install/files/acp/templates/noticeList.tpl index c3d7a15e4c2..5c30518be68 100644 --- a/wcfsetup/install/files/acp/templates/noticeList.tpl +++ b/wcfsetup/install/files/acp/templates/noticeList.tpl @@ -1,22 +1,17 @@ {include file='header' pageTitle='wcf.acp.notice.list'} - -
-

{lang}wcf.acp.notice.list{/lang}{if $items} {#$items}{/if}

+

{lang}wcf.acp.notice.list{/lang} {#$gridView->countRows()}

-{hascontent} -
- {content}{pages print=true assign=pagesLinks controller="NoticeList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content} -
-{/hascontent} +
+ {unsafe:$gridView->render()} +
-{if $objects|count} -
-
    - {foreach from=$objects item='notice'} -
  1. - - {$notice->noticeName} - - - - {icon name='arrows-up-down-left-right'} - - {objectAction action="toggle" isDisabled=$notice->isDisabled} - {icon name='pencil'} - {objectAction action="delete" objectTitle=$notice->noticeName} - - {event name='itemButtons'} - - -
  2. - {/foreach} -
-
- -
- -
- - -{else} - {lang}wcf.global.noItems{/lang} +{if $gridView->countRows() > 1} + {/if} {include file='footer'} diff --git a/wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php b/wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php index f61d91c45fd..9b733f8417d 100644 --- a/wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php +++ b/wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php @@ -2,8 +2,9 @@ namespace wcf\acp\page; -use wcf\data\notice\NoticeList; -use wcf\page\SortablePage; +use wcf\page\AbstractGridViewPage; +use wcf\system\gridView\AbstractGridView; +use wcf\system\gridView\admin\NoticeGridView; /** * Lists the available notices. @@ -12,32 +13,23 @@ * @copyright 2001-2019 WoltLab GmbH * @license GNU Lesser General Public License * - * @extends SortablePage + * @extends AbstractGridViewPage */ -class NoticeListPage extends SortablePage +class NoticeListPage extends AbstractGridViewPage { /** * @inheritDoc */ public $activeMenuItem = 'wcf.acp.menu.link.notice.list'; - /** - * @inheritDoc - */ - public $defaultSortField = 'showOrder'; - /** * @inheritDoc */ public $neededPermissions = ['admin.notice.canManageNotice']; - /** - * @inheritDoc - */ - public $objectListClassName = NoticeList::class; - - /** - * @inheritDoc - */ - public $validSortFields = ['noticeID', 'noticeName', 'showOrder']; + #[\Override] + protected function createGridView(): AbstractGridView + { + return new NoticeGridView(); + } } diff --git a/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php b/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php index 8e746d39af3..97fb3f812b6 100644 --- a/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php +++ b/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php @@ -222,6 +222,11 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) { $event->register(new \wcf\system\endpoint\controller\core\ads\DeleteAd()); $event->register(new \wcf\system\endpoint\controller\core\ads\GetShowOrder()); $event->register(new \wcf\system\endpoint\controller\core\ads\ChangeShowOrder()); + $event->register(new \wcf\system\endpoint\controller\core\notices\EnableNotice()); + $event->register(new \wcf\system\endpoint\controller\core\notices\DisableNotice()); + $event->register(new \wcf\system\endpoint\controller\core\notices\DeleteNotice()); + $event->register(new \wcf\system\endpoint\controller\core\notices\GetShowOrder()); + $event->register(new \wcf\system\endpoint\controller\core\notices\ChangeShowOrder()); } ); diff --git a/wcfsetup/install/files/lib/data/notice/NoticeAction.class.php b/wcfsetup/install/files/lib/data/notice/NoticeAction.class.php index 467a2487ce0..325174eea6c 100644 --- a/wcfsetup/install/files/lib/data/notice/NoticeAction.class.php +++ b/wcfsetup/install/files/lib/data/notice/NoticeAction.class.php @@ -3,11 +3,9 @@ namespace wcf\data\notice; use wcf\data\AbstractDatabaseObjectAction; -use wcf\data\ISortableAction; use wcf\data\IToggleAction; use wcf\data\TDatabaseObjectToggle; use wcf\system\condition\ConditionHandler; -use wcf\system\exception\UserInputException; use wcf\system\user\storage\UserStorageHandler; use wcf\system\WCF; @@ -20,7 +18,7 @@ * * @extends AbstractDatabaseObjectAction */ -class NoticeAction extends AbstractDatabaseObjectAction implements ISortableAction, IToggleAction +class NoticeAction extends AbstractDatabaseObjectAction implements IToggleAction { use TDatabaseObjectToggle; @@ -121,27 +119,6 @@ public function validateDismiss() $this->getSingleObject(); } - /** - * @inheritDoc - */ - public function validateUpdatePosition() - { - WCF::getSession()->checkPermissions($this->permissionsUpdate); - - if (!isset($this->parameters['data']['structure']) || !\is_array($this->parameters['data']['structure'])) { - throw new UserInputException('structure'); - } - - $noticeList = new NoticeList(); - $noticeList->setObjectIDs($this->parameters['data']['structure'][0]); - $noticeList->readObjects(); - if (\count($noticeList) !== \count($this->parameters['data']['structure'][0])) { - throw new UserInputException('structure'); - } - - $this->readInteger('offset', true, 'data'); - } - /** * @inheritDoc */ @@ -157,25 +134,4 @@ public function update() \reset($this->objects)->setShowOrder($this->parameters['data']['showOrder']); } } - - /** - * @inheritDoc - */ - public function updatePosition() - { - $sql = "UPDATE wcf1_notice - SET showOrder = ? - WHERE noticeID = ?"; - $statement = WCF::getDB()->prepare($sql); - - $showOrder = $this->parameters['data']['offset']; - WCF::getDB()->beginTransaction(); - foreach ($this->parameters['data']['structure'][0] as $noticeID) { - $statement->execute([ - $showOrder++, - $noticeID, - ]); - } - WCF::getDB()->commitTransaction(); - } } diff --git a/wcfsetup/install/files/lib/event/interaction/admin/NoticeInteractionCollecting.class.php b/wcfsetup/install/files/lib/event/interaction/admin/NoticeInteractionCollecting.class.php new file mode 100644 index 00000000000..4f5353eee86 --- /dev/null +++ b/wcfsetup/install/files/lib/event/interaction/admin/NoticeInteractionCollecting.class.php @@ -0,0 +1,21 @@ + + * @since 6.2 + */ +final class NoticeInteractionCollecting implements IPsr14Event +{ + public function __construct(public readonly NoticeInteractions $param) + { + } +} diff --git a/wcfsetup/install/files/lib/event/interaction/bulk/admin/NoticeBulkInteractionCollecting.class.php b/wcfsetup/install/files/lib/event/interaction/bulk/admin/NoticeBulkInteractionCollecting.class.php new file mode 100644 index 00000000000..215f15a9667 --- /dev/null +++ b/wcfsetup/install/files/lib/event/interaction/bulk/admin/NoticeBulkInteractionCollecting.class.php @@ -0,0 +1,21 @@ + + * @since 6.2 + */ +final class NoticeBulkInteractionCollecting implements IPsr14Event +{ + public function __construct(public readonly NoticeBulkInteractions $param) + { + } +} diff --git a/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/ChangeShowOrder.class.php b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/ChangeShowOrder.class.php new file mode 100644 index 00000000000..3d4031c2d32 --- /dev/null +++ b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/ChangeShowOrder.class.php @@ -0,0 +1,68 @@ + + * @since 6.2 + */ +#[PostRequest('/core/notices/show-order')] +final class ChangeShowOrder implements IController +{ + public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface + { + WCF::getSession()->checkPermissions(['admin.notice.canManageNotice']); + + $noticeList = new NoticeList(); + $noticeList->sqlOrderBy = 'showOrder ASC'; + $noticeList->readObjects(); + + $items = \array_map( + static fn(Notice $notice) => new ShowOrderItem($notice->noticeID, $notice->getTitle()), + $noticeList->getObjects() + ); + + $sortedItems = (new ShowOrderHandler($items))->getSortedItemsFromRequest($request); + $this->saveShowOrder($sortedItems); + + return new JsonResponse([]); + } + + /** + * @param list $items + */ + private function saveShowOrder(array $items): void + { + WCF::getDB()->beginTransaction(); + $sql = "UPDATE wcf1_notice + SET showOrder = ? + WHERE noticeID = ?"; + $statement = WCF::getDB()->prepare($sql); + for ($i = 0, $length = \count($items); $i < $length; $i++) { + $statement->execute([ + $i + 1, + $items[$i]->id, + ]); + } + WCF::getDB()->commitTransaction(); + + NoticeCacheBuilder::getInstance()->reset(); + } +} diff --git a/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/DeleteNotice.class.php b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/DeleteNotice.class.php new file mode 100644 index 00000000000..f88153833b6 --- /dev/null +++ b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/DeleteNotice.class.php @@ -0,0 +1,37 @@ + + * @since 6.2 + */ +#[DeleteRequest("/core/notices/{id:\d+}")] +final class DeleteNotice implements IController +{ + #[\Override] + public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface + { + WCF::getSession()->checkPermissions(['admin.notice.canManageNotice']); + + $notice = Helper::fetchObjectFromRequestParameter($variables['id'], Notice::class); + + (new NoticeAction([$notice], 'delete'))->executeAction(); + + return new JsonResponse([]); + } +} diff --git a/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/DisableNotice.class.php b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/DisableNotice.class.php new file mode 100644 index 00000000000..f12e7194594 --- /dev/null +++ b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/DisableNotice.class.php @@ -0,0 +1,46 @@ + + * @since 6.2 + */ +#[PostRequest("/core/notices/{id:\d+}/disable")] +final class DisableNotice implements IController +{ + public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface + { + $notice = Helper::fetchObjectFromRequestParameter($variables['id'], Notice::class); + + $this->assertNoticeCanBeDisabled($notice); + + (new NoticeAction([$notice], 'toggle'))->executeAction(); + + return new JsonResponse([]); + } + + private function assertNoticeCanBeDisabled(Notice $notice): void + { + WCF::getSession()->checkPermissions(['admin.notice.canManageNotice']); + + if ($notice->isDisabled) { + throw new PermissionDeniedException(); + } + } +} diff --git a/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/EnableNotice.class.php b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/EnableNotice.class.php new file mode 100644 index 00000000000..2c39f7fe5ee --- /dev/null +++ b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/EnableNotice.class.php @@ -0,0 +1,46 @@ + + * @since 6.2 + */ +#[PostRequest("/core/notices/{id:\d+}/enable")] +final class EnableNotice implements IController +{ + public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface + { + $notice = Helper::fetchObjectFromRequestParameter($variables['id'], Notice::class); + + $this->assertNoticeCanBeEnabled($notice); + + (new NoticeAction([$notice], 'toggle'))->executeAction(); + + return new JsonResponse([]); + } + + private function assertNoticeCanBeEnabled(Notice $notice): void + { + WCF::getSession()->checkPermissions(['admin.notice.canManageNotice']); + + if (!$notice->isDisabled) { + throw new PermissionDeniedException(); + } + } +} diff --git a/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/GetShowOrder.class.php b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/GetShowOrder.class.php new file mode 100644 index 00000000000..60ea8865175 --- /dev/null +++ b/wcfsetup/install/files/lib/system/endpoint/controller/core/notices/GetShowOrder.class.php @@ -0,0 +1,41 @@ + + * @since 6.2 + */ +#[GetRequest('/core/notices/show-order')] +final class GetShowOrder implements IController +{ + public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface + { + WCF::getSession()->checkPermissions(['admin.notice.canManageNotice']); + + $noticeList = new NoticeList(); + $noticeList->sqlOrderBy = 'showOrder ASC'; + $noticeList->readObjects(); + + $items = \array_map( + static fn(Notice $notice) => new ShowOrderItem($notice->noticeID, $notice->getTitle()), + $noticeList->getObjects() + ); + + return (new ShowOrderHandler($items))->toJsonResponse(); + } +} diff --git a/wcfsetup/install/files/lib/system/gridView/admin/NoticeGridView.class.php b/wcfsetup/install/files/lib/system/gridView/admin/NoticeGridView.class.php new file mode 100644 index 00000000000..cb13266672e --- /dev/null +++ b/wcfsetup/install/files/lib/system/gridView/admin/NoticeGridView.class.php @@ -0,0 +1,84 @@ + + * @since 6.2 + * + * @extends AbstractGridView + */ +final class NoticeGridView extends AbstractGridView +{ + public function __construct() + { + $this->addColumns([ + GridViewColumn::for('noticeID') + ->label('wcf.global.objectID') + ->renderer(new ObjectIdColumnRenderer()) + ->sortable(), + GridViewColumn::for('noticeName') + ->label('wcf.global.name') + ->titleColumn() + ->filter(new TextFilter()) + ->sortable(), + GridViewColumn::for('showOrder') + ->label('wcf.global.showOrder') + ->renderer(new NumberColumnRenderer()) + ->filter(new NumericFilter()) + ->sortable(), + ]); + + $provider = new NoticeInteractions(); + $provider->addInteractions([ + new Divider(), + new EditInteraction(NoticeEditForm::class) + ]); + $this->setInteractionProvider($provider); + $this->setBulkInteractionProvider(new NoticeBulkInteractions()); + + $this->addQuickInteraction( + new ToggleInteraction( + 'enable', + 'core/notices/%s/enable', + 'core/notices/%s/disable' + ) + ); + + $this->setSortField("showOrder"); + $this->addRowLink(new GridViewRowLink(NoticeEditForm::class)); + } + + #[\Override] + public function isAccessible(): bool + { + return WCF::getSession()->getPermission("admin.notice.canManageNotice"); + } + + #[\Override] + protected function createObjectList(): NoticeList + { + return new NoticeList(); + } +} diff --git a/wcfsetup/install/files/lib/system/interaction/admin/NoticeInteractions.class.php b/wcfsetup/install/files/lib/system/interaction/admin/NoticeInteractions.class.php new file mode 100644 index 00000000000..83c790c2d37 --- /dev/null +++ b/wcfsetup/install/files/lib/system/interaction/admin/NoticeInteractions.class.php @@ -0,0 +1,37 @@ + + * @since 6.2 + */ +final class NoticeInteractions extends AbstractInteractionProvider +{ + public function __construct() + { + $this->addInteractions([ + new DeleteInteraction("core/notices/%s"), + ]); + + EventHandler::getInstance()->fire( + new NoticeInteractionCollecting($this) + ); + } + + #[\Override] + public function getObjectClassName(): string + { + return Notice::class; + } +} diff --git a/wcfsetup/install/files/lib/system/interaction/bulk/admin/NoticeBulkInteractions.class.php b/wcfsetup/install/files/lib/system/interaction/bulk/admin/NoticeBulkInteractions.class.php new file mode 100644 index 00000000000..25aab8f4f75 --- /dev/null +++ b/wcfsetup/install/files/lib/system/interaction/bulk/admin/NoticeBulkInteractions.class.php @@ -0,0 +1,37 @@ + + * @since 6.2 + */ +final class NoticeBulkInteractions extends AbstractBulkInteractionProvider +{ + public function __construct() + { + $this->addInteractions([ + new BulkDeleteInteraction('core/notices/%s') + ]); + + EventHandler::getInstance()->fire( + new NoticeBulkInteractionCollecting($this) + ); + } + + #[\Override] + public function getObjectListClassName(): string + { + return NoticeList::class; + } +}