diff --git a/src/Contao/Dca/Builder/Legacy/LegacyDcaDataDefinitionBuilder.php b/src/Contao/Dca/Builder/Legacy/LegacyDcaDataDefinitionBuilder.php
index 36707e751..efef53234 100644
--- a/src/Contao/Dca/Builder/Legacy/LegacyDcaDataDefinitionBuilder.php
+++ b/src/Contao/Dca/Builder/Legacy/LegacyDcaDataDefinitionBuilder.php
@@ -120,7 +120,6 @@
use function explode;
use function in_array;
use function is_array;
-use function is_callable;
use function next;
use function parse_str;
use function reset;
diff --git a/src/Contao/Picker/PagePickerProvider.php b/src/Contao/Picker/PagePickerProvider.php
index 35a7563ef..fce998447 100644
--- a/src/Contao/Picker/PagePickerProvider.php
+++ b/src/Contao/Picker/PagePickerProvider.php
@@ -67,7 +67,7 @@ public function __construct(
*/
public function getName()
{
- return 'ccaPagePicker';
+ return 'pagePicker';
}
/**
diff --git a/src/Contao/View/Contao2BackendView/ActionHandler/AbstractListShowAllHandler.php b/src/Contao/View/Contao2BackendView/ActionHandler/AbstractListShowAllHandler.php
index 008da09d2..fba145d39 100644
--- a/src/Contao/View/Contao2BackendView/ActionHandler/AbstractListShowAllHandler.php
+++ b/src/Contao/View/Contao2BackendView/ActionHandler/AbstractListShowAllHandler.php
@@ -76,6 +76,9 @@
use function array_key_exists;
use function implode;
+use function in_array;
+use function is_string;
+use function sprintf;
use function str_contains;
use function str_replace;
use function trigger_error;
@@ -154,7 +157,7 @@ public function __construct(
}
if (null === $tokenName) {
$tokenName = System::getContainer()->getParameter('contao.csrf_token_name');
- assert(\is_string($tokenName));
+ assert(is_string($tokenName));
// @codingStandardsIgnoreStart
@trigger_error(
@@ -264,7 +267,7 @@ protected function process(Action $action, EnvironmentInterface $environment)
*
* @return string
*/
- private function languageSwitcher(EnvironmentInterface $environment)
+ private function languageSwitcher(EnvironmentInterface $environment): string
{
$template = new ContaoBackendViewTemplate('dcbe_general_language_selector');
@@ -335,9 +338,9 @@ protected function translate($key, $domain, array $parameters = [])
$translated =
$this->translator->trans(
- \sprintf('%s.%s', $domain, $key),
+ sprintf('%s.%s', $domain, $key),
$parameters,
- \sprintf('contao_%s', $domain)
+ sprintf('contao_%s', $domain)
);
}
@@ -494,7 +497,7 @@ protected function loadCollection(EnvironmentInterface $environment)
*
* @return string
*/
- private function generateHeaderButtons(EnvironmentInterface $environment)
+ private function generateHeaderButtons(EnvironmentInterface $environment): string
{
return (new GlobalButtonRenderer($environment))->render();
}
@@ -512,7 +515,7 @@ private function renderCollection(
EnvironmentInterface $environment,
CollectionInterface $collection,
array $grouping
- ) {
+ ): void {
$definition = $environment->getDataDefinition();
assert($definition instanceof ContainerInterface);
@@ -578,7 +581,7 @@ private function addGroupHeader(
&$groupClass,
&$eoCount,
&$remoteCur = null
- ) {
+ ): void {
if ($grouping && GroupAndSortingInformationInterface::GROUP_NONE !== $grouping['mode']) {
$remoteNew = $this->renderGroupHeader(
$grouping['property'],
@@ -612,7 +615,7 @@ private function addGroupHeader(
*
* @return string When no information of panels can be obtained from the data container.
*/
- private function panel(EnvironmentInterface $environment, $ignoredPanels = [])
+ private function panel(EnvironmentInterface $environment, array $ignoredPanels = []): string
{
$view = $environment->getView();
assert($view instanceof BackendViewInterface);
@@ -627,7 +630,7 @@ private function panel(EnvironmentInterface $environment, $ignoredPanels = [])
*
* @return array
*/
- private function getTableHead(EnvironmentInterface $environment)
+ private function getTableHead(EnvironmentInterface $environment): array
{
$definition = $environment->getDataDefinition();
assert($definition instanceof ContainerInterface);
@@ -638,7 +641,7 @@ private function getTableHead(EnvironmentInterface $environment)
$columns = $this->getSortingColumns($sorting);
foreach ($formatter->getPropertyNames() as $field) {
$tableHead[] = [
- 'class' => 'tl_folder_tlist col_' . $field . (\in_array($field, $columns) ? ' ordered_by' : ''),
+ 'class' => 'tl_folder_tlist col_' . $field . (in_array($field, $columns) ? ' ordered_by' : ''),
'content' => $this->translateButtonLabel($field, $definition->getName())
];
}
@@ -666,12 +669,12 @@ private function getTableHead(EnvironmentInterface $environment)
* @SuppressWarnings(PHPMD.CamelCaseVariableName)
*/
private function renderGroupHeader(
- $field,
+ string $field,
ModelInterface $model,
- $groupMode,
- $groupLength,
+ string $groupMode,
+ int $groupLength,
EnvironmentInterface $environment
- ) {
+ ): ?string {
$definition = $environment->getDataDefinition();
assert($definition instanceof ContainerInterface);
@@ -716,7 +719,7 @@ protected function getSelectButtons(EnvironmentInterface $environment)
*
* @return bool
*/
- private function isSortable(EnvironmentInterface $environment)
+ private function isSortable(EnvironmentInterface $environment): bool
{
$definition = $environment->getDataDefinition();
assert($definition instanceof ContainerInterface);
@@ -751,7 +754,7 @@ protected function renderPasteTopButton(EnvironmentInterface $environment, $sort
assert($basicDefinition instanceof BasicDefinitionInterface);
$dataProvider = $basicDefinition->getDataProvider();
- assert(\is_string($dataProvider));
+ assert(is_string($dataProvider));
$filter->andModelIsFromProvider($dataProvider);
@@ -784,7 +787,7 @@ protected function renderPasteTopButton(EnvironmentInterface $environment, $sort
ContaoEvents::IMAGE_GET_HTML
);
- return \sprintf(
+ return sprintf(
'%s',
$urlEvent->getUrl(),
$this->translateButtonLabel('pastenew', $definition->getName()),
@@ -802,7 +805,7 @@ protected function renderPasteTopButton(EnvironmentInterface $environment, $sort
* @SuppressWarnings(PHPMD.Superglobals)
* @SuppressWarnings(PHPMD.CamelCaseVariableName)
*/
- private function breadcrumb(EnvironmentInterface $environment)
+ private function breadcrumb(EnvironmentInterface $environment): ?string
{
$event = new GetBreadcrumbEvent($environment);
@@ -830,7 +833,7 @@ private function breadcrumb(EnvironmentInterface $environment)
*
* @return array
*/
- private function getSortingColumns($sortingDefinition)
+ private function getSortingColumns(?GroupAndSortingDefinitionInterface $sortingDefinition): array
{
if (null === $sortingDefinition) {
return [];
@@ -855,7 +858,7 @@ private function getSortingColumns($sortingDefinition)
*
* @return array
*/
- private function getSelectContainer(EnvironmentInterface $environment)
+ private function getSelectContainer(EnvironmentInterface $environment): array
{
$inputProvider = $environment->getInputProvider();
assert($inputProvider instanceof InputProviderInterface);
@@ -892,7 +895,7 @@ private function getSelectContainer(EnvironmentInterface $environment)
*
* @return void
*/
- private function handleEditAllButton(CollectionInterface $collection, EnvironmentInterface $environment)
+ private function handleEditAllButton(CollectionInterface $collection, EnvironmentInterface $environment): void
{
if (0 < $collection->count()) {
return;
diff --git a/src/Contao/View/Contao2BackendView/ActionHandler/CopyHandler.php b/src/Contao/View/Contao2BackendView/ActionHandler/CopyHandler.php
index 754ef9d81..4b8669542 100644
--- a/src/Contao/View/Contao2BackendView/ActionHandler/CopyHandler.php
+++ b/src/Contao/View/Contao2BackendView/ActionHandler/CopyHandler.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general.
*
- * (c) 2013-2023 Contao Community Alliance.
+ * (c) 2013-2024 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,14 +17,13 @@
* @author Sven Baumann
* @author Richard Henkenjohann
* @author Ingolf Steinhardt
- * @copyright 2013-2023 Contao Community Alliance.
+ * @copyright 2013-2024 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/
namespace ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\ActionHandler;
-use Contao\System;
use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents;
use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\RedirectEvent;
use ContaoCommunityAlliance\Contao\Bindings\Events\System\LogEvent;
@@ -48,6 +47,8 @@
use ContaoCommunityAlliance\UrlBuilder\Contao\CsrfUrlBuilderFactory;
use ContaoCommunityAlliance\UrlBuilder\UrlBuilder;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Class CopyModelController handles copy action on a model.
@@ -65,19 +66,41 @@ class CopyHandler
*
* @var CsrfUrlBuilderFactory
*/
- private $securityUrlBuilder;
+ private CsrfUrlBuilderFactory $securityUrlBuilder;
+
+ /**
+ * The request stack.
+ *
+ * @var RequestStack
+ */
+ private RequestStack $requestStack;
+
+ /**
+ * The URL generator.
+ *
+ * @var UrlGeneratorInterface
+ */
+ private UrlGeneratorInterface $urlGenerator;
/**
* PasteHandler constructor.
*
* @param RequestScopeDeterminator $scopeDeterminator The request mode determinator.
* @param CsrfUrlBuilderFactory $securityUrlBuilder The URL builder factory for URLs with security token.
+ * @param RequestStack $requestStack The request stack.
+ * @param UrlGeneratorInterface $urlGenerator The URL generator.
*/
- public function __construct(RequestScopeDeterminator $scopeDeterminator, CsrfUrlBuilderFactory $securityUrlBuilder)
- {
+ public function __construct(
+ RequestScopeDeterminator $scopeDeterminator,
+ CsrfUrlBuilderFactory $securityUrlBuilder,
+ RequestStack $requestStack,
+ UrlGeneratorInterface $urlGenerator,
+ ) {
$this->setScopeDeterminator($scopeDeterminator);
$this->securityUrlBuilder = $securityUrlBuilder;
+ $this->requestStack = $requestStack;
+ $this->urlGenerator = $urlGenerator;
}
/**
@@ -230,24 +253,38 @@ protected function redirect($environment, $copiedModelId)
return;
}
- // Build a clean url to remove the copy related arguments instead of using the AddToUrlEvent.
- $urlBuilder = new UrlBuilder();
- $urlBuilder
- ->setPath('contao')
- ->setQueryParameter('do', $inputProvider->getParameter('do'))
- ->setQueryParameter('table', $copiedModelId->getDataProviderName())
- ->setQueryParameter('act', 'edit')
- ->setQueryParameter('id', $copiedModelId->getSerialized());
- if (null !== ($pid = $inputProvider->getParameter('pid'))) {
- $urlBuilder->setQueryParameter('pid', $pid);
- }
-
- $redirectEvent = new RedirectEvent($this->securityUrlBuilder->create($urlBuilder->getUrl())->getUrl());
-
if (null === ($dispatcher = $environment->getEventDispatcher())) {
return;
}
+ $request = $this->requestStack->getCurrentRequest();
+ $routeName = $request?->attributes->get('_route');
+ // Build a clean url to remove the copy related arguments instead of using the AddToUrlEvent.
+ $urlBuilder = new UrlBuilder();
+ if ($routeName !== 'contao.backend') {
+ $params = [
+ 'table' => $copiedModelId->getDataProviderName(),
+ 'act' => 'edit',
+ 'id' => $copiedModelId->getSerialized(),
+ ];
+ if (null !== ($pid = $inputProvider->getParameter('pid'))) {
+ $params['pid'] = $pid;
+ }
+ $url = $this->urlGenerator->generate($routeName, $params);
+ } else {
+ $urlBuilder
+ ->setPath('contao')
+ ->setQueryParameter('do', $inputProvider->getParameter('do'))
+ ->setQueryParameter('table', $copiedModelId->getDataProviderName())
+ ->setQueryParameter('act', 'edit')
+ ->setQueryParameter('id', $copiedModelId->getSerialized());
+ if (null !== ($pid = $inputProvider->getParameter('pid'))) {
+ $urlBuilder->setQueryParameter('pid', $pid);
+ }
+ $url = $urlBuilder->getUrl();
+ }
+ $redirectEvent = new RedirectEvent($this->securityUrlBuilder->create($url)->getUrl());
+
$dispatcher->dispatch($redirectEvent, ContaoEvents::CONTROLLER_REDIRECT);
}
@@ -308,7 +345,7 @@ protected function process(EnvironmentInterface $environment)
*
* @return string|bool
*/
- private function checkPermission(EnvironmentInterface $environment)
+ private function checkPermission(EnvironmentInterface $environment): bool|string
{
if (null === ($definition = $environment->getDataDefinition())) {
return false;
diff --git a/src/Contao/View/Contao2BackendView/ActionHandler/MultipleHandler/SelectPropertyAllHandler.php b/src/Contao/View/Contao2BackendView/ActionHandler/MultipleHandler/SelectPropertyAllHandler.php
index 38c8a5e40..f55073eb5 100644
--- a/src/Contao/View/Contao2BackendView/ActionHandler/MultipleHandler/SelectPropertyAllHandler.php
+++ b/src/Contao/View/Contao2BackendView/ActionHandler/MultipleHandler/SelectPropertyAllHandler.php
@@ -194,11 +194,11 @@ private function getCollection(
$model->setID($property->getName());
$model->setProperty(
'name',
- $property->getLabel() ?: $property->getName()
+ $this->translator->trans($property->getLabel(), [], $definition->getName())
);
$model->setProperty(
'description',
- $property->getDescription() ?: $property->getName()
+ $this->translator->trans($property->getDescription(), [], $definition->getName())
);
$this->handlePropertyFileTree($property);
diff --git a/src/Contao/View/Contao2BackendView/ActionHandler/SelectHandler.php b/src/Contao/View/Contao2BackendView/ActionHandler/SelectHandler.php
index a4359aa33..58338f517 100644
--- a/src/Contao/View/Contao2BackendView/ActionHandler/SelectHandler.php
+++ b/src/Contao/View/Contao2BackendView/ActionHandler/SelectHandler.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general.
*
- * (c) 2013-2023 Contao Community Alliance.
+ * (c) 2013-2024 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -16,7 +16,7 @@
* @author Stefan Heimes
* @author Sven Baumann
* @author Ingolf Steinhardt
- * @copyright 2013-2023 Contao Community Alliance.
+ * @copyright 2013-2024 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/
@@ -617,6 +617,9 @@ private function getSelectCollection(EnvironmentInterface $environment)
foreach (($session['models'] ?? []) as $modelId) {
$modelIds[] = ModelId::fromSerialized($modelId)->getId();
}
+ if ([] === $modelIds) {
+ return $dataProvider->getEmptyCollection();
+ }
$idProperty = method_exists($dataProvider, 'getIdProperty') ? $dataProvider->getIdProperty() : 'id';
$collection = $dataProvider->fetchAll(
diff --git a/src/Contao/View/Contao2BackendView/ButtonRenderer.php b/src/Contao/View/Contao2BackendView/ButtonRenderer.php
index 0a853704a..79084b3cc 100644
--- a/src/Contao/View/Contao2BackendView/ButtonRenderer.php
+++ b/src/Contao/View/Contao2BackendView/ButtonRenderer.php
@@ -325,10 +325,12 @@ private function hasPasteNewButton()
private function buildCommand($command, $model, $previous, $next, $isCircularReference, $childIds)
{
$extra = (array) $command->getExtra();
- $attributes = '';
-
- if (!empty($extra['attributes'])) {
- $attributes .= sprintf($extra['attributes'], $model->getID());
+ if ('' !== ($attributes = $extra['attributes'] ?? '')) {
+ // BC compatibility with legacy strings containing 'Edit item %s'
+ if (!str_contains($attributes, '%id%')) {
+ $attributes = sprintf($attributes, $model->getID());
+ }
+ $attributes = strtr($attributes, ['%id%' => $model->getId()]);
}
$icon = $extra['icon'];
diff --git a/src/Contao/View/Contao2BackendView/Controller/ClipboardController.php b/src/Contao/View/Contao2BackendView/Controller/ClipboardController.php
index b393ee960..13060bb0d 100644
--- a/src/Contao/View/Contao2BackendView/Controller/ClipboardController.php
+++ b/src/Contao/View/Contao2BackendView/Controller/ClipboardController.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general.
*
- * (c) 2013-2023 Contao Community Alliance.
+ * (c) 2013-2024 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,7 +17,7 @@
* @author Stefan Heimes
* @author Sven Baumann
* @author Ingolf Steinhardt
- * @copyright 2013-2023 Contao Community Alliance.
+ * @copyright 2013-2024 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/
@@ -46,9 +46,16 @@
use ContaoCommunityAlliance\DcGeneral\Event\ViewEvent;
use ContaoCommunityAlliance\DcGeneral\InputProviderInterface;
use ContaoCommunityAlliance\Translator\TranslatorInterface;
+use ContaoCommunityAlliance\UrlBuilder\UrlBuilder;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use function array_shift;
+use function in_array;
+use function is_string;
+use function parse_str;
+use function sprintf;
+
/**
* Class ClipboardController.
*
@@ -61,7 +68,7 @@ class ClipboardController implements EventSubscriberInterface
*
* @var RequestScopeDeterminator
*/
- private $scopeDeterminator;
+ private RequestScopeDeterminator $scopeDeterminator;
/**
* ClipboardController constructor.
@@ -143,7 +150,7 @@ private function checkPermission(ActionEvent $event)
if (
(('create' === $actionName) && (true === $basicDefinition->isCreatable()))
|| (('cut' === $actionName) && (true === $basicDefinition->isEditable()))
- || (false === \in_array($actionName, ['create', 'cut']))
+ || (false === in_array($actionName, ['create', 'cut']))
) {
return true;
}
@@ -162,7 +169,7 @@ private function checkPermission(ActionEvent $event)
}
$event->setResponse(
- \sprintf(
+ sprintf(
'%s.
',
$permissionMessage
)
@@ -206,7 +213,15 @@ private function clearClipboard(ActionEvent $event, $redirect = true)
$addToUrlEvent = new AddToUrlEvent('clipboard-item=&original-act=&act=' . $input->getParameter('original-act'));
$eventDispatcher->dispatch($addToUrlEvent, ContaoEvents::BACKEND_ADD_TO_URL);
- $redirectEvent = new RedirectEvent($addToUrlEvent->getUrl());
+ $url = new UrlBuilder($addToUrlEvent->getUrl());
+ parse_str($url->getQueryString(), $parameters);
+ foreach ($parameters as $name => $value) {
+ if ('' === $value) {
+ $url->unsetQueryParameter($name);
+ }
+ }
+
+ $redirectEvent = new RedirectEvent($url->getUrl());
$eventDispatcher->dispatch($redirectEvent, ContaoEvents::CONTROLLER_REDIRECT);
}
@@ -272,11 +287,11 @@ private function addToClipboard(ActionEvent $event)
assert($definition instanceof ContainerInterface);
$providerName = $definition->getBasicDefinition()->getDataProvider();
- assert(\is_string($providerName));
+ assert(is_string($providerName));
- $item = new UnsavedItem($clipboardActionName, $parentId, $providerName);
+ $item = new UnsavedItem($clipboardActionName, $parentId, $providerName);
- // Remove other create items, there can only be one create item in the clipboard or many others
+ // Remove other create items, there can only be one create item in the clipboard or many others.
$clipboard->clear();
} else {
$modelIdRaw = $input->getParameter('source');
@@ -358,7 +373,7 @@ public function handleView(ViewEvent $event)
$basicDefinition = $definition->getBasicDefinition();
$dataProvider = $basicDefinition->getDataProvider();
- assert(\is_string($dataProvider));
+ assert(is_string($dataProvider));
$filter = new Filter();
$filter->andModelIsFromProvider($dataProvider);
@@ -390,7 +405,7 @@ public function handleView(ViewEvent $event)
$formatModelLabel = new FormatModelLabelEvent($environment, $model);
$eventDispatcher->dispatch($formatModelLabel, DcGeneralEvents::FORMAT_MODEL_LABEL);
$label = $formatModelLabel->getLabel();
- $label = \array_shift($label);
+ $label = array_shift($label);
$label = $label['content'];
} else {
$model = $dataProvider->getEmptyModel();
@@ -398,7 +413,7 @@ public function handleView(ViewEvent $event)
$translator = $environment->getTranslator();
assert($translator instanceof TranslatorInterface);
- $label = $translator->translate('new.0', $item->getDataProviderName());
+ $label = $translator->translate('new.label', $item->getDataProviderName());
}
$options[$item->getClipboardId()] = ['item' => $item, 'model' => $model, 'label' => $label];
diff --git a/src/Contao/View/Contao2BackendView/EventListener/ColorPickerWizardListener.php b/src/Contao/View/Contao2BackendView/EventListener/ColorPickerWizardListener.php
index b67b598da..0d7d68329 100644
--- a/src/Contao/View/Contao2BackendView/EventListener/ColorPickerWizardListener.php
+++ b/src/Contao/View/Contao2BackendView/EventListener/ColorPickerWizardListener.php
@@ -95,7 +95,7 @@ public static function getWizard($propInfo, EnvironmentInterface $environment)
assert($translator instanceof TranslatorInterface);
if (\array_key_exists('colorpicker', $propExtra) && $propExtra['colorpicker']) {
- $pickerText = $translator->translate('colorpicker', 'dc-general');
+ $pickerText = $translator->translate('colorPicker', 'dc-general');
$event = new GenerateHtmlEvent(
'pickcolor.svg',
$pickerText,
diff --git a/src/Contao/View/Contao2BackendView/FileSelect.php b/src/Contao/View/Contao2BackendView/FileSelect.php
index b3bd27c9d..76b2a928e 100644
--- a/src/Contao/View/Contao2BackendView/FileSelect.php
+++ b/src/Contao/View/Contao2BackendView/FileSelect.php
@@ -362,7 +362,7 @@ private function setupItemContainer(ModelIdInterface $modelId)
}
/**
- * Run the ajax request if is determine for run.
+ * Run the ajax request if it is determining for run.
*
* @SuppressWarnings(PHPMD.Superglobals)
*
diff --git a/src/Contao/View/Contao2BackendView/GlobalButtonRenderer.php b/src/Contao/View/Contao2BackendView/GlobalButtonRenderer.php
index a45ed0cf6..d911ffa63 100644
--- a/src/Contao/View/Contao2BackendView/GlobalButtonRenderer.php
+++ b/src/Contao/View/Contao2BackendView/GlobalButtonRenderer.php
@@ -146,7 +146,7 @@ private function renderButton(CommandInterface $command)
$buttonEvent
->setAccessKey(isset($extra['accesskey']) ? \trim($extra['accesskey']) : '')
->setAttributes(' ' . \ltrim($extra['attributes'] ?? ''))
- ->setClass($extra['class'])
+ ->setClass($extra['class'] ?? '')
->setKey($command->getName())
->setHref($href)
->setLabel($label)
diff --git a/src/Contao/View/Contao2BackendView/Subscriber/CheckPermission.php b/src/Contao/View/Contao2BackendView/Subscriber/CheckPermission.php
index 89011350a..6622be542 100644
--- a/src/Contao/View/Contao2BackendView/Subscriber/CheckPermission.php
+++ b/src/Contao/View/Contao2BackendView/Subscriber/CheckPermission.php
@@ -21,6 +21,7 @@
namespace ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Subscriber;
+use Contao\CoreBundle\Security\ContaoCorePermissions;
use ContaoCommunityAlliance\DcGeneral\Contao\DataDefinition\Definition\Contao2BackendViewDefinitionInterface;
use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator;
use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\View\CommandCollectionInterface;
@@ -30,6 +31,7 @@
use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\PropertyInterface;
use ContaoCommunityAlliance\DcGeneral\Factory\Event\BuildDataDefinitionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\Security\Core\Security;
/**
* The check permission subscriber.
@@ -48,7 +50,10 @@ class CheckPermission implements EventSubscriberInterface
*
* @param RequestScopeDeterminator $scopeDeterminator
*/
- public function __construct(RequestScopeDeterminator $scopeDeterminator)
+ public function __construct(
+ RequestScopeDeterminator $scopeDeterminator,
+ private Security $security
+ )
{
$this->scopeDeterminator = $scopeDeterminator;
}
@@ -84,6 +89,7 @@ public function checkPermissionForProperties(BuildDataDefinitionEvent $event)
$container = $event->getContainer();
$properties = $container->getPropertiesDefinition();
$palettesDefinition = $container->getPalettesDefinition();
+ $definitionName = $container->getName();
foreach ($palettesDefinition->getPalettes() as $palette) {
foreach ($palette->getProperties() as $property) {
@@ -100,10 +106,15 @@ public function checkPermissionForProperties(BuildDataDefinitionEvent $event)
// @codingStandardsIgnoreEnd
continue;
}
+ $excluded = $properties->getProperty($name)->isExcluded();
+ // Include all excluded fields which are allowed for the current user
+ if ($excluded && $this->security->isGranted(ContaoCorePermissions::USER_CAN_EDIT_FIELD_OF_TABLE, $definitionName . '::' . $name)) {
+ $excluded = false;
+ }
$this
->getVisibilityConditionChain($property)
- ->addCondition(new BooleanCondition(!$properties->getProperty($name)->isExcluded()));
+ ->addCondition(new BooleanCondition(!$excluded));
}
}
}
diff --git a/src/Contao/View/Contao2BackendView/Subscriber/WidgetBuilder.php b/src/Contao/View/Contao2BackendView/Subscriber/WidgetBuilder.php
index ea4617d7c..a3303beec 100644
--- a/src/Contao/View/Contao2BackendView/Subscriber/WidgetBuilder.php
+++ b/src/Contao/View/Contao2BackendView/Subscriber/WidgetBuilder.php
@@ -547,12 +547,18 @@ private function prepareWidgetAttributes(ModelInterface $model, PropertyInterfac
$propExtra = $this->setPropExtraDisabled($property, $propExtra);
+ // If no description present, pass as string instead of array.
+ $label = $this->translator->trans($property->getLabel(), [], $defName);
+ if ('' !== $description = $property->getDescription()) {
+ $label = [
+ $label,
+ $this->translator->trans($description, [], $defName),
+ ];
+ }
+
$widgetConfig = [
'inputType' => $property->getWidgetType(),
- 'label' => [
- $this->translator->trans($property->getLabel(), [], $defName),
- $this->translator->trans($property->getDescription(), [], $defName),
- ],
+ 'label' => $label,
'options' => $this->getOptionsForWidget($property, $model),
'eval' => $propExtra,
];
diff --git a/src/Contao/View/Contao2BackendView/ViewHelpers.php b/src/Contao/View/Contao2BackendView/ViewHelpers.php
index ac64737ee..3395cf806 100644
--- a/src/Contao/View/Contao2BackendView/ViewHelpers.php
+++ b/src/Contao/View/Contao2BackendView/ViewHelpers.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general.
*
- * (c) 2013-2023 Contao Community Alliance.
+ * (c) 2013-2024 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,13 +17,14 @@
* @author Stefan Heimes
* @author Sven Baumann
* @author Ingolf Steinhardt
- * @copyright 2013-2023 Contao Community Alliance.
+ * @copyright 2013-2024 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/
namespace ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView;
+use Contao\System;
use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents;
use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\RedirectEvent;
use ContaoCommunityAlliance\DcGeneral\Contao\DataDefinition\Definition\Contao2BackendViewDefinitionInterface;
@@ -40,7 +41,14 @@
use ContaoCommunityAlliance\DcGeneral\Panel\PanelInterface;
use ContaoCommunityAlliance\DcGeneral\Panel\SortElementInterface;
use ContaoCommunityAlliance\DcGeneral\View\Event\RenderReadablePropertyValueEvent;
+use LogicException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+
+use function sprintf;
+use function strtoupper;
/**
* Helper class that provides static methods used in views.
@@ -157,7 +165,7 @@ public static function initializeSorting($panel, $dataConfig, $listingConfig)
$newSorting = [];
foreach ($listingConfig->getGroupAndSortingDefinition()->getDefault() as $information) {
/** @var GroupAndSortingInformationInterface $information */
- $newSorting[$information->getProperty()] = \strtoupper($information->getSortingMode());
+ $newSorting[$information->getProperty()] = strtoupper($information->getSortingMode());
}
$dataConfig->setSorting($newSorting);
}
@@ -240,44 +248,75 @@ public static function getReadableFieldValue(
*
* @param EnvironmentInterface $environment The environment.
*
- * @return void
+ * @return never
*/
- public static function redirectHome(EnvironmentInterface $environment)
+ public static function redirectHome(EnvironmentInterface $environment): never
{
$input = $environment->getInputProvider();
assert($input instanceof InputProviderInterface);
+ $request = self::getRequest();
+ $routeName = $request->attributes->get('_route');
+ if ($routeName !== 'contao.backend') {
+ self::determineNewStyleRedirect($routeName, $request, $environment);
+ }
+
if ($input->hasParameter('table')) {
if ($input->hasParameter('pid')) {
$event = new RedirectEvent(
- \sprintf(
+ sprintf(
'contao?do=%s&table=%s&pid=%s',
$input->getParameter('do'),
$input->getParameter('table'),
$input->getParameter('pid')
)
);
- } else {
- $event = new RedirectEvent(
- \sprintf(
- 'contao?do=%s&table=%s',
- $input->getParameter('do'),
- $input->getParameter('table')
- )
- );
+ self::dispatchRedirect($environment, $event);
}
- } else {
$event = new RedirectEvent(
- \sprintf(
- 'contao?do=%s',
- $input->getParameter('do')
+ sprintf(
+ 'contao?do=%s&table=%s',
+ $input->getParameter('do'),
+ $input->getParameter('table')
)
);
+ self::dispatchRedirect($environment, $event);
}
+ $event = new RedirectEvent(sprintf('contao?do=%s', $input->getParameter('do')));
+
+ self::dispatchRedirect($environment, $event);
+ }
+ private static function determineNewStyleRedirect(
+ string $routeName,
+ Request $request,
+ EnvironmentInterface $environment
+ ): never
+ {
+ $routeGenerator = System::getContainer()->get('router');
+ assert($routeGenerator instanceof UrlGeneratorInterface);
+ $parameters = $request->query->all();
+ unset($parameters['act']);
+ $routeBase = $routeGenerator->generate($routeName, $parameters);
+
+ self::dispatchRedirect($environment, new RedirectEvent($routeBase));
+ }
+
+ private static function getRequest(): Request
+ {
+ $requestStack = System::getContainer()->get('request_stack');
+ assert($requestStack instanceof RequestStack);
+
+ return $requestStack->getCurrentRequest();
+ }
+
+ public static function dispatchRedirect(EnvironmentInterface $environment, RedirectEvent $event): never
+ {
$dispatcher = $environment->getEventDispatcher();
assert($dispatcher instanceof EventDispatcherInterface);
$dispatcher->dispatch($event, ContaoEvents::CONTROLLER_REDIRECT);
+
+ throw new LogicException('Redirect did not happen.');
}
}
diff --git a/src/DataDefinition/Definition/View/BackCommand.php b/src/DataDefinition/Definition/View/BackCommand.php
index e64d04689..6faa5ac23 100644
--- a/src/DataDefinition/Definition/View/BackCommand.php
+++ b/src/DataDefinition/Definition/View/BackCommand.php
@@ -31,7 +31,7 @@ class BackCommand extends Command
public function __construct()
{
parent::__construct();
- $this->extra['class'] = 'header_back';
+ $this->extra['class'] = 'header_back dcgBC';
$this->extra['accesskey'] = 'b';
$this->extra['attributes'] = 'onclick="Backend.getScrollOffset();"';
$this
diff --git a/src/DataDefinition/Definition/View/CreateModelCommand.php b/src/DataDefinition/Definition/View/CreateModelCommand.php
index f66c6f5fd..9fad2c4f6 100644
--- a/src/DataDefinition/Definition/View/CreateModelCommand.php
+++ b/src/DataDefinition/Definition/View/CreateModelCommand.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general.
*
- * (c) 2013-2019 Contao Community Alliance.
+ * (c) 2013-2024 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -13,7 +13,8 @@
* @package contao-community-alliance/dc-general
* @author Christian Schiffler
* @author Sven Baumann
- * @copyright 2013-2019 Contao Community Alliance.
+ * @author Ingolf Steinhardt
+ * @copyright 2013-2024 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general/blob/master/LICENSE LGPL-3.0-or-later
* @filesource
*/
@@ -36,8 +37,8 @@ public function __construct()
$this->extra['attributes'] = 'onclick="Backend.getScrollOffset();"';
$this
->setName('button_new')
- ->setLabel('new.0')
- ->setDescription('new.1');
+ ->setLabel('new.label')
+ ->setDescription('new.description');
$this->parameters['act'] = 'create';
}
}
diff --git a/src/EventListener/StoreRefererListener.php b/src/EventListener/StoreRefererListener.php
new file mode 100644
index 000000000..1b57b72a7
--- /dev/null
+++ b/src/EventListener/StoreRefererListener.php
@@ -0,0 +1,132 @@
+
+ * @author Ingolf Steinhardt
+ * @copyright 2013-2024 Contao Community Alliance.
+ * @license https://github.com/contao-community-alliance/dc-general/blob/master/LICENSE LGPL-3.0-or-later
+ * @filesource
+ */
+
+declare(strict_types=1);
+
+namespace ContaoCommunityAlliance\DcGeneral\EventListener;
+
+use Contao\CoreBundle\Routing\ScopeMatcher;
+use Contao\User;
+use RuntimeException;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\ResponseEvent;
+use Symfony\Component\Security\Core\Security;
+
+use function array_merge;
+use function array_shift;
+use function count;
+use function is_array;
+use function strlen;
+
+/**
+ * @internal
+ */
+class StoreRefererListener
+{
+ public function __construct(
+ private readonly Security $security,
+ private readonly ScopeMatcher $scopeMatcher
+ ) {
+ }
+
+ /**
+ * Stores the referer in the session.
+ */
+ public function __invoke(ResponseEvent $event): void
+ {
+ if (!$this->scopeMatcher->isBackendMainRequest($event)) {
+ return;
+ }
+
+ $request = $event->getRequest();
+ if (!$request->isMethod(Request::METHOD_GET)) {
+ return;
+ }
+
+ $response = $event->getResponse();
+ if (200 !== $response->getStatusCode()) {
+ return;
+ }
+
+ $user = $this->security->getUser();
+ if (!$user instanceof User) {
+ return;
+ }
+
+ if (!$this->canModifyBackendSession($request)) {
+ return;
+ }
+
+ if (!$request->hasSession()) {
+ throw new RuntimeException('The request did not contain a session.');
+ }
+
+ $session = $request->getSession();
+ $key = $request->query->has('popup') ? 'popupReferer' : 'referer';
+ $refererId = $request->attributes->get('_contao_referer_id');
+ $referers = $this->prepareBackendReferer($refererId, $session->get($key));
+ $ref = $request->query->get('ref', '');
+
+ // Move current to last if the referer is in both the URL and the session.
+ if ('' !== $ref && isset($referers[$ref])) {
+ $referers[$refererId] = array_merge($referers[$ref], $referers[$refererId]);
+ $referers[$refererId]['last'] = $referers[$ref]['current'];
+ }
+
+ // Set new current referer
+ $referers[$refererId]['current'] = $this->getRelativeRequestUri($request);
+
+ $session->set($key, $referers);
+ }
+
+ private function canModifyBackendSession(Request $request): bool
+ {
+ return true === $request->attributes->get('_dcg_referer_update') && !$request->isXmlHttpRequest();
+ }
+
+ /**
+ * @return array>
+ */
+ private function prepareBackendReferer(string $refererId, array $referers = null): array
+ {
+ if (!is_array($referers)) {
+ $referers = [];
+ }
+
+ if (!isset($referers[$refererId]) || !is_array($referers[$refererId])) {
+ $referers[$refererId] = end($referers) ?: ['last' => ''];
+ }
+
+ // Make sure we never have more than 25 different referer URLs
+ while (count($referers) >= 25) {
+ array_shift($referers);
+ }
+
+ return $referers;
+ }
+
+ /**
+ * Returns the current request URI relative to the base path.
+ */
+ private function getRelativeRequestUri(Request $request): string
+ {
+ return (string) substr($request->getRequestUri(), strlen($request->getBasePath()) + 1);
+ }
+}
diff --git a/src/Resources/config/backend_event_subscribers.yml b/src/Resources/config/backend_event_subscribers.yml
index 2be544dfb..0a591669d 100644
--- a/src/Resources/config/backend_event_subscribers.yml
+++ b/src/Resources/config/backend_event_subscribers.yml
@@ -36,6 +36,7 @@ services:
public: true
arguments:
- "@cca.dc-general.scope-matcher"
+ - "@security.helper"
tags:
- name: kernel.event_subscriber
diff --git a/src/Resources/config/contao/handler_backend_listeners.yml b/src/Resources/config/contao/handler_backend_listeners.yml
index 7d8120695..bc6055d33 100644
--- a/src/Resources/config/contao/handler_backend_listeners.yml
+++ b/src/Resources/config/contao/handler_backend_listeners.yml
@@ -27,6 +27,8 @@ services:
arguments:
- "@cca.dc-general.scope-matcher"
- "@cca.dc-general.security-url-builder-factory"
+ - "@request_stack"
+ - "@router"
tags:
- name: kernel.event_listener
event: dc-general.action
diff --git a/src/Resources/config/event_listeners.yml b/src/Resources/config/event_listeners.yml
index 55fb9e8b6..763a19c9f 100644
--- a/src/Resources/config/event_listeners.yml
+++ b/src/Resources/config/event_listeners.yml
@@ -61,3 +61,10 @@ services:
- name: kernel.event_listener
event: dc-general.model.post-paste
priority: -256
+
+ ContaoCommunityAlliance\DcGeneral\EventListener\StoreRefererListener:
+ arguments:
+ - '@security.helper'
+ - '@contao.routing.scope_matcher'
+ tags:
+ - kernel.event_listener
diff --git a/src/Resources/contao/templates/dcbe_general_show.html5 b/src/Resources/contao/templates/dcbe_general_show.html5
index 636205c5c..af7fd12a9 100644
--- a/src/Resources/contao/templates/dcbe_general_show.html5
+++ b/src/Resources/contao/templates/dcbe_general_show.html5
@@ -15,7 +15,7 @@ assert($translator instanceof \Symfony\Contracts\Translation\TranslatorInterface
?>
-
diff --git a/src/Resources/public/css/generalDriver.css b/src/Resources/public/css/generalDriver.css
index bbb2f6eb4..74e3ef635 100644
--- a/src/Resources/public/css/generalDriver.css
+++ b/src/Resources/public/css/generalDriver.css
@@ -1,2 +1,2 @@
@charset "UTF-8";@media projection,screen{div table.tl_listing{margin-top:0!important;margin-bottom:0!important}.tl_folder_tlist{border-top:0}.treepicker_popup a.folding{float:left;margin-right:20px}.tl_listing tr.tl_folder_clipped>td{background-color:#fff9e6}.cursor_disabled{cursor:not-allowed}#dcg_clipboard{position:relative;padding-top:2px;padding-left:40px;min-height:32px;background-image:url(../images/clipboard.svg);background-size:24px 24px;background-position:6px 3px;background-repeat:no-repeat}#dcg_clipboard .btn-clear{position:absolute;top:3px;left:6px;opacity:0;-webkit-transition:opacity 300ms;transition:opacity 300ms}#dcg_clipboard .btn-clear:hover{opacity:1;-webkit-transition:opacity 300ms;transition:opacity 300ms}#dcg_clipboard ul{display:block}#dcg_clipboard li{display:inline-block;border:1px solid #ddd;background-color:#f9f9f9;padding:2px 4px}#dcg_clipboard li>*{display:inline-block;vertical-align:middle}#dcg_clipboard img{vertical-align:middle}.tl_language_panel{padding:6px 6px 7px 0;background:#f3f3f3;border-top:1px solid #fff;border-bottom:1px solid #bbb;text-align:right}.tl_language_panel .tl_select{width:240px}.mac .tl_language_panel select{max-width:none}.mac .tl_language_panel .tl_select,.mac .tl_panel_bottom .tl_select{font-size:11px}.ie .tl_language_panel,.safari .tl_language_panel{overflow:hidden}.tl_language_panel .tl_formbody{position:relative}.ie .tl_language_panel .tl_formbody,.safari .tl_language_panel .tl_formbody{float:right}.tl_language_panel .tl_submit{margin-top:3px;vertical-align:top}.ie .tl_language_panel .tl_submit,.webkit .tl_language_panel .tl_submit{padding-top:4px;padding-bottom:4px}.opera .tl_language_panel .tl_submit{padding-top:3px;padding-bottom:3px;margin-top:-1px}.tl_language_panel img{position:relative;top:4px;vertical-align:top}#general_messageBox{width:-webkit-min-content;width:-moz-min-content;width:min-content;max-width:60%;min-width:40%;padding:24px;position:absolute;left:0;right:0;margin:0 auto;background:#fff no-repeat right center;border:2px solid #666;border-radius:6px;font-family:"Trebuchet MS",Verdana,sans-serif;font-size:15px;text-align:left;word-wrap:break-word}#general_messageBox.loading{background-image:url(../images/loading.gif);padding-right:60px}#general_messageBox.box-small{width:-webkit-max-content;width:-moz-max-content;width:max-content}#general_messageBox .tl_submit{text-align:center}#general_messageBox .tl_submit_container{text-align:right}#general_messageBox .tl_submit_container [type=submit]{margin-left:4px}.stickySave #general_messageBox .tl_submit_container{text-align:right;position:relative}.stickySave #general_messageBox .tl_submit_container [type=submit]{margin-left:4px}#general_messageOverlay{width:-webkit-max-content;width:-moz-max-content;width:max-content;height:100%;position:absolute;top:0;left:0;background:#fff;opacity:0.5}.header_stop{background-image:url("/system/themes/flexible/icons/stop.svg");background-size:16px}}
-/*# sourceMappingURL=generalDriver.css.map */
+/*# sourceMappingURL=generalDriver.css.map */
\ No newline at end of file
diff --git a/src/Resources/public/css/generalDriver.css.map b/src/Resources/public/css/generalDriver.css.map
index 298a3c537..404a81146 100644
--- a/src/Resources/public/css/generalDriver.css.map
+++ b/src/Resources/public/css/generalDriver.css.map
@@ -1 +1 @@
-{"version":3,"sources":["generalDriver.css","../sass/generalDriver.scss","../sass/_clipboard.scss","../sass/_languagePanel.scss","../sass/_messageBox.scss","../sass/_headerButton.scss"],"names":[],"mappings":"AAAA,gBAAgB,CCUhB,yBACE,qBACE,sBAAA,CACA,yBDCF,CCEA,iBACE,YDCF,CCEA,4BACE,UAAA,CACA,iBDCF,CCEA,oCACE,wBDCF,CCEA,iBACE,kBDCF,CE/BF,eACE,iBAAA,CACA,eAAA,CACA,iBAAA,CACA,eAAA,CACA,6CAAA,CACA,yBAAA,CACA,2BAAA,CACA,2BFkCA,CEhCA,0BACE,iBAAA,CACA,OAAA,CACA,QAAA,CACA,SAAA,CACA,gCAAA,CAAA,wBFkCF,CEhCE,gCACE,SAAA,CACA,gCAAA,CAAA,wBFkCJ,CE/BA,kBACE,aFiCF,CE/BA,kBACE,oBAAA,CACA,qBAAA,CACA,wBAAA,CACA,eFiCF,CE/BE,oBACE,oBAAA,CACA,qBFiCJ,CE9BA,mBACE,qBFgCF,CGrEF,mBACE,qBAAA,CACA,kBAAA,CACA,yBAAA,CACA,4BAAA,CACA,gBHwEA,CGrEF,8BACE,WHwEA,CGrEF,+BACE,cHwEA,CGrEF,oEAEE,cHwEA,CGrEF,kDAEE,eHwEA,CGrEF,gCACE,iBHwEA,CGrEF,4EAEE,WHwEA,CGrEF,8BACE,cAAA,CACA,kBHwEA,CGrEF,wEAEE,eAAA,CACA,kBHwEA,CGrEF,qCACE,eAAA,CACA,kBAAA,CACA,eHwEA,CGrEF,uBACE,iBAAA,CACA,OAAA,CACA,kBHwEA,CI/HF,oBACE,yBAAA,CAAA,sBAAA,CAAA,iBAAA,CACA,aAAA,CACA,aAAA,CACA,YAAA,CACA,iBAAA,CACA,MAAA,CACA,OAAA,CACA,aAAA,CACA,sCAAA,CACA,qBAAA,CACA,iBAAA,CACA,6CAAA,CACA,cAAA,CACA,eAAA,CACA,oBJkIA,CIhIA,4BACE,2CAAA,CACA,kBJkIF,CI/HA,8BACE,yBAAA,CAAA,sBAAA,CAAA,iBJiIF,CI9HA,+BACE,iBJgIF,CI7HA,yCACE,gBJ+HF,CI7HE,uDACE,eJ+HJ,CIzHF,qDACE,gBAAA,CACA,iBJ6HA,CI3HA,mEACE,eJ6HF,CIzHF,wBACE,yBAAA,CAAA,sBAAA,CAAA,iBAAA,CACA,WAAA,CACA,iBAAA,CACA,KAAA,CACA,MAAA,CACA,eAAA,CACA,WJ4HA,CKpLF,aACE,8DAAA,CACA,oBLuLA,CACF","file":"generalDriver.css"}
\ No newline at end of file
+{"version":3,"sources":["generalDriver.css","../sass/generalDriver.scss","../sass/_clipboard.scss","../sass/_languagePanel.scss","../sass/_messageBox.scss","../sass/_headerButton.scss"],"names":[],"mappings":"AAAA,gBAAgB,CCUhB,yBACE,qBACE,sBAAA,CACA,yBDCF,CCEA,iBACE,YDAF,CCGA,4BACE,UAAA,CACA,iBDDF,CCIA,oCACE,wBDFF,CCKA,iBACE,kBDHF,CE3BF,eACE,iBAAA,CACA,eAAA,CACA,iBAAA,CACA,eAAA,CACA,6CAAA,CACA,yBAAA,CACA,2BAAA,CACA,2BF6BA,CE3BA,0BACE,iBAAA,CACA,OAAA,CACA,QAAA,CACA,SAAA,CACA,gCAAA,CAAA,wBF6BF,CE3BE,gCACE,SAAA,CACA,gCAAA,CAAA,wBF6BJ,CE1BA,kBACE,aF4BF,CE1BA,kBACE,oBAAA,CACA,qBAAA,CACA,wBAAA,CACA,eF4BF,CE1BE,oBACE,oBAAA,CACA,qBF4BJ,CEzBA,mBACE,qBF2BF,CGhEF,mBACE,qBAAA,CACA,kBAAA,CACA,yBAAA,CACA,4BAAA,CACA,gBHkEA,CG/DF,8BACE,WHiEA,CG9DF,+BACE,cHgEA,CG7DF,oEAEE,cH+DA,CG5DF,kDAEE,eH8DA,CG3DF,gCACE,iBH6DA,CG1DF,4EAEE,WH4DA,CGzDF,8BACE,cAAA,CACA,kBH2DA,CGxDF,wEAEE,eAAA,CACA,kBH0DA,CGvDF,qCACE,eAAA,CACA,kBAAA,CACA,eHyDA,CGtDF,uBACE,iBAAA,CACA,OAAA,CACA,kBHwDA,CI/GF,oBACE,yBAAA,CAAA,sBAAA,CAAA,iBAAA,CACA,aAAA,CACA,aAAA,CACA,YAAA,CACA,iBAAA,CACA,MAAA,CACA,OAAA,CACA,aAAA,CACA,sCAAA,CACA,qBAAA,CACA,iBAAA,CACA,6CAAA,CACA,cAAA,CACA,eAAA,CACA,oBJiHA,CI/GA,4BACE,2CAAA,CACA,kBJiHF,CI9GA,8BACE,yBAAA,CAAA,sBAAA,CAAA,iBJgHF,CI7GA,+BACE,iBJ+GF,CI5GA,yCACE,gBJ8GF,CI5GE,uDACE,eJ8GJ,CIxGF,qDACE,gBAAA,CACA,iBJ2GA,CIzGA,mEACE,eJ2GF,CIvGF,wBACE,yBAAA,CAAA,sBAAA,CAAA,iBAAA,CACA,WAAA,CACA,iBAAA,CACA,KAAA,CACA,MAAA,CACA,eAAA,CACA,WJyGA,CKjKF,aACE,8DAAA,CACA,oBLmKA,CACF","file":"generalDriver.css"}
\ No newline at end of file
diff --git a/src/Resources/public/js/vanillaGeneral.js b/src/Resources/public/js/vanillaGeneral.js
index e311ad0c6..d920677c9 100644
--- a/src/Resources/public/js/vanillaGeneral.js
+++ b/src/Resources/public/js/vanillaGeneral.js
@@ -157,7 +157,7 @@ function GeneralTableDnD()
// Build url.
var href = window.location.href.replace(/\?.*$/, '');
- var req = window.location.search;
+ var req = window.location.search + '?';
req += '&act=paste';
req += '&source=' + id;
req += '&after=' + insertAfter;
diff --git a/src/Resources/public/sass/generalDriver.scss b/src/Resources/public/sass/generalDriver.scss
index b0197935e..ded539c3f 100644
--- a/src/Resources/public/sass/generalDriver.scss
+++ b/src/Resources/public/sass/generalDriver.scss
@@ -26,10 +26,10 @@
.tl_listing tr.tl_folder_clipped > td {
background-color: #fff9e6;
}
-
+
.cursor_disabled{
cursor: not-allowed;
- }
+ }
@import "clipboard";
@import "languagePanel";
diff --git a/src/Resources/translations/dc-general.de.xlf b/src/Resources/translations/dc-general.de.xlf
index ac284dff2..fe2c7e12a 100644
--- a/src/Resources/translations/dc-general.de.xlf
+++ b/src/Resources/translations/dc-general.de.xlf
@@ -1,465 +1,471 @@
-
-
-
- Language
- Sprache
-
-
-
-
- Switch language
- Sprache wechseln
-
-
-
-
- Table: %table%
- Tabelle: %table%
-
-
-
-
- The property "%property%" is already in the database and not unique.
- Die Eigenschaft "%property%" ist schon in der Datenbank und nicht unique.
-
-
-
-
- Nothing was selected!
- Es wurde nichts ausgewählt!
-
-
-
-
- Ok
- Ok
-
-
-
-
- Abort
- Abbrechen
-
-
-
-
- Cancel
- Beenden
-
-
-
-
- Cancel multiple processing.
- Die Mehrfachbearbeitung beenden.
-
-
-
-
- The property "%property%" isn't supported in mode "%mode%".
- Die Eigenschaft "%property%" wird im Modus "%mode%" nicht unterstützt.
-
-
-
-
- You must select the property "%property%" for edit it.
- Die Eigenschaft "%property%" muss ausgewählt sein, damit diese bearbeitet werden kann.
-
-
-
-
- You must select the parent property "%parent_property%" for edit the property
- "%edit_property%".
-
- Die Abhängige Eigenschaft "%parent_property%" muss ausgewählt sein, damit man die Eigenschaft
- "%edit_property%" bearbeiten kann.
-
-
-
-
-
- Select properties
- Eigenschaften auswählen
-
-
-
-
- Please check your selected properties!
- Bitte überprüfen Sie die ausgewählten Eigenschaften!
-
-
-
-
- Select models
- Elemente auswählen
-
-
-
-
- Disabled: %title%
- Gesperrt: %title%
-
-
-
-
- Create a new item
- Neuen Datensatz erstellen
-
-
-
-
- Edit record %id%
- Datensatz %id% bearbeiten
-
-
-
-
- W Y
- W. Y
-
-
-
-
- Delete
- Löschen
-
-
-
-
- Edit
- Bearbeiten
-
-
-
-
- Override
- Überschreiben
-
-
-
-
- Copy
- Kopieren
-
-
-
-
- Close
- Schließen
-
-
-
-
- Continue
- Weiter
-
-
-
-
- Do you really want to delete the selected records?
- Wollen Sie die ausgewählten Einträge wirklich löschen?
-
-
-
-
- Delete
- Löschen
-
-
-
-
- Move
- Verschieben
-
-
-
-
- Copy
- Kopieren
-
-
-
-
- Edit
- Bearbeiten
-
-
-
-
- Override
- Überschreiben
-
-
-
-
- Edit multiple
- Mehrere bearbeiten
-
-
-
-
- no
- nein
-
-
-
-
- yes
- ja
-
-
-
-
- Show the details of record %id%
- Details des Datensatzes %id% anzeigen
-
-
-
-
- Color picker
- Farbe auswählen
-
-
-
-
- Word wrap
- Zeilenumbruch
-
-
-
-
- Open the help wizard
- Den Hilfe-Assistent aufrufen
-
-
-
-
- Change selection
- Auswahl ändern
-
-
-
-
- Drag the items to re-order them
- Elemente können durch Ziehen umsortiert werden
-
-
-
-
- Reset selection
- Auswahl aufheben
-
-
-
-
- Select all
- Alle auswählen
-
-
-
-
- Collapse node
- Bereich schließen
-
-
-
-
- Expand node
- Bereich öffnen
-
-
-
-
- Save
- Speichern
-
-
-
-
- Save and close
- Speichern und schließen
-
-
-
-
- Save and edit
- Speichern und bearbeiten
-
-
-
-
- Save and go back
- Speichern und zurück
-
-
-
-
- Save and new
- Speichern und neu
-
-
-
-
- Save and duplicate
- Speichern und duplizieren
-
-
-
-
- Go back
- Zurück
-
-
-
-
- Back to the previous page
- Zurück zur vorherigen Seite
-
-
-
-
- Revision date
- Änderungsdatum
-
-
-
-
- 0
- 1
-
-
-
-
- %B %d%o, %Y
- %d. %B %Y
-
-
-
-
- ID
- ID
-
-
-
-
- Parent ID
- Elternelement
-
-
-
-
- Sorting value
- Sortierindex
-
-
-
-
- Search
- Suchen
-
-
-
-
- Treepicker manager
- Treepicker-Manager
-
-
-
-
- utf-8
- utf-8
-
-
-
-
- Records
- Datensätze
-
-
-
-
- All
- Alle
-
-
-
-
- Update mode
- Update-Modus
-
-
-
-
- Add the selected values
- Ausgewählte Werte hinzufügen
-
-
-
-
- Remove the selected values
- Ausgewählte Werte entfernen
-
-
-
-
- Replace the existing entries
- Bestehende Einträge überschreiben
-
-
-
-
- Apply
- Anwenden
-
-
-
-
- Sort
- Sortieren
-
-
-
-
- Show
- Anzeigen
-
-
-
-
- Reset
- Zurücksetzen
-
-
-
-
- Version
- Version
-
-
-
-
- Restore
- Wiederherstellen
-
-
-
-
- Clear clipboard
- Ablage leeren
-
-
-
-
- Remove this item from clipboard
- Element von Ablage entfernen
-
-
-
-
- No records found.
- Keine Einträge gefunden.
-
-
-
+
+
+
+ Language
+ Sprache
+
+
+
+
+ Switch language
+ Sprache wechseln
+
+
+
+
+ Table: %table%
+ Tabelle: %table%
+
+
+
+
+ Color picker
+ Farbe auswählen
+
+
+
+
+ Page picker
+ Seite auswählen
+
+
+
+
+ The property "%property%" is already in the database and not unique.
+ Die Eigenschaft "%property%" ist schon in der Datenbank und nicht unique.
+
+
+
+
+ Nothing was selected!
+ Es wurde nichts ausgewählt!
+
+
+
+
+ Ok
+ Ok
+
+
+
+
+ Abort
+ Abbrechen
+
+
+
+
+ Cancel
+ Beenden
+
+
+
+
+ Cancel multiple processing.
+ Die Mehrfachbearbeitung beenden.
+
+
+
+
+ The property "%property%" isn't supported in mode "%mode%".
+ Die Eigenschaft "%property%" wird im Modus "%mode%" nicht unterstützt.
+
+
+
+
+ You must select the property "%property%" for edit it.
+ Die Eigenschaft "%property%" muss ausgewählt sein, damit diese bearbeitet werden kann.
+
+
+
+
+ You must select the parent property "%parent_property%" for edit the property
+ "%edit_property%".
+
+ Die Abhängige Eigenschaft "%parent_property%" muss ausgewählt sein, damit man die Eigenschaft
+ "%edit_property%" bearbeiten kann.
+
+
+
+
+
+ Select properties
+ Eigenschaften auswählen
+
+
+
+
+ Please check your selected properties!
+ Bitte überprüfen Sie die ausgewählten Eigenschaften!
+
+
+
+
+ Select models
+ Elemente auswählen
+
+
+
+
+ Disabled: %title%
+ Gesperrt: %title%
+
+
+
+
+ Create a new item
+ Neuen Datensatz erstellen
+
+
+
+
+ Edit record %id%
+ Datensatz %id% bearbeiten
+
+
+
+
+ W Y
+ W. Y
+
+
+
+
+ Delete
+ Löschen
+
+
+
+
+ Edit
+ Bearbeiten
+
+
+
+
+ Override
+ Überschreiben
+
+
+
+
+ Copy
+ Kopieren
+
+
+
+
+ Close
+ Schließen
+
+
+
+
+ Continue
+ Weiter
+
+
+
+
+ Do you really want to delete the selected records?
+ Wollen Sie die ausgewählten Einträge wirklich löschen?
+
+
+
+
+ Delete
+ Löschen
+
+
+
+
+ Move
+ Verschieben
+
+
+
+
+ Copy
+ Kopieren
+
+
+
+
+ Edit
+ Bearbeiten
+
+
+
+
+ Override
+ Überschreiben
+
+
+
+
+ Edit multiple
+ Mehrere bearbeiten
+
+
+
+
+ no
+ nein
+
+
+
+
+ yes
+ ja
+
+
+
+
+ Show the details of record %id%
+ Details des Datensatzes %id% anzeigen
+
+
+
+
+ Word wrap
+ Zeilenumbruch
+
+
+
+
+ Open the help wizard
+ Den Hilfe-Assistent aufrufen
+
+
+
+
+ Change selection
+ Auswahl ändern
+
+
+
+
+ Drag the items to re-order them
+ Elemente können durch Ziehen umsortiert werden
+
+
+
+
+ Reset selection
+ Auswahl aufheben
+
+
+
+
+ Select all
+ Alle auswählen
+
+
+
+
+ Collapse node
+ Bereich schließen
+
+
+
+
+ Expand node
+ Bereich öffnen
+
+
+
+
+ Save
+ Speichern
+
+
+
+
+ Save and close
+ Speichern und schließen
+
+
+
+
+ Save and edit
+ Speichern und bearbeiten
+
+
+
+
+ Save and go back
+ Speichern und zurück
+
+
+
+
+ Save and new
+ Speichern und neu
+
+
+
+
+ Save and duplicate
+ Speichern und duplizieren
+
+
+
+
+ Go back
+ Zurück
+
+
+
+
+ Back to the previous page
+ Zurück zur vorherigen Seite
+
+
+
+
+ Revision date
+ Änderungsdatum
+
+
+
+
+ 0
+ 1
+
+
+
+
+ %B %d%o, %Y
+ %d. %B %Y
+
+
+
+
+ ID
+ ID
+
+
+
+
+ Parent ID
+ Elternelement
+
+
+
+
+ Sorting value
+ Sortierindex
+
+
+
+
+ Search
+ Suchen
+
+
+
+
+ Treepicker manager
+ Treepicker-Manager
+
+
+
+
+ utf-8
+ utf-8
+
+
+
+
+ Records
+ Datensätze
+
+
+
+
+ All
+ Alle
+
+
+
+
+ Update mode
+ Update-Modus
+
+
+
+
+ Add the selected values
+ Ausgewählte Werte hinzufügen
+
+
+
+
+ Remove the selected values
+ Ausgewählte Werte entfernen
+
+
+
+
+ Replace the existing entries
+ Bestehende Einträge überschreiben
+
+
+
+
+ Apply
+ Anwenden
+
+
+
+
+ Sort
+ Sortieren
+
+
+
+
+ Show
+ Anzeigen
+
+
+
+
+ Reset
+ Zurücksetzen
+
+
+
+
+ Version
+ Version
+
+
+
+
+ Restore
+ Wiederherstellen
+
+
+
+
+ Clear clipboard
+ Ablage leeren
+
+
+
+
+ Remove this item from clipboard
+ Element von Ablage entfernen
+
+
+
+
+ No records found.
+ Keine Einträge gefunden.
+
+
+
diff --git a/src/Resources/translations/dc-general.en.xlf b/src/Resources/translations/dc-general.en.xlf
index 22ab9d8a8..c475f7746 100644
--- a/src/Resources/translations/dc-general.en.xlf
+++ b/src/Resources/translations/dc-general.en.xlf
@@ -1,387 +1,391 @@
-
-
-
- Language
-
-
-
-
- Switch language
-
-
-
-
- Table: %table%
-
-
-
-
- The property "%property%" is already in the database and not unique.
-
-
-
-
- Nothing was selected!
-
-
-
-
- Ok
-
-
-
-
- Abort
-
-
-
-
- Cancel
-
-
-
-
- Cancel multiple processing.
-
-
-
-
- The property "%property%" isn't supported in mode "%mode%".
-
-
-
-
- You must select the property "%property%" for edit it.
-
-
-
-
- You must select the parent property "%parent_property%" for edit the property
- "%edit_property%".
-
-
-
-
-
- Select properties
-
-
-
-
- Please check your selected properties!
-
-
-
-
- Select models
-
-
-
-
- Disabled: %title%
-
-
-
-
- Create a new item
-
-
-
-
- Edit record %id%
-
-
-
-
- W Y
-
-
-
-
- Delete
-
-
-
-
- Edit
-
-
-
-
- Override
-
-
-
-
- Copy
-
-
-
-
- Close
-
-
-
-
- Continue
-
-
-
-
- Do you really want to delete the selected records?
-
-
-
-
- Delete
-
-
-
-
- Move
-
-
-
-
- Copy
-
-
-
-
- Edit
-
-
-
-
- Override
-
-
-
-
- Edit multiple
-
-
-
-
- no
-
-
-
-
- yes
-
-
-
-
- Show the details of record %id%
-
-
-
-
- Color picker
-
-
-
-
- Word wrap
-
-
-
-
- Open the help wizard
-
-
-
-
- Change selection
-
-
-
-
- Drag the items to re-order them
-
-
-
-
- Reset selection
-
-
-
-
- Select all
-
-
-
-
- Collapse node
-
-
-
-
- Expand node
-
-
-
-
- Save
-
-
-
-
- Save and close
-
-
-
-
- Save and edit
-
-
-
-
- Save and go back
-
-
-
-
- Save and new
-
-
-
-
- Save and duplicate
-
-
-
-
- Go back
-
-
-
-
- Back to the previous page
-
-
-
-
- Revision date
-
-
-
-
- 0
-
-
-
-
- %B %d%o, %Y
-
-
-
-
- ID
-
-
-
-
- Parent ID
-
-
-
-
- Sorting value
-
-
-
-
- Search
-
-
-
-
- Treepicker manager
-
-
-
-
- utf-8
-
-
-
-
- Records
-
-
-
-
- All
-
-
-
-
- Update mode
-
-
-
-
- Add the selected values
-
-
-
-
- Remove the selected values
-
-
-
-
- Replace the existing entries
-
-
-
-
- Apply
-
-
-
-
- Sort
-
-
-
-
- Show
-
-
-
-
- Reset
-
-
-
-
- Version
-
-
-
-
- Restore
-
-
-
-
- Clear clipboard
-
-
-
-
- Remove this item from clipboard
-
-
-
-
- No records found.
-
-
-
+
+
+
+ Language
+
+
+
+
+ Switch language
+
+
+
+
+ Table: %table%
+
+
+
+
+ Color picker
+
+
+
+
+ Page picker
+
+
+
+
+ The property "%property%" is already in the database and not unique.
+
+
+
+
+ Nothing was selected!
+
+
+
+
+ Ok
+
+
+
+
+ Abort
+
+
+
+
+ Cancel
+
+
+
+
+ Cancel multiple processing.
+
+
+
+
+ The property "%property%" isn't supported in mode "%mode%".
+
+
+
+
+ You must select the property "%property%" to edit it.
+
+
+
+
+ You must select the parent property "%parent_property%" to edit the property "%edit_property%".
+
+
+
+
+
+ Select properties
+
+
+
+
+ Please check your selected properties!
+
+
+
+
+ Select models
+
+
+
+
+ Disabled: %title%
+
+
+
+
+ Create a new item
+
+
+
+
+ Edit record %id%
+
+
+
+
+ W Y
+
+
+
+
+ Delete
+
+
+
+
+ Edit
+
+
+
+
+ Override
+
+
+
+
+ Copy
+
+
+
+
+ Close
+
+
+
+
+ Continue
+
+
+
+
+ Do you really want to delete the selected records?
+
+
+
+
+ Delete
+
+
+
+
+ Move
+
+
+
+
+ Copy
+
+
+
+
+ Edit
+
+
+
+
+ Override
+
+
+
+
+ Edit multiple
+
+
+
+
+ no
+
+
+
+
+ yes
+
+
+
+
+ Show the details of record %id%
+
+
+
+
+ Word wrap
+
+
+
+
+ Open the help wizard
+
+
+
+
+ Change selection
+
+
+
+
+ Drag the items to re-order them
+
+
+
+
+ Reset selection
+
+
+
+
+ Select all
+
+
+
+
+ Collapse node
+
+
+
+
+ Expand node
+
+
+
+
+ Save
+
+
+
+
+ Save and close
+
+
+
+
+ Save and edit
+
+
+
+
+ Save and go back
+
+
+
+
+ Save and new
+
+
+
+
+ Save and duplicate
+
+
+
+
+ Go back
+
+
+
+
+ Back to the previous page
+
+
+
+
+ Revision date
+
+
+
+
+ 0
+
+
+
+
+ %B %d%o, %Y
+
+
+
+
+ ID
+
+
+
+
+ Parent ID
+
+
+
+
+ Sorting value
+
+
+
+
+ Search
+
+
+
+
+ Treepicker manager
+
+
+
+
+ utf-8
+
+
+
+
+ Records
+
+
+
+
+ All
+
+
+
+
+ Update mode
+
+
+
+
+ Add the selected values
+
+
+
+
+ Remove the selected values
+
+
+
+
+ Replace the existing entries
+
+
+
+
+ Apply
+
+
+
+
+ Sort
+
+
+
+
+ Show
+
+
+
+
+ Reset
+
+
+
+
+ Version
+
+
+
+
+ Restore
+
+
+
+
+ Clear clipboard
+
+
+
+
+ Remove this item from clipboard
+
+
+
+
+ No records found.
+
+
+
diff --git a/src/View/ActionHandler/AbstractPropertyVisibilityHandler.php b/src/View/ActionHandler/AbstractPropertyVisibilityHandler.php
index 5ac0e1563..0b7b6fe53 100644
--- a/src/View/ActionHandler/AbstractPropertyVisibilityHandler.php
+++ b/src/View/ActionHandler/AbstractPropertyVisibilityHandler.php
@@ -50,6 +50,7 @@
use function in_array;
use function method_exists;
use function sprintf;
+use function Symfony\Component\DependencyInjection\Loader\Configurator\env;
/**
* This abstract visibility handler provide methods for the visibility of properties.
@@ -498,7 +499,10 @@ protected function injectSelectSubPropertiesInformation(
$information = [];
foreach ($properties as $propertyName => $informationProperty) {
- $label = !$informationProperty->getLabel() ? $propertyName : $informationProperty->getLabel();
+ $label = $translator->translate(
+ $informationProperty->getLabel() ?: $propertyName,
+ $environment->getDataDefinition()?->getName()
+ );
$information[] =
'' .