Skip to content

Commit c9e9a97

Browse files
committed
Migration user option list to grid view
1 parent f4d3e02 commit c9e9a97

File tree

12 files changed

+355
-132
lines changed

12 files changed

+355
-132
lines changed

wcfsetup/install/files/acp/templates/userOptionList.tpl

Lines changed: 2 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<header class="contentHeader">
44
<div class="contentHeaderTitle">
5-
<h1 class="contentTitle">{lang}wcf.acp.user.option.list{/lang} <span class="badge badgeInverse">{#$items}</span></h1>
5+
<h1 class="contentTitle">{lang}wcf.acp.user.option.list{/lang} <span class="badge badgeInverse">{#$gridView->countRows()}</span></h1>
66
</div>
77

88
<nav class="contentHeaderNavigation">
@@ -14,73 +14,6 @@
1414
</nav>
1515
</header>
1616

17-
{hascontent}
18-
<div class="paginationTop">
19-
{content}{pages print=true assign=pagesLinks controller="UserOptionList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content}
20-
</div>
21-
{/hascontent}
22-
23-
{if $objects|count}
24-
<div class="section tabularBox">
25-
<table class="table jsObjectActionContainer" data-object-action-class-name="wcf\data\user\option\UserOptionAction">
26-
<thead>
27-
<tr>
28-
<th class="columnID columnOptionID{if $sortField == 'optionID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=optionID&sortOrder={if $sortField == 'optionID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
29-
<th class="columnTitle columnOptionName{if $sortField == 'optionName'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=optionName&sortOrder={if $sortField == 'optionName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.name{/lang}</a></th>
30-
<th class="columnText columnCategoryName{if $sortField == 'categoryName'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=categoryName&sortOrder={if $sortField == 'categoryName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.category{/lang}</a></th>
31-
<th class="columnText columnOptionType{if $sortField == 'optionType'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=optionType&sortOrder={if $sortField == 'optionType' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.acp.user.option.optionType{/lang}</a></th>
32-
<th class="columnDigits columnShowOrder{if $sortField == 'showOrder'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=showOrder&sortOrder={if $sortField == 'showOrder' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.showOrder{/lang}</a></th>
33-
34-
{event name='columnHeads'}
35-
</tr>
36-
</thead>
37-
38-
<tbody class="jsReloadPageWhenEmpty">
39-
{foreach from=$objects item=option}
40-
<tr class="jsOptionRow jsObjectActionObject" data-object-id="{@$option->getObjectID()}">
41-
<td class="columnIcon">
42-
{objectAction action="toggle" isDisabled=$option->isDisabled}
43-
<a href="{link controller='UserOptionEdit' id=$option->optionID}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
44-
{if $option->canDelete()}
45-
{objectAction action="delete" objectTitle=$option->getTitle()}
46-
{else}
47-
<span class="disabled" title="{lang}wcf.global.button.delete{/lang}">
48-
{icon name='xmark'}
49-
</span>
50-
{/if}
51-
52-
{event name='rowButtons'}
53-
</td>
54-
<td class="columnID">{@$option->optionID}</td>
55-
<td class="columnTitle columnOptionName"><a href="{link controller='UserOptionEdit' id=$option->optionID}{/link}">{$option->getTitle()}</a></td>
56-
<td class="columnText columnCategoryName">{lang}wcf.user.option.category.{$option->categoryName}{/lang}</td>
57-
<td class="columnText columnOptionType">{$option->optionType}</td>
58-
<td class="columnDigits columnShowOrder">{#$option->showOrder}</td>
59-
60-
{event name='columns'}
61-
</tr>
62-
{/foreach}
63-
</tbody>
64-
</table>
65-
</div>
66-
67-
<footer class="contentFooter">
68-
{hascontent}
69-
<div class="paginationBottom">
70-
{content}{@$pagesLinks}{/content}
71-
</div>
72-
{/hascontent}
73-
74-
<nav class="contentFooterNavigation">
75-
<ul>
76-
<li><a href="{link controller='UserOptionAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.user.option.add{/lang}</span></a></li>
77-
78-
{event name='contentFooterNavigation'}
79-
</ul>
80-
</nav>
81-
</footer>
82-
{else}
83-
<woltlab-core-notice type="info">{lang}wcf.global.noItems{/lang}</woltlab-core-notice>
84-
{/if}
17+
{unsafe:$gridView->render()}
8518

8619
{include file='footer'}

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

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22

33
namespace wcf\acp\page;
44

5-
use wcf\data\user\option\UserOptionList;
6-
use wcf\page\SortablePage;
5+
use wcf\page\AbstractGridViewPage;
6+
use wcf\system\view\grid\AbstractGridView;
7+
use wcf\system\view\grid\UserOptionGridView;
78

89
/**
9-
* Shows a list of installed user options.
10+
* Shows a list of the installed user options.
1011
*
11-
* @author Marcel Werk
12-
* @copyright 2001-2019 WoltLab GmbH
13-
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12+
* @author Marcel Werk
13+
* @copyright 2001-2024 WoltLab GmbH
14+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
1415
*
15-
* @property UserOptionList $objectList
16+
* @property UserOptionGridView $gridView
1617
*/
17-
class UserOptionListPage extends SortablePage
18+
class UserOptionListPage extends AbstractGridViewPage
1819
{
1920
/**
2021
* @inheritDoc
@@ -26,35 +27,9 @@ class UserOptionListPage extends SortablePage
2627
*/
2728
public $neededPermissions = ['admin.user.canManageUserOption'];
2829

29-
/**
30-
* @inheritDoc
31-
*/
32-
public $defaultSortField = 'showOrder';
33-
34-
/**
35-
* @inheritDoc
36-
*/
37-
public $objectListClassName = UserOptionList::class;
38-
39-
/**
40-
* @inheritDoc
41-
*/
42-
public $validSortFields = ['optionID', 'optionName', 'categoryName', 'optionType', 'showOrder'];
43-
44-
/**
45-
* @inheritDoc
46-
*/
47-
protected function initObjectList()
30+
#[\Override]
31+
protected function createGridViewController(): AbstractGridView
4832
{
49-
parent::initObjectList();
50-
51-
$this->objectList->getConditionBuilder()->add(
52-
"option_table.categoryName IN (
53-
SELECT categoryName
54-
FROM wcf1_user_option_category
55-
WHERE parentCategoryName = ?
56-
)",
57-
['profile']
58-
);
33+
return new UserOptionGridView();
5934
}
6035
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
138138
$event->register(new \wcf\system\endpoint\controller\core\gridViews\GetRows);
139139
$event->register(new \wcf\system\endpoint\controller\core\messages\GetMentionSuggestions);
140140
$event->register(new \wcf\system\endpoint\controller\core\sessions\DeleteSession);
141+
$event->register(new \wcf\system\endpoint\controller\core\users\options\DeleteOption);
142+
$event->register(new \wcf\system\endpoint\controller\core\users\options\DisableOption);
143+
$event->register(new \wcf\system\endpoint\controller\core\users\options\EnableOption);
141144
$event->register(new \wcf\system\endpoint\controller\core\users\ranks\DeleteUserRank);
142145
}
143146
);

wcfsetup/install/files/lib/data/user/option/UserOptionAction.class.php

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
namespace wcf\data\user\option;
44

55
use wcf\data\AbstractDatabaseObjectAction;
6-
use wcf\data\IToggleAction;
7-
use wcf\data\TDatabaseObjectToggle;
8-
use wcf\system\exception\PermissionDeniedException;
96

107
/**
118
* Executes user option-related actions.
@@ -18,10 +15,8 @@
1815
* @method UserOptionEditor[] getObjects()
1916
* @method UserOptionEditor getSingleObject()
2017
*/
21-
class UserOptionAction extends AbstractDatabaseObjectAction implements IToggleAction
18+
class UserOptionAction extends AbstractDatabaseObjectAction
2219
{
23-
use TDatabaseObjectToggle;
24-
2520
/**
2621
* @inheritDoc
2722
*/
@@ -32,11 +27,6 @@ class UserOptionAction extends AbstractDatabaseObjectAction implements IToggleAc
3227
*/
3328
protected $permissionsCreate = ['admin.user.canManageUserOption'];
3429

35-
/**
36-
* @inheritDoc
37-
*/
38-
protected $permissionsDelete = ['admin.user.canManageUserOption'];
39-
4030
/**
4131
* @inheritDoc
4232
*/
@@ -45,19 +35,5 @@ class UserOptionAction extends AbstractDatabaseObjectAction implements IToggleAc
4535
/**
4636
* @inheritDoc
4737
*/
48-
protected $requireACP = ['create', 'delete', 'toggle', 'update'];
49-
50-
/**
51-
* @inheritDoc
52-
*/
53-
public function validateDelete()
54-
{
55-
parent::validateDelete();
56-
57-
foreach ($this->getObjects() as $userOption) {
58-
if (!$userOption->canDelete()) {
59-
throw new PermissionDeniedException();
60-
}
61-
}
62-
}
38+
protected $requireACP = ['create', 'update'];
6339
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace wcf\event\gridView;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\view\grid\UserOptionGridView;
7+
8+
/**
9+
* Indicates that the user option grid view has been initialized.
10+
*
11+
* @author Marcel Werk
12+
* @copyright 2001-2024 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class UserOptionGridViewInitialized implements IPsr14Event
17+
{
18+
public function __construct(public readonly UserOptionGridView $gridView) {}
19+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\users\options;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\user\option\UserOption;
9+
use wcf\http\Helper;
10+
use wcf\system\endpoint\DeleteRequest;
11+
use wcf\system\endpoint\IController;
12+
use wcf\system\exception\PermissionDeniedException;
13+
use wcf\system\WCF;
14+
15+
/**
16+
* API endpoint for deleting user options.
17+
*
18+
* @author Marcel Werk
19+
* @copyright 2001-2024 WoltLab GmbH
20+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
21+
* @since 6.2
22+
*/
23+
#[DeleteRequest('/core/users/options/{id:\d+}')]
24+
final class DeleteOption implements IController
25+
{
26+
#[\Override]
27+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
28+
{
29+
$option = Helper::fetchObjectFromRequestParameter($variables['id'], UserOption::class);
30+
31+
$this->assertOptionCanBeDeleted($option);
32+
33+
(new \wcf\system\user\option\command\DeleteOption($option))();
34+
35+
return new JsonResponse([]);
36+
}
37+
38+
private function assertOptionCanBeDeleted(UserOption $option): void
39+
{
40+
WCF::getSession()->checkPermissions(['admin.user.canManageUserOption']);
41+
42+
if (!$option->canDelete()) {
43+
throw new PermissionDeniedException();
44+
}
45+
}
46+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\users\options;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\user\option\UserOption;
9+
use wcf\http\Helper;
10+
use wcf\system\endpoint\IController;
11+
use wcf\system\endpoint\PostRequest;
12+
use wcf\system\WCF;
13+
14+
/**
15+
* API endpoint for disabling user options.
16+
*
17+
* @author Marcel Werk
18+
* @copyright 2001-2024 WoltLab GmbH
19+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
20+
* @since 6.2
21+
*/
22+
#[PostRequest('/core/users/options/{id:\d+}/disable')]
23+
final class DisableOption implements IController
24+
{
25+
#[\Override]
26+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
27+
{
28+
$option = Helper::fetchObjectFromRequestParameter($variables['id'], UserOption::class);
29+
30+
$this->assertOptionCanBeDisabled();
31+
32+
if (!$option->isDisabled) {
33+
(new \wcf\system\user\option\command\DisableOption($option))();
34+
}
35+
36+
return new JsonResponse([]);
37+
}
38+
39+
private function assertOptionCanBeDisabled(): void
40+
{
41+
WCF::getSession()->checkPermissions(['admin.user.canManageUserOption']);
42+
}
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\users\options;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\user\option\UserOption;
9+
use wcf\http\Helper;
10+
use wcf\system\endpoint\IController;
11+
use wcf\system\endpoint\PostRequest;
12+
use wcf\system\WCF;
13+
14+
/**
15+
* API endpoint for enabling user options.
16+
*
17+
* @author Marcel Werk
18+
* @copyright 2001-2024 WoltLab GmbH
19+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
20+
* @since 6.2
21+
*/
22+
#[PostRequest('/core/users/options/{id:\d+}/enable')]
23+
final class EnableOption implements IController
24+
{
25+
#[\Override]
26+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
27+
{
28+
$option = Helper::fetchObjectFromRequestParameter($variables['id'], UserOption::class);
29+
30+
$this->assertOptionCanBeEnabled();
31+
32+
if ($option->isDisabled) {
33+
(new \wcf\system\user\option\command\EnableOption($option))();
34+
}
35+
36+
return new JsonResponse([]);
37+
}
38+
39+
private function assertOptionCanBeEnabled(): void
40+
{
41+
WCF::getSession()->checkPermissions(['admin.user.canManageUserOption']);
42+
}
43+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace wcf\system\user\option\command;
4+
5+
use wcf\data\user\option\UserOption;
6+
use wcf\data\user\option\UserOptionAction;
7+
8+
/**
9+
* Deletes a user option.
10+
*
11+
* @author Marcel Werk
12+
* @copyright 2001-2024 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class DeleteOption
17+
{
18+
public function __construct(
19+
private readonly UserOption $option,
20+
) {}
21+
22+
public function __invoke(): void
23+
{
24+
$action = new UserOptionAction([$this->option], 'delete');
25+
$action->executeAction();
26+
}
27+
}

0 commit comments

Comments
 (0)