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: 19 additions & 62 deletions wcfsetup/install/files/acp/templates/adList.tpl
Original file line number Diff line number Diff line change
@@ -1,80 +1,37 @@
{include file='header' pageTitle='wcf.acp.ad.list'}

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

<header class="contentHeader">
<div class="contentHeaderTitle">
<h1 class="contentTitle">{lang}wcf.acp.ad.list{/lang}{if $items} <span class="badge badgeInverse">{#$items}</span>{/if}</h1>
<h1 class="contentTitle">{lang}wcf.acp.ad.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='AdAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.menu.link.ad.add{/lang}</span></a></li>

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

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

{if $objects|count}
<div class="section sortableListContainer" id="adList">
<ol class="sortableList jsObjectActionContainer jsReloadPageWhenEmpty" data-object-id="0" start="{@($pageNo - 1) * $itemsPerPage + 1}" data-object-action-class-name="wcf\data\ad\AdAction">
{foreach from=$objects item='ad'}
<li class="sortableNode sortableNoNesting jsAd jsObjectActionObject" data-object-id="{@$ad->adID}">
<span class="sortableNodeLabel">
<a href="{link controller='AdEdit' object=$ad}{/link}">{$ad->adName}</a>

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

{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='AdAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.menu.link.ad.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}
<script data-relocate="true">
require(["WoltLabSuite/Core/Component/ChangeShowOrder"], ({ setup }) => {
{jsphrase name='wcf.global.changeShowOrder'}

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

{include file='footer'}
23 changes: 10 additions & 13 deletions wcfsetup/install/files/lib/acp/page/AdListPage.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\ad\AdList;
use wcf\page\MultipleLinkPage;
use wcf\page\AbstractGridViewPage;
use wcf\system\gridView\AbstractGridView;
use wcf\system\gridView\admin\AdGridView;

/**
* Lists the available ads.
Expand All @@ -12,9 +13,9 @@
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @extends MultipleLinkPage<AdList>
* @extends AbstractGridViewPage<AdGridView>
*/
class AdListPage extends MultipleLinkPage
class AdListPage extends AbstractGridViewPage
{
/**
* @inheritDoc
Expand All @@ -31,13 +32,9 @@ class AdListPage extends MultipleLinkPage
*/
public $neededModules = ['MODULE_WCF_AD'];

/**
* @inheritDoc
*/
public $objectListClassName = AdList::class;

/**
* @inheritDoc
*/
public $sqlOrderBy = 'ad.showOrder';
#[\Override]
protected function createGridView(): AbstractGridView
{
return new AdGridView();
}
}
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 @@ -216,6 +216,11 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
$event->register(new \wcf\system\endpoint\controller\core\trophies\DeleteTrophy());
$event->register(new \wcf\system\endpoint\controller\core\trophies\GetShowOrder());
$event->register(new \wcf\system\endpoint\controller\core\trophies\ChangeShowOrder());
$event->register(new \wcf\system\endpoint\controller\core\ads\EnableAd());
$event->register(new \wcf\system\endpoint\controller\core\ads\DisableAd());
$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());
}
);

Expand Down
63 changes: 1 addition & 62 deletions wcfsetup/install/files/lib/data/ad/AdAction.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
namespace wcf\data\ad;

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\WCF;

/**
* Executes ad-related actions.
Expand All @@ -19,7 +16,7 @@
*
* @extends AbstractDatabaseObjectAction<Ad, AdEditor>
*/
class AdAction extends AbstractDatabaseObjectAction implements ISortableAction, IToggleAction
class AdAction extends AbstractDatabaseObjectAction implements IToggleAction
{
use TDatabaseObjectToggle;

Expand Down Expand Up @@ -67,62 +64,4 @@ public function delete()

return parent::delete();
}

/**
* @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');
}

$adList = new AdList();
$adList->setObjectIDs($this->parameters['data']['structure'][0]);
$adList->readObjects();
if (\count($adList) !== \count($this->parameters['data']['structure'][0])) {
throw new UserInputException('structure');
}

$this->readInteger('offset', true, 'data');
}

/**
* @inheritDoc
*/
public function update()
{
parent::update();

if (
\count($this->objects) == 1
&& isset($this->parameters['data']['showOrder'])
&& $this->parameters['data']['showOrder'] != \reset($this->objects)->showOrder
) {
\reset($this->objects)->setShowOrder($this->parameters['data']['showOrder']);
}
}

/**
* @inheritDoc
*/
public function updatePosition()
{
$sql = "UPDATE wcf1_ad
SET showOrder = ?
WHERE adID = ?";
$statement = WCF::getDB()->prepare($sql);

$showOrder = $this->parameters['data']['offset'];
WCF::getDB()->beginTransaction();
foreach ($this->parameters['data']['structure'][0] as $adID) {
$statement->execute([
$showOrder++,
$adID,
]);
}
WCF::getDB()->commitTransaction();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace wcf\event\gridView\admin;

use wcf\event\IPsr14Event;
use wcf\system\gridView\admin\AdGridView;

/**
* Indicates that the ad grid view has been initialized.
*
* @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 AdGridViewInitialized implements IPsr14Event
{
public function __construct(public readonly AdGridView $param)
{
}
}
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\AdInteractions;

/**
* Indicates that the provider for ad 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 AdInteractionCollecting implements IPsr14Event
{
public function __construct(public readonly AdInteractions $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\AdBulkInteractions;

/**
* Indicates that the provider for ad 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 AdBulkInteractionCollecting implements IPsr14Event
{
public function __construct(public readonly AdBulkInteractions $param)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

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

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\ad\Ad;
use wcf\data\ad\AdList;
use wcf\system\cache\builder\AdCacheBuilder;
use wcf\system\endpoint\IController;
use wcf\system\endpoint\PostRequest;
use wcf\system\exception\IllegalLinkException;
use wcf\system\showOrder\ShowOrderHandler;
use wcf\system\showOrder\ShowOrderItem;
use wcf\system\WCF;

/**
* API endpoint for changing the show order of ads.
*
* @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/ads/show-order')]
final class ChangeShowOrder implements IController
{
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
{
$this->assertAdCanBeSorted();

$adList = new AdList();
$adList->sqlOrderBy = 'showOrder ASC';
$adList->readObjects();

$items = \array_map(
static fn(Ad $ad) => new ShowOrderItem($ad->adID, $ad->getTitle()),
$adList->getObjects()
);

$sortedItems = (new ShowOrderHandler($items))->getSortedItemsFromRequest($request);
$this->saveShowOrder($sortedItems);

return new JsonResponse([]);
}

private function assertAdCanBeSorted(): void
{
if (!\MODULE_WCF_AD) {
throw new IllegalLinkException();
}

WCF::getSession()->checkPermissions(['admin.ad.canManageAd']);
}

/**
* @param list<ShowOrderItem> $items
*/
private function saveShowOrder(array $items): void
{
WCF::getDB()->beginTransaction();
$sql = "UPDATE wcf1_ad
SET showOrder = ?
WHERE adID = ?";
$statement = WCF::getDB()->prepare($sql);
for ($i = 0, $length = \count($items); $i < $length; $i++) {
$statement->execute([
$i + 1,
$items[$i]->id,
]);
}
WCF::getDB()->commitTransaction();

AdCacheBuilder::getInstance()->reset();
}
}
Loading