Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 20 additions & 61 deletions wcfsetup/install/files/acp/templates/noticeList.tpl
Original file line number Diff line number Diff line change
@@ -1,80 +1,39 @@
{include file='header' pageTitle='wcf.acp.notice.list'}

<script data-relocate="true">
require(['WoltLabSuite/Core/Ui/Sortable/List'], function (UiSortableList) {
new UiSortableList({
containerId: 'noticeList',
className: 'wcf\\data\\notice\\NoticeAction',
offset: {@$startIndex}
});
});
</script>

<header class="contentHeader">
<div class="contentHeaderTitle">
<h1 class="contentTitle">{lang}wcf.acp.notice.list{/lang}{if $items} <span class="badge badgeInverse">{#$items}</span>{/if}</h1>
<h1 class="contentTitle">{lang}wcf.acp.notice.list{/lang} <span class="badge badgeInverse">{#$gridView->countRows()}</span></h1>
</div>

<nav class="contentHeaderNavigation">
<ul>
{if $gridView->countRows() > 1}
<li>
<button type="button" class="button jsChangeShowOrder">{icon name='up-down'} <span>{lang}wcf.global.changeShowOrder{/lang}</span></button>
</li>
{/if}
<li><a href="{link controller='NoticeAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.menu.link.notice.add{/lang}</span></a></li>

{event name='contentHeaderNavigation'}
</ul>
</nav>
</header>

{hascontent}
<div class="paginationTop">
{content}{pages print=true assign=pagesLinks controller="NoticeList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content}
</div>
{/hascontent}
<div class="section">
{unsafe:$gridView->render()}
</div>

{if $objects|count}
<div class="section sortableListContainer" id="noticeList">
<ol class="sortableList jsReloadPageWhenEmpty jsObjectActionContainer" data-object-action-class-name="wcf\data\notice\NoticeAction" data-object-id="0" start="{@($pageNo - 1) * $itemsPerPage + 1}">
{foreach from=$objects item='notice'}
<li class="sortableNode sortableNoNesting jsNotice jsObjectActionObject" data-object-id="{@$notice->getObjectID()}">
<span class="sortableNodeLabel">
<a href="{link controller='NoticeEdit' object=$notice}{/link}">{$notice->noticeName}</a>

<span class="statusDisplay sortableButtonContainer">
<span class="sortableNodeHandle">
{icon name='arrows-up-down-left-right'}
</span>
{objectAction action="toggle" isDisabled=$notice->isDisabled}
<a href="{link controller='NoticeEdit' object=$notice}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
{objectAction action="delete" objectTitle=$notice->noticeName}

{event name='itemButtons'}
</span>
</span>
</li>
{/foreach}
</ol>
</div>

<div class="formSubmit">
<button type="button" class="button buttonPrimary" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
</div>

<footer class="contentFooter">
{hascontent}
<div class="paginationBottom">
{content}{@$pagesLinks}{/content}
</div>
{/hascontent}

<nav class="contentFooterNavigation">
<ul>
<li><a href="{link controller='NoticeAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.menu.link.notice.add{/lang}</span></a></li>

{event name='contentFooterNavigation'}
</ul>
</nav>
</footer>
{else}
<woltlab-core-notice type="info">{lang}wcf.global.noItems{/lang}</woltlab-core-notice>
{if $gridView->countRows() > 1}
<script data-relocate="true">
require(["WoltLabSuite/Core/Component/ChangeShowOrder"], ({ setup }) => {
{jsphrase name='wcf.global.changeShowOrder'}

setup(
document.querySelector('.jsChangeShowOrder'),
'core/notices/show-order',
);
});
</script>
{/if}

{include file='footer'}
28 changes: 10 additions & 18 deletions wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -12,32 +13,23 @@
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @extends SortablePage<NoticeList>
* @extends AbstractGridViewPage<NoticeGridView>
*/
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();
}
}
5 changes: 5 additions & 0 deletions wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
);

Expand Down
46 changes: 1 addition & 45 deletions wcfsetup/install/files/lib/data/notice/NoticeAction.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -20,7 +18,7 @@
*
* @extends AbstractDatabaseObjectAction<Notice, NoticeEditor>
*/
class NoticeAction extends AbstractDatabaseObjectAction implements ISortableAction, IToggleAction
class NoticeAction extends AbstractDatabaseObjectAction implements IToggleAction
{
use TDatabaseObjectToggle;

Expand Down Expand Up @@ -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
*/
Expand All @@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace wcf\event\interaction\admin;

use wcf\event\IPsr14Event;
use wcf\system\interaction\admin\NoticeInteractions;

/**
* Indicates that the provider for notice interactions is collecting interactions.
*
* @author Olaf Braun
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
final class NoticeInteractionCollecting implements IPsr14Event
{
public function __construct(public readonly NoticeInteractions $param)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace wcf\event\interaction\bulk\admin;

use wcf\event\IPsr14Event;
use wcf\system\interaction\bulk\admin\NoticeBulkInteractions;

/**
* Indicates that the provider for notice bulk interactions is collecting interactions.
*
* @author Olaf Braun
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
final class NoticeBulkInteractionCollecting implements IPsr14Event
{
public function __construct(public readonly NoticeBulkInteractions $param)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace wcf\system\endpoint\controller\core\notices;

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\notice\Notice;
use wcf\data\notice\NoticeCache;
use wcf\data\notice\NoticeList;
use wcf\system\cache\builder\NoticeCacheBuilder;
use wcf\system\endpoint\IController;
use wcf\system\endpoint\PostRequest;
use wcf\system\showOrder\ShowOrderHandler;
use wcf\system\showOrder\ShowOrderItem;
use wcf\system\WCF;

/**
* API endpoint for changing the show order of notices.
*
* @author Olaf Braun
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @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<ShowOrderItem> $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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace wcf\system\endpoint\controller\core\notices;

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\notice\Notice;
use wcf\data\notice\NoticeAction;
use wcf\http\Helper;
use wcf\system\endpoint\DeleteRequest;
use wcf\system\endpoint\IController;
use wcf\system\WCF;

/**
* API endpoint for deleting notices.
*
* @author Olaf Braun
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @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([]);
}
}
Loading