From 81221cd292f67e7d837440eef629727fd09f7b56 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Wed, 24 Dec 2025 15:20:03 +0100 Subject: [PATCH 1/2] Add support for grid view row links that open a form builder dialog rer https://www.woltlab.com/community/thread/315426-woltlab-suite-6-2-namen-von-texten-wieder-mit-einem-link-versehen/ --- com.woltlab.wcf/templates/shared_gridView.tpl | 4 +- .../gridView/AbstractGridView.class.php | 9 ++- .../AbstractGridViewRowLink.class.php | 36 ++++++++++ ...FormBuilderDialogGridViewRowLink.class.php | 65 +++++++++++++++++++ .../system/gridView/GridViewRowLink.class.php | 25 +++---- .../gridView/IGridViewRowLink.class.php | 31 +++++++++ .../admin/LanguageItemGridView.class.php | 23 +++---- 7 files changed, 156 insertions(+), 37 deletions(-) create mode 100644 wcfsetup/install/files/lib/system/gridView/AbstractGridViewRowLink.class.php create mode 100644 wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php create mode 100644 wcfsetup/install/files/lib/system/gridView/IGridViewRowLink.class.php diff --git a/com.woltlab.wcf/templates/shared_gridView.tpl b/com.woltlab.wcf/templates/shared_gridView.tpl index 909c8ec3803..81d682e16df 100644 --- a/com.woltlab.wcf/templates/shared_gridView.tpl +++ b/com.woltlab.wcf/templates/shared_gridView.tpl @@ -112,9 +112,7 @@ ); }); -{if $view->hasInteractions()} - {unsafe:$view->renderInteractionInitialization()} -{/if} +{unsafe:$view->renderInteractionInitialization()} {if $view->hasBulkInteractions()} {unsafe:$view->renderBulkInteractionInitialization()} {/if} diff --git a/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php b/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php index b296c42705c..eaed861c22c 100644 --- a/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php +++ b/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php @@ -52,7 +52,7 @@ abstract class AbstractGridView */ protected DatabaseObjectList $objectList; - private GridViewRowLink $rowLink; + private IGridViewRowLink $rowLink; private int $rowsPerPage = 20; private string $baseUrl = ''; private string $defaultSortField = ''; @@ -341,6 +341,11 @@ public function renderInteractionInitialization(): string )); } + if (isset($this->rowLink)) { + $code .= "\n"; + $code .= $this->rowLink->renderInitialization($this->getID() . '_table'); + } + return $code; } @@ -634,7 +639,7 @@ public function getParameters(): array /** * Adds the given row link to the grid view. */ - public function addRowLink(GridViewRowLink $rowLink): void + public function addRowLink(IGridViewRowLink $rowLink): void { $this->rowLink = $rowLink; } diff --git a/wcfsetup/install/files/lib/system/gridView/AbstractGridViewRowLink.class.php b/wcfsetup/install/files/lib/system/gridView/AbstractGridViewRowLink.class.php new file mode 100644 index 00000000000..e0c755d8ef3 --- /dev/null +++ b/wcfsetup/install/files/lib/system/gridView/AbstractGridViewRowLink.class.php @@ -0,0 +1,36 @@ + + * @since 6.2 + */ +abstract class AbstractGridViewRowLink implements IGridViewRowLink +{ + public function __construct( + protected readonly ?\Closure $isAvailableCallback = null, + ) {} + + #[\Override] + public function renderInitialization(string $containerId): ?string + { + return null; + } + + #[\Override] + public function isAvailable(DatabaseObject $row): bool + { + if ($this->isAvailableCallback === null) { + return true; + } + + return ($this->isAvailableCallback)($row); + } +} diff --git a/wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php b/wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php new file mode 100644 index 00000000000..701a221210b --- /dev/null +++ b/wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php @@ -0,0 +1,65 @@ + + * @since 6.2 + */ +class FormBuilderDialogGridViewRowLink extends AbstractGridViewRowLink +{ + public function __construct( + private readonly string $identifier, + private readonly string $endpoint, + private readonly InteractionEffect $interactionEffect = InteractionEffect::ReloadItem, + ?\Closure $isAvailableCallback = null, + ) { + parent::__construct($isAvailableCallback); + } + + #[\Override] + public function render(mixed $value, DatabaseObject $row, bool $isPrimaryColumn = false): string + { + $identifier = StringUtil::encodeJS($this->identifier); + $endpoint = StringUtil::encodeHTML( + \sprintf($this->endpoint, $row->getObjectID()) + ); + $tabindex = $isPrimaryColumn ? '0' : '-1'; + + return << + {$value} + + HTML; + } + + #[\Override] + public function renderInitialization(string $containerId): ?string + { + $identifier = StringUtil::encodeJS($this->identifier); + $containerId = StringUtil::encodeJS($containerId); + + return << + require(['WoltLabSuite/Core/Component/Interaction/FormBuilderDialog'], ({ setup }) => { + setup('{$identifier}', document.getElementById('{$containerId}')); + }); + + HTML; + } +} diff --git a/wcfsetup/install/files/lib/system/gridView/GridViewRowLink.class.php b/wcfsetup/install/files/lib/system/gridView/GridViewRowLink.class.php index 2342c0f08a4..8796319f659 100644 --- a/wcfsetup/install/files/lib/system/gridView/GridViewRowLink.class.php +++ b/wcfsetup/install/files/lib/system/gridView/GridViewRowLink.class.php @@ -9,14 +9,14 @@ use wcf\util\StringUtil; /** - * Represents a row link of a grid view. + * Represents a row link in a grid view that uses a link. * * @author Marcel Werk - * @copyright 2001-2024 WoltLab GmbH + * @copyright 2001-2025 WoltLab GmbH * @license GNU Lesser General Public License * @since 6.2 */ -class GridViewRowLink +class GridViewRowLink extends AbstractGridViewRowLink { /** * @param array $parameters @@ -26,12 +26,12 @@ public function __construct( private readonly array $parameters = [], private readonly string $cssClass = '', private readonly bool $isLinkableObject = false, - private readonly ?\Closure $isAvailableCallback = null - ) {} + ?\Closure $isAvailableCallback = null + ) { + parent::__construct($isAvailableCallback); + } - /** - * Renders the row link. - */ + #[\Override] public function render(mixed $value, DatabaseObject $row, bool $isPrimaryColumn = false): string { $href = ''; @@ -79,13 +79,4 @@ private function getLink(DatabaseObject $object): string throw new \BadMethodCallException("GridViewRowLink expects object to be an implementation of ILinkableObject."); } - - public function isAvailable(DatabaseObject $row): bool - { - if ($this->isAvailableCallback === null) { - return true; - } - - return ($this->isAvailableCallback)($row); - } } diff --git a/wcfsetup/install/files/lib/system/gridView/IGridViewRowLink.class.php b/wcfsetup/install/files/lib/system/gridView/IGridViewRowLink.class.php new file mode 100644 index 00000000000..1d1062f2016 --- /dev/null +++ b/wcfsetup/install/files/lib/system/gridView/IGridViewRowLink.class.php @@ -0,0 +1,31 @@ + + * @since 6.2 + */ +interface IGridViewRowLink +{ + /** + * Renders the row link. + */ + public function render(mixed $value, DatabaseObject $row, bool $isPrimaryColumn = false): string; + + /** + * Renders the initialization code for this row link. + */ + public function renderInitialization(string $containerId): ?string; + + /** + * Returns true if the row link is available for the given row. + */ + public function isAvailable(DatabaseObject $row): bool; +} diff --git a/wcfsetup/install/files/lib/system/gridView/admin/LanguageItemGridView.class.php b/wcfsetup/install/files/lib/system/gridView/admin/LanguageItemGridView.class.php index 088f5fa5a24..5fc78dd9587 100644 --- a/wcfsetup/install/files/lib/system/gridView/admin/LanguageItemGridView.class.php +++ b/wcfsetup/install/files/lib/system/gridView/admin/LanguageItemGridView.class.php @@ -8,16 +8,14 @@ use wcf\data\language\category\LanguageCategoryList; use wcf\data\language\item\LanguageItem; use wcf\data\language\item\LanguageItemList; -use wcf\data\language\Language; use wcf\data\language\LanguageList; use wcf\event\gridView\admin\LanguageItemGridViewInitialized; use wcf\system\gridView\AbstractGridView; +use wcf\system\gridView\FormBuilderDialogGridViewRowLink; use wcf\system\gridView\GridViewColumn; use wcf\system\gridView\renderer\AbstractColumnRenderer; use wcf\system\gridView\renderer\TruncatedTextColumnRenderer; use wcf\system\interaction\admin\LanguageItemInteractions; -use wcf\system\interaction\Divider; -use wcf\system\interaction\FormBuilderDialogInteraction; use wcf\system\request\LinkHandler; use wcf\system\view\filter\BooleanFilter; use wcf\system\view\filter\SelectFilter; @@ -127,19 +125,14 @@ public function applyFilter(DatabaseObjectList $list, string $value): void }, new BooleanFilter('isCustomLanguageItem', 'wcf.acp.language.item.isCustomLanguageItem'), ]); - $provider = new LanguageItemInteractions(); - $provider->addInteractions([ - new Divider(), - new FormBuilderDialogInteraction( - 'edit', - LinkHandler::getInstance()->getControllerLink( - LanguageItemEditAction::class, - ['id' => '%s'] - ), - 'wcf.global.button.edit' + $this->setInteractionProvider(new LanguageItemInteractions()); + $this->addRowLink(new FormBuilderDialogGridViewRowLink( + 'edit', + LinkHandler::getInstance()->getControllerLink( + LanguageItemEditAction::class, + ['id' => '%s'] ) - ]); - $this->setInteractionProvider($provider); + )); $this->setDefaultSortField('languageItem'); } From d0d6548c43a10be2952a79655f11d2b67f0b8f77 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Wed, 31 Dec 2025 13:35:58 +0100 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Alexander Ebert --- .../system/gridView/FormBuilderDialogGridViewRowLink.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php b/wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php index 701a221210b..02209870609 100644 --- a/wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php +++ b/wcfsetup/install/files/lib/system/gridView/FormBuilderDialogGridViewRowLink.class.php @@ -28,7 +28,7 @@ public function __construct( #[\Override] public function render(mixed $value, DatabaseObject $row, bool $isPrimaryColumn = false): string { - $identifier = StringUtil::encodeJS($this->identifier); + $identifier = StringUtil::encodeHTML($this->identifier); $endpoint = StringUtil::encodeHTML( \sprintf($this->endpoint, $row->getObjectID()) );