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
92 changes: 4 additions & 88 deletions wcfsetup/install/files/acp/templates/languageList.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

<nav class="contentHeaderNavigation">
Expand All @@ -15,92 +15,8 @@
</nav>
</header>

{hascontent}
<div class="paginationTop">
{content}{pages print=true assign=pagesLinks controller='LanguageList' link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content}
</div>
{/hascontent}

{if $objects|count}
<div id="userTableContainer" class="section tabularBox">
<table class="table jsObjectActionContainer" data-object-action-class-name="wcf\data\language\LanguageAction">
<thead>
<tr>
<th class="columnID columnLanguageID{if $sortField == 'languageID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='LanguageList'}pageNo={@$pageNo}&sortField=languageID&sortOrder={if $sortField == 'languageID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
<th class="columnTitle columnLanguageName{if $sortField == 'languageName'} active {@$sortOrder}{/if}"><a href="{link controller='LanguageList'}pageNo={@$pageNo}&sortField=languageName&sortOrder={if $sortField == 'languageName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.name{/lang}</a></th>
<th class="columnDigits columnUsers{if $sortField == 'users'} active {@$sortOrder}{/if}"><a href="{link controller='LanguageList'}pageNo={@$pageNo}&sortField=users&sortOrder={if $sortField == 'users' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.acp.language.users{/lang}</a></th>
<th class="columnDigits columnVariables{if $sortField == 'variables'} active {@$sortOrder}{/if}"><a href="{link controller='LanguageList'}pageNo={@$pageNo}&sortField=variables&sortOrder={if $sortField == 'variables' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.acp.language.variables{/lang}</a></th>
<th class="columnDigits columnCustomVariables{if $sortField == 'customVariables'} active {@$sortOrder}{/if}"><a href="{link controller='LanguageList'}pageNo={@$pageNo}&sortField=customVariables&sortOrder={if $sortField == 'customVariables' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.acp.language.customVariables{/lang}</a></th>

{event name='columnHeads'}
</tr>
</thead>

<tbody class="jsReloadPageWhenEmpty">
{foreach from=$objects item=language}
<tr class="jsLanguageRow jsObjectActionObject" data-object-id="{@$language->getObjectID()}">
<td class="columnIcon">
<a href="{link controller='LanguageExport' id=$language->languageID}{/link}" title="{lang}wcf.acp.language.export{/lang}" class="jsTooltip">{icon name='download'}</a>

{if !$language->isDefault}
{objectAction action="toggle" isDisabled=$language->isDisabled}
<button type="button" class="jsObjectAction jsTooltip" data-object-action="setAsDefault" data-object-action-success="reload" title="{lang}wcf.acp.language.setAsDefault{/lang}">
{icon name='circle-check'}
</button>
{else}
<span class="disabled" title="{lang}wcf.global.button.{if $language->isDisabled}enable{else}disable{/if}{/lang}">
{if $language->isDisabled}
{icon name='square'}
{else}
{icon name='square-check'}
{/if}
</span>
<span class="disabled" title="{lang}wcf.acp.language.setAsDefault{/lang}">
{icon name='circle-check'}
</span>
{/if}

<a href="{link controller='LanguageEdit' id=$language->languageID}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>

{if $language->isDeletable()}
{objectAction action="delete" objectTitle=$language->languageName}
{else}
<span class="disabled" title="{lang}wcf.global.button.delete{/lang}">
{icon name='xmark'}
</span>
{/if}

{event name='rowButtons'}
</td>
<td class="columnID columnLanguageID">{@$language->languageID}</td>
<td class="columnTitle columnLanguageName"><a href="{link controller='LanguageEdit' id=$language->languageID}{/link}">{$language->languageName} ({@$language->languageCode})</a></td>
<td class="columnDigits columnUsers">{#$language->users}</td>
<td class="columnDigits columnVariables"><a href="{link controller='LanguageItemList'}languageID={@$language->languageID}{/link}">{#$language->variables}</a></td>
<td class="columnDigits columnCustomVariables">{if $language->customVariables > 0}<a href="{link controller='LanguageItemList'}languageID={@$language->languageID}&hasCustomValue=1{/link}">{#$language->customVariables}</a>{else}{#$language->customVariables}{/if}</td>

{event name='columns'}
</tr>
{/foreach}
</tbody>
</table>
</div>

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

<nav class="contentFooterNavigation">
<ul>
<li><a href="{link controller='LanguageAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.language.add{/lang}</span></a></li>
<li><a href="{link controller='LanguageImport'}{/link}" class="button">{icon name='upload'} <span>{lang}wcf.acp.language.import{/lang}</span></a></li>

{event name='contentFooterNavigation'}
</ul>
</nav>
</footer>
{/if}
<div class="section">
{unsafe:$gridView->render()}
</div>

{include file='footer'}
66 changes: 11 additions & 55 deletions wcfsetup/install/files/lib/acp/page/LanguageListPage.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,34 @@

namespace wcf\acp\page;

use wcf\data\language\LanguageList;
use wcf\page\SortablePage;
use wcf\system\WCF;
use wcf\page\AbstractGridViewPage;
use wcf\system\gridView\AbstractGridView;
use wcf\system\gridView\admin\LanguageGridView;

/**
* Shows a list of all installed languages.
*
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @author Olaf Brau, Marcel Werk
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @property LanguageList $objectList
* @property LanguageGridView $gridView
*/
class LanguageListPage extends SortablePage
class LanguageListPage extends AbstractGridViewPage
{
/**
* @inheritDoc
*/
public $activeMenuItem = 'wcf.acp.menu.link.language.list';

/**
* @inheritDoc
*/
public $defaultSortField = 'languageName';

/**
* @inheritDoc
*/
public $neededPermissions = ['admin.language.canManageLanguage'];

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

/**
* @inheritDoc
*/
public $validSortFields = ['languageID', 'languageCode', 'languageName', 'users', 'variables', 'customVariables'];

/**
* @inheritDoc
*/
public function initObjectList()
#[\Override]
protected function createGridViewController(): AbstractGridView
{
parent::initObjectList();

$this->objectList->sqlSelects = "(
SELECT COUNT(*)
FROM wcf1_user user
WHERE languageID = language.languageID
) AS users, (
SELECT COUNT(*)
FROM wcf1_language_item
WHERE languageID = language.languageID
) AS variables, (
SELECT COUNT(*)
FROM wcf1_language_item
WHERE languageID = language.languageID
AND languageCustomItemValue IS NOT NULL
) AS customVariables";
}

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

WCF::getTPL()->assign([
'languages' => $this->objectList->getObjects(),
]);
return new LanguageGridView();
}
}
4 changes: 4 additions & 0 deletions wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
$event->register(new \wcf\system\endpoint\controller\core\bbcodes\media\providers\DisableProvider());
$event->register(new \wcf\system\endpoint\controller\core\bbcodes\media\providers\EnableProvider());
$event->register(new \wcf\system\endpoint\controller\core\bbCodes\DeleteBBCodes());
$event->register(new \wcf\system\endpoint\controller\core\languages\DisableLanguage());
$event->register(new \wcf\system\endpoint\controller\core\languages\DeleteLanguage());
$event->register(new \wcf\system\endpoint\controller\core\languages\EnableLanguage());
$event->register(new \wcf\system\endpoint\controller\core\languages\SetAsDefaultLanguage());
$event->register(new \wcf\system\endpoint\controller\core\languages\items\DeleteItem());
$event->register(new \wcf\system\endpoint\controller\core\labels\groups\DeleteGroup());
}
Expand Down
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\LanguageGridView;

/**
* Indicates that the language 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 LanguageGridViewInitialized implements IPsr14Event
{
public function __construct(public readonly LanguageGridView $gridView)
{
}
}
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\LanguageInteractions;

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

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

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\language\Language;
use wcf\data\language\LanguageAction;
use wcf\http\Helper;
use wcf\system\endpoint\DeleteRequest;
use wcf\system\endpoint\IController;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\language\LanguageFactory;
use wcf\system\WCF;

/**
* API endpoint for deleting languages.
*
* @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/languages/{id:\d+}')]
final class DeleteLanguage implements IController
{
#[\Override]
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
{
$language = Helper::fetchObjectFromRequestParameter($variables['id'], Language::class);

$this->assertLanguageCanBeDeleted($language);

(new LanguageAction([$language], 'delete'))->executeAction();

LanguageFactory::getInstance()->clearCache();
LanguageFactory::getInstance()->deleteLanguageCache();

return new JsonResponse([]);
}

private function assertLanguageCanBeDeleted(Language $language): void
{
WCF::getSession()->checkPermissions(['admin.language.canManageLanguage']);

if (!$language->isDeletable()) {
throw new PermissionDeniedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

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

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\language\Language;
use wcf\data\language\LanguageAction;
use wcf\http\Helper;
use wcf\system\endpoint\IController;
use wcf\system\endpoint\PostRequest;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;

/**
* API endpoint for disabling languages.
*
* @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/languages/{id:\d+}/disable')]
final class DisableLanguage implements IController
{
#[\Override]
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
{
$language = Helper::fetchObjectFromRequestParameter($variables['id'], Language::class);

$this->assertLanguageCanBeDisabled($language);

(new LanguageAction([$language], 'toggle'))->executeAction();

return new JsonResponse([]);
}

private function assertLanguageCanBeDisabled(Language $language): void
{
WCF::getSession()->checkPermissions(['admin.language.canManageLanguage']);

if ($language->isDefault) {
throw new PermissionDeniedException();
}

if ($language->isDisabled) {
throw new PermissionDeniedException();
}
}
}
Loading