Skip to content

Commit 39ddf8e

Browse files
committed
Migrate PaidSubscriptionUserListPage to grid view
1 parent bc4ed04 commit 39ddf8e

File tree

8 files changed

+258
-221
lines changed

8 files changed

+258
-221
lines changed
Lines changed: 4 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
{include file='header' pageTitle='wcf.acp.paidSubscription.user.list'}
22

3-
<script data-relocate="true">
4-
require(['WoltLabSuite/Core/Ui/User/Search/Input'], (UiUserSearchInput) => {
5-
new UiUserSearchInput(document.getElementById('username'));
6-
});
7-
</script>
8-
93
<header class="contentHeader">
104
<div class="contentHeaderTitle">
11-
<h1 class="contentTitle">{lang}wcf.acp.paidSubscription.user.list{/lang}{if $items} <span class="badge badgeInverse">{#$items}</span>{/if}</h1>
5+
<h1 class="contentTitle">{lang}wcf.acp.paidSubscription.user.list{/lang} <span class="badge badgeInverse">{#$gridView->countRows()}</span></h1>
126
</div>
137

148
{hascontent}
@@ -20,111 +14,8 @@
2014
{/hascontent}
2115
</header>
2216

23-
<form method="post" action="{link controller='PaidSubscriptionUserList'}{/link}">
24-
<section class="section">
25-
<h2 class="sectionTitle">{lang}wcf.global.filter{/lang}</h2>
26-
27-
<div class="row rowColGap formGrid">
28-
<dl class="col-xs-12 col-md-4">
29-
<dt></dt>
30-
<dd>
31-
<input type="text" id="username" name="username" value="{$username}" placeholder="{lang}wcf.user.username{/lang}" class="long">
32-
</dd>
33-
</dl>
34-
35-
{if $availableSubscriptions|count > 1}
36-
<dl class="col-xs-12 col-md-4">
37-
<dt></dt>
38-
<dd>
39-
<select name="subscriptionID" id="subscriptionID">
40-
<option value="0">{lang}wcf.acp.paidSubscription.subscription{/lang}</option>
41-
{foreach from=$availableSubscriptions item=availableSubscription}
42-
<option value="{$availableSubscription->subscriptionID}"{if $availableSubscription->subscriptionID == $subscriptionID} selected{/if}>{$availableSubscription->getTitle()}</option>
43-
{/foreach}
44-
</select>
45-
</dd>
46-
</dl>
47-
{/if}
48-
49-
{event name='filterFields'}
50-
</div>
51-
52-
<div class="formSubmit">
53-
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
54-
{csrfToken}
55-
</div>
56-
</section>
57-
</form>
58-
59-
{assign var='linkParameters' value=''}
60-
{if $username}{capture append=linkParameters}&username={@$username|rawurlencode}{/capture}{/if}
61-
{if $subscriptionID}{capture append=linkParameters}&subscriptionID={@$subscriptionID}{/capture}{/if}
62-
63-
{hascontent}
64-
<div class="paginationTop">
65-
{content}{pages print=true assign=pagesLinks controller='PaidSubscriptionUserList' link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$linkParameters"}{/content}
66-
</div>
67-
{/hascontent}
68-
69-
{if $objects|count}
70-
<div class="section tabularBox">
71-
<table class="table jsObjectActionContainer" data-object-action-class-name="wcf\data\paid\subscription\user\PaidSubscriptionUserAction"
72-
<thead>
73-
<tr>
74-
<th class="columnID columnSubscriptionUserID{if $sortField == 'subscriptionUserID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='PaidSubscriptionUserList'}pageNo={@$pageNo}&sortField=subscriptionUserID&sortOrder={if $sortField == 'subscriptionUserID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
75-
<th class="columnText columnUsername{if $sortField == 'username'} active {@$sortOrder}{/if}"><a href="{link controller='PaidSubscriptionUserList'}pageNo={@$pageNo}&sortField=username&sortOrder={if $sortField == 'username' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.user.username{/lang}</a></th>
76-
<th class="columnText columnSubscriptionTitle{if $sortField == 'subscriptionID'} active {@$sortOrder}{/if}"><a href="{link controller='PaidSubscriptionUserList'}pageNo={@$pageNo}&sortField=subscriptionID&sortOrder={if $sortField == 'subscriptionID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.acp.paidSubscription.subscription{/lang}</a></th>
77-
<th class="columnDate columnEndDate{if $sortField == 'endDate'} active {@$sortOrder}{/if}"><a href="{link controller='PaidSubscriptionUserList'}pageNo={@$pageNo}&sortField=endDate&sortOrder={if $sortField == 'endDate' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.acp.paidSubscription.user.endDate{/lang}</a></th>
78-
79-
{event name='columnHeads'}
80-
</tr>
81-
</thead>
82-
83-
<tbody class="jsReloadPageWhenEmpty">
84-
{foreach from=$objects item=subscriptionUser}
85-
<tr class="jsPaidSubscriptionUserRow jsObjectActionObject" data-object-id="{@$subscriptionUser->getObjectID()}">
86-
<td class="columnIcon">
87-
{if $subscriptionUser->endDate}
88-
<a href="{link controller='PaidSubscriptionUserEdit' id=$subscriptionUser->subscriptionUserID}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
89-
{else}
90-
<span class="disabled" title="{lang}wcf.global.button.edit{/lang}">
91-
{icon name='pencil'}
92-
</span>
93-
{/if}
94-
{objectAction action="delete" confirmMessage='wcf.acp.paidSubscription.user.delete.confirmMessage'}
95-
96-
{event name='itemButtons'}
97-
</td>
98-
<td class="columnID columnSubscriptionUserID">{@$subscriptionUser->subscriptionUserID}</td>
99-
<td class="columnText columnUsername"><a href="{link controller='UserEdit' id=$subscriptionUser->userID}{/link}" title="{lang}wcf.acp.user.edit{/lang}">{$subscriptionUser->username}</a></td>
100-
<td class="columnText columnSubscriptionTitle">{$subscriptionUser->title|phrase}</td>
101-
<td class="columnDate columnEndDate">{if $subscriptionUser->endDate}{@$subscriptionUser->endDate|time}{/if}</td>
102-
103-
{event name='columns'}
104-
</tr>
105-
{/foreach}
106-
</tbody>
107-
</table>
108-
109-
</div>
110-
111-
<footer class="contentFooter">
112-
{hascontent}
113-
<div class="paginationBottom">
114-
{content}{@$pagesLinks}{/content}
115-
</div>
116-
{/hascontent}
117-
118-
{hascontent}
119-
<nav class="contentFooterNavigation">
120-
<ul>
121-
{content}{event name='contentFooterNavigation'}{/content}
122-
</ul>
123-
</nav>
124-
{/hascontent}
125-
</footer>
126-
{else}
127-
<woltlab-core-notice type="info">{lang}wcf.global.noItems{/lang}</woltlab-core-notice>
128-
{/if}
17+
<div class="section">
18+
{unsafe:$gridView->render()}
19+
</div>
12920

13021
{include file='footer'}

wcfsetup/install/files/lib/acp/page/PaidSubscriptionUserListPage.class.php

Lines changed: 11 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,20 @@
22

33
namespace wcf\acp\page;
44

5-
use wcf\data\paid\subscription\user\PaidSubscriptionUserList;
6-
use wcf\page\SortablePage;
7-
use wcf\system\cache\builder\PaidSubscriptionCacheBuilder;
8-
use wcf\system\WCF;
9-
use wcf\util\StringUtil;
5+
use wcf\page\AbstractGridViewPage;
6+
use wcf\system\gridView\AbstractGridView;
7+
use wcf\system\gridView\admin\PaidSubscriptionUserGridView;
108

119
/**
1210
* Shows the list of paid subscription users.
1311
*
14-
* @author Marcel Werk
15-
* @copyright 2001-2019 WoltLab GmbH
16-
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12+
* @author Olaf Braun, Marcel Werk
13+
* @copyright 2001-2025 WoltLab GmbH
14+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
1715
*
18-
* @property PaidSubscriptionUserList $objectList
16+
* @property PaidSubscriptionUserGridView $gridView
1917
*/
20-
class PaidSubscriptionUserListPage extends SortablePage
18+
class PaidSubscriptionUserListPage extends AbstractGridViewPage
2119
{
2220
/**
2321
* @inheritDoc
@@ -34,104 +32,9 @@ class PaidSubscriptionUserListPage extends SortablePage
3432
*/
3533
public $neededPermissions = ['admin.paidSubscription.canManageSubscription'];
3634

37-
/**
38-
* @inheritDoc
39-
*/
40-
public $defaultSortField = 'username';
41-
42-
/**
43-
* @inheritDoc
44-
*/
45-
public $validSortFields = ['subscriptionUserID', 'username', 'subscriptionID', 'startDate', 'endDate'];
46-
47-
/**
48-
* @inheritDoc
49-
*/
50-
public $objectListClassName = PaidSubscriptionUserList::class;
51-
52-
/**
53-
* username
54-
* @var string
55-
*/
56-
public $username = '';
57-
58-
/**
59-
* subscription id
60-
* @var int
61-
*/
62-
public $subscriptionID = 0;
63-
64-
/**
65-
* @inheritDoc
66-
*/
67-
public function readParameters()
35+
#[\Override]
36+
protected function createGridViewController(): AbstractGridView
6837
{
69-
parent::readParameters();
70-
71-
if (isset($_REQUEST['username'])) {
72-
$this->username = StringUtil::trim($_REQUEST['username']);
73-
}
74-
if (isset($_REQUEST['subscriptionID'])) {
75-
$this->subscriptionID = \intval($_REQUEST['subscriptionID']);
76-
}
77-
}
78-
79-
/**
80-
* Initializes DatabaseObjectList instance.
81-
*/
82-
protected function initObjectList()
83-
{
84-
parent::initObjectList();
85-
86-
if ($this->username) {
87-
$this->objectList->getConditionBuilder()->add(
88-
'paid_subscription_user.userID IN (
89-
SELECT userID
90-
FROM wcf1_user
91-
WHERE username LIKE ?
92-
)',
93-
['%' . $this->username . '%']
94-
);
95-
}
96-
if ($this->subscriptionID) {
97-
$this->objectList->getConditionBuilder()->add(
98-
'paid_subscription_user.subscriptionID = ?',
99-
[$this->subscriptionID]
100-
);
101-
}
102-
103-
$this->objectList->getConditionBuilder()->add('paid_subscription_user.isActive = ?', [1]);
104-
$this->objectList->sqlSelects = 'user_table.username, paid_subscription.title';
105-
$this->objectList->sqlJoins = "
106-
LEFT JOIN wcf1_user user_table
107-
ON user_table.userID = paid_subscription_user.userID
108-
LEFT JOIN wcf1_paid_subscription paid_subscription
109-
ON paid_subscription.subscriptionID = paid_subscription_user.subscriptionID";
110-
}
111-
112-
/**
113-
* @inheritDoc
114-
*/
115-
protected function readObjects()
116-
{
117-
if ($this->sortField == 'username') {
118-
$this->sqlOrderBy = 'user_table.username ' . $this->sortOrder . ', paid_subscription_user.subscriptionUserID ' . $this->sortOrder;
119-
}
120-
121-
parent::readObjects();
122-
}
123-
124-
/**
125-
* @inheritDoc
126-
*/
127-
public function assignVariables()
128-
{
129-
parent::assignVariables();
130-
131-
WCF::getTPL()->assign([
132-
'username' => $this->username,
133-
'subscriptionID' => $this->subscriptionID,
134-
'availableSubscriptions' => PaidSubscriptionCacheBuilder::getInstance()->getData(),
135-
]);
38+
return new PaidSubscriptionUserGridView();
13639
}
13740
}

wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
186186
$event->register(new \wcf\system\endpoint\controller\core\languages\SetAsDefaultLanguage());
187187
$event->register(new \wcf\system\endpoint\controller\core\languages\items\DeleteItem());
188188
$event->register(new \wcf\system\endpoint\controller\core\labels\groups\DeleteGroup());
189+
$event->register(new \wcf\system\endpoint\controller\core\paid\subscriptions\users\DeleteSubscriptionUser());
189190
}
190191
);
191192

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace wcf\event\gridView\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\gridView\admin\PaidSubscriptionUserGridView;
7+
8+
/**
9+
* Indicates that the acp paid subscription user grid view has been initialized.
10+
*
11+
* @author Olaf Braun
12+
* @copyright 2001-2025 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
class PaidSubscriptionUserGridViewInitialized implements IPsr14Event
17+
{
18+
public function __construct(public readonly PaidSubscriptionUserGridView $gridView)
19+
{
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace wcf\event\interaction\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\interaction\admin\PaidSubscriptionUserInteractions;
7+
8+
/**
9+
* Indicates that the provider for paid subscription user interactions has been initialized.
10+
*
11+
* @author Olaf Braun
12+
* @copyright 2001-2025 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class PaidSubscriptionUserInteractionCollecting implements IPsr14Event
17+
{
18+
public function __construct(public readonly PaidSubscriptionUserInteractions $provider)
19+
{
20+
}
21+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\paid\subscriptions\users;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\paid\subscription\user\PaidSubscriptionUser;
9+
use wcf\data\paid\subscription\user\PaidSubscriptionUserAction;
10+
use wcf\http\Helper;
11+
use wcf\system\endpoint\DeleteRequest;
12+
use wcf\system\endpoint\IController;
13+
use wcf\system\exception\IllegalLinkException;
14+
use wcf\system\WCF;
15+
16+
/**
17+
* API endpoint for the deletion of paid subscriptions for users.
18+
*
19+
* @author Olaf Braun
20+
* @copyright 2001-2025 WoltLab GmbH
21+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
22+
* @since 6.2
23+
*/
24+
#[DeleteRequest('/core/paid/subscriptions/users/{id:\d+}')]
25+
final class DeleteSubscriptionUser implements IController
26+
{
27+
#[\Override]
28+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
29+
{
30+
$this->assertSubscriptionUserCanDeleted();
31+
32+
$user = Helper::fetchObjectFromRequestParameter($variables['id'], PaidSubscriptionUser::class);
33+
34+
(new PaidSubscriptionUserAction([$user], 'delete'))->executeAction();
35+
36+
return new JsonResponse([]);
37+
}
38+
39+
private function assertSubscriptionUserCanDeleted(): void
40+
{
41+
if (!\MODULE_PAID_SUBSCRIPTION) {
42+
throw new IllegalLinkException();
43+
}
44+
45+
WCF::getSession()->checkPermissions(['admin.paidSubscription.canManageSubscription']);
46+
}
47+
}

0 commit comments

Comments
 (0)