Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for deep copy in tree view #658

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
21 changes: 14 additions & 7 deletions src/BaseConfigRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,27 @@ public function getEnvironment()
private function addParentFilter(ModelIdInterface $idParent, ConfigInterface $config): ConfigInterface
{
$environment = $this->getEnvironment();
$definition = $environment->getDataDefinition();
assert($environment instanceof EnvironmentInterface);

$definition = $environment->getDataDefinition();
if (null === $definition) {
throw new DcGeneralRuntimeException('Data definition not set.');
}
$basicDefinition = $definition->getBasicDefinition();
$providerName = $basicDefinition->getDataProvider();
$providerName = (string) $basicDefinition->getDataProvider();
$parentProviderName = $idParent->getDataProviderName();
$parentProvider = $environment->getDataProvider($parentProviderName);

if ($basicDefinition->getParentDataProvider() !== $parentProviderName) {
throw new DcGeneralRuntimeException(
'Unexpected parent provider ' . $parentProviderName .
' (expected ' . ((string) $basicDefinition->getParentDataProvider()) . ')'
);
// Could be a tree parent then.
if ($basicDefinition->getDataProvider() !== $parentProviderName) {
throw new DcGeneralRuntimeException(
'Unexpected parent provider ' . $parentProviderName .
' (expected ' . ((string) $basicDefinition->getParentDataProvider()) . ')'
);
}
$parentProviderName = $providerName;
$parentProvider = $environment->getDataProvider($parentProviderName);
}

if ($parentProvider) {
Expand All @@ -115,7 +122,7 @@ private function addParentFilter(ModelIdInterface $idParent, ConfigInterface $co

$condition = $definition->getModelRelationshipDefinition()->getChildCondition(
$parentProviderName,
(string) $providerName
$providerName
);

if ($condition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,11 @@ protected function parseDataProvider(ContainerInterface $container)
}

// First check if we are using the "new" notation used in DcGeneral 0.9.
if (!\is_array($this->getFromDca('dca_config/data_provider'))) {
$dataProvidersDca = $this->getFromDca('dca_config/data_provider');
if (!\is_array($dataProvidersDca)) {
return;
}

$dataProvidersDca = $this->getFromDca('dca_config/data_provider');

foreach ($dataProvidersDca as $dataProviderDcaName => $dataProviderDca) {
$providerInformation = $this->parseSingleDataProvider(
$container,
Expand Down Expand Up @@ -326,6 +325,7 @@ protected function parseDataProvider(ContainerInterface $container)
break;

default:
$baseInitializationData['name'] = $providerInformation->getName();
}

$providerInformation->setInitializationData(
Expand Down
6 changes: 6 additions & 0 deletions src/Contao/Dca/Populator/ParentDefinitionPopulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ public function populateController(EnvironmentInterface $environment)
return;
}

if ($parentDataProvider === $definition->getName()) {
$environment->setParentDataDefinition($definition);

return;
}

if (null === $dispatcher = $environment->getEventDispatcher()) {
throw new LogicException('No event dispatcher given');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -15,7 +15,7 @@
* @author Sven Baumann <[email protected]>
* @author David Molineus <[email protected]>
* @author Ingolf Steinhardt <[email protected]>
* @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
*/
Expand Down Expand Up @@ -144,7 +144,7 @@ protected function process(EnvironmentInterface $environment)
return null;
}

ViewHelpers::redirectHome($environment);
ViewHelpers::redirectCleanHome($environment, ['source', 'after', 'into']);

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ private function handleCopyAllAction(EnvironmentInterface $environment, Action $
foreach ($this->getModelIds($environment, $action, $this->getSubmitAction($environment)) as $modelId) {
zonky2 marked this conversation as resolved.
Show resolved Hide resolved
$inputProvider->setParameter('source', $modelId->getSerialized());

$this->callAction($environment, 'copy');
$this->callAction($environment, 'deepcopy');

$inputProvider->unsetParameter('source');
}
Expand Down
5 changes: 3 additions & 2 deletions src/Contao/View/Contao2BackendView/ButtonRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,9 @@ private function calculateParameters(CommandInterface $command, string $serializ
}
if (($command instanceof CutCommandInterface) || ($command instanceof CopyCommandInterface)) {
// Cut & copy need some special information.
$parameters = [];
$parameters['act'] = $command->getName();
if (!\array_key_exists('act', $parameters)) {
$parameters['act'] = $command->getName();
}

$inputProvider = $this->environment->getInputProvider();
assert($inputProvider instanceof InputProviderInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ private function checkPermission(ActionEvent $event)
*
* @return void
*/
private function clearClipboard(ActionEvent $event, $redirect = true)
private function clearClipboard(ActionEvent $event, bool $redirect = true): void
{
$environment = $event->getEnvironment();

Expand Down
2 changes: 1 addition & 1 deletion src/Contao/View/Contao2BackendView/TreeView.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ private function handleNodeStateChanges()
$this->toggleModel($providerName, $modelId);
}

ViewHelpers::redirectHome($environment);
ViewHelpers::redirectCleanHome($environment, ['ptg', 'provider']);
}
}

Expand Down
71 changes: 48 additions & 23 deletions src/Contao/View/Contao2BackendView/ViewHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,56 @@ public static function redirectHome(EnvironmentInterface $environment): never
$request = self::getRequest();
$routeName = $request->attributes->get('_route');
if ($routeName !== 'contao_backend') {
self::determineNewStyleRedirect($routeName, $request, $environment);
self::determineNewStyleRedirect($routeName, $request, $environment, []);
}
self::determineLegacyRedirect($environment, $input);
}

/** @param list<string> $cleanNames */
public static function redirectCleanHome(EnvironmentInterface $environment, array $cleanNames): 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, $cleanNames);
}
self::determineLegacyRedirect($environment, $input);
}

/** @param list<string> $cleanNames */
private static function determineNewStyleRedirect(
string $routeName,
Request $request,
EnvironmentInterface $environment,
array $cleanNames
): never {
$routeGenerator = System::getContainer()->get('router');
assert($routeGenerator instanceof UrlGeneratorInterface);
$parameters = $request->query->all();
foreach ($cleanNames as $key) {
unset($parameters[$key]);
}
if ($routeName === $request->attributes->get('_route')) {
foreach ($request->attributes->get('_route_params') ?? [] as $key => $value) {
if ('_' === $key[0] || \in_array($key, $cleanNames, true)) {
continue;
}
$parameters[$key] = $value;
}
}
unset($parameters['act']);
$routeBase = $routeGenerator->generate($routeName, $parameters);

self::dispatchRedirect($environment, new RedirectEvent($routeBase));
}

private static function determineLegacyRedirect(
EnvironmentInterface $environment,
InputProviderInterface $input,
): never {
if ($input->hasParameter('table')) {
if ($input->hasParameter('pid')) {
$event = new RedirectEvent(
Expand All @@ -288,28 +335,6 @@ public static function redirectHome(EnvironmentInterface $environment): never
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();
if ($routeName === $request->attributes->get('_route')) {
foreach ($request->attributes->get('_route_params') ?? [] as $key => $value) {
if ('_' === $key[0]) {
continue;
}
$parameters[$key] = $value;
}
}
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');
Expand Down
16 changes: 8 additions & 8 deletions src/Controller/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ private function doActions(
// Now apply sorting and persist all models.
$models = $this->sortAndPersistModels($actions, $after, $into, $parentModelId, $items);

// At least, go ahead with the deep copy.
// At last, go ahead with the deep copy.
$this->doDeepCopy($deepCopyList);

return $models;
Expand Down Expand Up @@ -1112,28 +1112,28 @@ protected function doDeepCopy(array $deepCopyList)
$groupAndSortingCollection = $listingConfig->getGroupAndSortingDefinition();
$groupAndSorting = $groupAndSortingCollection->getDefault();

// ***** fetch the children
// ***** fetch the children.
$filter = $childCondition->getFilter($origin);

// apply parent-child condition
$config = $destinationDataProvider->getEmptyConfig();
$config->setFilter($filter);

// apply sorting
// Apply sorting.
$sorting = [];
foreach ($groupAndSorting as $information) {
/** @var GroupAndSortingInformationInterface $information */
$sorting[$information->getProperty()] = $information->getSortingMode();
}
$config->setSorting($sorting);

// receive children
// Receive children.
$children = $destinationDataProvider->fetchAll($config);

// ***** do the deep copy
// ***** do the deep copy.
$actions = [];

// build the copy actions
// Build the copy actions.
foreach ($children as $childModel) {
if (!($childModel instanceof ModelInterface)) {
continue;
Expand All @@ -1147,8 +1147,8 @@ protected function doDeepCopy(array $deepCopyList)
];
}

// do the deep copy
$childrenModels = $destinationController->doActions($actions, null, null, $parentId);
// Do the deep copy.
$childrenModels = $destinationController->doActions($actions, null, $parentId, null);

// ensure parent-child condition
foreach ($childrenModels as $childrenModel) {
Expand Down
42 changes: 22 additions & 20 deletions src/Controller/ModelCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -16,7 +16,7 @@
* @author Ingolf Steinhardt <[email protected]>
* @author David Molineus <[email protected]>
* @author Stefan Heimes <[email protected]>
* @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
*/
Expand Down Expand Up @@ -160,6 +160,8 @@ public function __construct(EnvironmentInterface $environment)
*
* @return ModelInterface|null
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @throws \InvalidArgumentException When the model id is invalid.
*/
public function getModel($modelId, $providerName = null)
Expand All @@ -185,34 +187,34 @@ public function getModel($modelId, $providerName = null)
assert($dataProvider instanceof DataProviderInterface);

$config = $dataProvider->getEmptyConfig();
$config->setId($modelId->getId());

if ($definition->getName() === $modelId->getDataProviderName()) {
$propertyDefinition = $definition->getPropertiesDefinition();
} elseif ($parentDefinition && $parentDefinition->getName() === $modelId->getDataProviderName()) {
$propertyDefinition = $parentDefinition->getPropertiesDefinition();
} else {
throw new \InvalidArgumentException('Invalid provider name ' . $modelId->getDataProviderName());
$propertyDefinition = null;
}
if (null !== $propertyDefinition) {
$properties = [];
// Filter real properties from the property definition.
foreach ($propertyDefinition->getPropertyNames() as $propertyName) {
if ($dataProvider->fieldExists($propertyName)) {
$properties[] = $propertyName;
continue;
}

$properties = [];

// Filter real properties from the property definition.
foreach ($propertyDefinition->getPropertyNames() as $propertyName) {
if ($dataProvider->fieldExists($propertyName)) {
$properties[] = $propertyName;

continue;
// @codingStandardsIgnoreStart
@\trigger_error(
'Only real property is allowed in the property definition.' .
'This will no longer be supported in the future.',
E_USER_DEPRECATED
);
// @codingStandardsIgnoreEnd
}

// @codingStandardsIgnoreStart
@\trigger_error(
'Only real property is allowed in the property definition.' .
'This will no longer be supported in the future.',
E_USER_DEPRECATED
);
// @codingStandardsIgnoreEnd
$config->setFields($properties);
}
$config->setId($modelId->getId())->setFields($properties);

return $dataProvider->fetch($config);
}
Expand Down
Loading