Skip to content

Commit e423c9d

Browse files
authored
Merge pull request #41661 from mattgoud/fix/quick-access-multilang-autofill-41644
Fix Quick Access form not auto-filling empty language names
2 parents acfa1f3 + 7cddf60 commit e423c9d

6 files changed

Lines changed: 125 additions & 13 deletions

File tree

src/Adapter/QuickAccess/CommandHandler/AddQuickAccessHandler.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414
use PrestaShop\PrestaShop\Core\Domain\QuickAccess\CommandHandler\AddQuickAccessHandlerInterface;
1515
use PrestaShop\PrestaShop\Core\Domain\QuickAccess\Exception\QuickAccessConstraintException;
1616
use PrestaShop\PrestaShop\Core\Domain\QuickAccess\ValueObject\QuickAccessId;
17+
use PrestaShop\PrestaShop\Core\Language\LocalizedNamesFiller;
1718
use QuickAccess;
1819

1920
#[AsCommandHandler]
2021
class AddQuickAccessHandler implements AddQuickAccessHandlerInterface
2122
{
22-
public function __construct(private readonly QuickAccessRepository $repository)
23-
{
23+
public function __construct(
24+
private readonly QuickAccessRepository $repository,
25+
private readonly LocalizedNamesFiller $localizedNamesFiller,
26+
) {
2427
}
2528

2629
public function handle(AddQuickAccessCommand $command): QuickAccessId
@@ -34,7 +37,7 @@ public function handle(AddQuickAccessCommand $command): QuickAccessId
3437

3538
$quickAccess = new QuickAccess();
3639
// @phpstan-ignore-next-line (ObjectModel multilingual field accepts array at runtime)
37-
$quickAccess->name = $command->getLocalizedNames();
40+
$quickAccess->name = $this->localizedNamesFiller->fill($command->getLocalizedNames());
3841
$quickAccess->link = $command->getLink();
3942
$quickAccess->new_window = $command->isNewWindow();
4043

src/Adapter/QuickAccess/CommandHandler/EditQuickAccessHandler.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,28 @@
1212
use PrestaShop\PrestaShop\Core\CommandBus\Attributes\AsCommandHandler;
1313
use PrestaShop\PrestaShop\Core\Domain\QuickAccess\Command\EditQuickAccessCommand;
1414
use PrestaShop\PrestaShop\Core\Domain\QuickAccess\CommandHandler\EditQuickAccessHandlerInterface;
15+
use PrestaShop\PrestaShop\Core\Language\LocalizedNamesFiller;
1516

1617
#[AsCommandHandler]
1718
class EditQuickAccessHandler implements EditQuickAccessHandlerInterface
1819
{
19-
public function __construct(private readonly QuickAccessRepository $repository)
20-
{
20+
public function __construct(
21+
private readonly QuickAccessRepository $repository,
22+
private readonly LocalizedNamesFiller $localizedNamesFiller,
23+
) {
2124
}
2225

2326
public function handle(EditQuickAccessCommand $command): void
2427
{
2528
$quickAccess = $this->repository->get($command->getQuickAccessId());
2629

2730
if (null !== $command->getLocalizedNames()) {
31+
// Pass the stored names as existing values so a partial update (e.g. a single language)
32+
// keeps the other languages instead of overwriting them with the auto-fill value.
33+
/** @var array<int, string> $existingNames */
34+
$existingNames = $quickAccess->name;
2835
// @phpstan-ignore-next-line (ObjectModel multilingual field accepts array at runtime)
29-
$quickAccess->name = $command->getLocalizedNames();
36+
$quickAccess->name = $this->localizedNamesFiller->fill($command->getLocalizedNames(), $existingNames);
3037
}
3138

3239
if (null !== $command->getLink()) {
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
/**
3+
* For the full copyright and license information, please view the
4+
* docs/licenses/LICENSE.txt file that was distributed with this source code.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace PrestaShop\PrestaShop\Core\Language;
10+
11+
use PrestaShop\PrestaShop\Adapter\Language\LanguageDataProvider;
12+
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
13+
14+
/**
15+
* Fills empty/missing localized values with the default language value, for every active language.
16+
*
17+
* This reproduces the legacy back office auto-fill behavior at the CQRS level, so it applies whatever
18+
* builds the command: a form, an ajax call that only provides the current language, or the Admin API.
19+
*/
20+
class LocalizedNamesFiller
21+
{
22+
public function __construct(
23+
private readonly LanguageDataProvider $languageDataProvider,
24+
private readonly ConfigurationInterface $configuration,
25+
) {
26+
}
27+
28+
/**
29+
* Returns the localized values with every active language filled in.
30+
*
31+
* Non-empty values from $localizedValues are applied on top of $existingValues, so a partial
32+
* update (e.g. the ajax call that only sends the current language) keeps the languages it does
33+
* not touch. Languages that are still empty afterwards are filled with the default value.
34+
*
35+
* @param array<int, string> $localizedValues lang-ID-keyed values to apply
36+
* @param array<int, string> $existingValues lang-ID-keyed values already stored (empty on creation)
37+
*
38+
* @return array<int, string>
39+
*/
40+
public function fill(array $localizedValues, array $existingValues = []): array
41+
{
42+
$filledValues = $existingValues;
43+
foreach ($localizedValues as $languageId => $value) {
44+
if (!empty($value)) {
45+
$filledValues[(int) $languageId] = $value;
46+
}
47+
}
48+
49+
$defaultValue = $this->resolveDefaultValue($filledValues);
50+
if (null === $defaultValue) {
51+
return $filledValues;
52+
}
53+
54+
foreach ($this->languageDataProvider->getLanguages(false, false, true) as $languageId) {
55+
if (empty($filledValues[(int) $languageId])) {
56+
$filledValues[(int) $languageId] = $defaultValue;
57+
}
58+
}
59+
60+
return $filledValues;
61+
}
62+
63+
/**
64+
* Returns the value used to fill the empty languages: the default language value when set,
65+
* otherwise the first non-empty value provided (e.g. the ajax call only sends the current language).
66+
*
67+
* @param array<int, string> $localizedValues
68+
*/
69+
private function resolveDefaultValue(array $localizedValues): ?string
70+
{
71+
$defaultLanguageId = (int) $this->configuration->get('PS_LANG_DEFAULT');
72+
if (!empty($localizedValues[$defaultLanguageId])) {
73+
return $localizedValues[$defaultLanguageId];
74+
}
75+
76+
foreach ($localizedValues as $value) {
77+
if (!empty($value)) {
78+
return $value;
79+
}
80+
}
81+
82+
return null;
83+
}
84+
}

src/PrestaShopBundle/Form/Admin/Configure/AdvancedParameters/QuickAccess/QuickAccessType.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
3030
],
3131
'options' => [
3232
'constraints' => [
33-
new NotBlank([
34-
'message' => $this->trans(
35-
'The %s field is required.',
36-
'Admin.Notifications.Error',
37-
[sprintf('"%s"', $this->trans('Name', 'Admin.Global'))]
38-
),
39-
]),
4033
new Length([
4134
'max' => 32,
4235
'maxMessage' => $this->trans(

src/PrestaShopBundle/Resources/config/services/core/language.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ services:
1313
'ar': 'Tahoma'
1414

1515
PrestaShop\PrestaShop\Core\Language\ContextLanguageProviderInterface: '@PrestaShop\PrestaShop\Adapter\Language\ContextLanguageProvider'
16+
17+
PrestaShop\PrestaShop\Core\Language\LocalizedNamesFiller:
18+
autowire: true

tests/Integration/Behaviour/Features/Scenario/QuickAccess/quick_access_management.feature

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,28 @@ Feature: Quick access management
3333
| link | index.php?controller=catalog |
3434
| new_window | false |
3535

36+
Scenario: Add a quick access with only the default language name fills the other languages
37+
When I add a quick access "qa_autofill" with the following properties:
38+
| localizedNames[en-US] | Dashboard |
39+
| link | index.php?controller=dashboard |
40+
| new_window | false |
41+
Then quick access "qa_autofill" should have the following properties:
42+
| localizedNames[en-US] | Dashboard |
43+
| localizedNames[fr-FR] | Dashboard |
44+
| link | index.php?controller=dashboard |
45+
46+
Scenario: Editing only one language keeps the other languages untouched
47+
Given I add a quick access "qa_refill" with the following properties:
48+
| localizedNames[en-US] | Before |
49+
| localizedNames[fr-FR] | Untouched |
50+
| link | index.php?controller=refill |
51+
| new_window | false |
52+
When I edit quick access "qa_refill" with the following properties:
53+
| localizedNames[en-US] | After |
54+
Then quick access "qa_refill" should have the following properties:
55+
| localizedNames[en-US] | After |
56+
| localizedNames[fr-FR] | Untouched |
57+
3658
Scenario: Edit a quick access - change name
3759
Given I add a quick access "qa_edit" with the following properties:
3860
| localizedNames[en-US] | Original name |

0 commit comments

Comments
 (0)