Skip to content

Commit 2b49b51

Browse files
committed
Tweaks
1 parent 1593cc4 commit 2b49b51

File tree

6 files changed

+111
-153
lines changed

6 files changed

+111
-153
lines changed

src/Dto/ActionDto.php

+4-35
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,8 @@ final class ActionDto
1212
{
1313
private ?string $type = null;
1414
private ?string $name = null;
15-
private TranslatableInterface|string|null $label = null;
16-
17-
/**
18-
* @var (callable(object): string)|null
19-
*/
20-
private $labelCallable;
21-
15+
/** @var TranslatableInterface|string|(callable(object): string)|null */
16+
private mixed $label = null;
2217
private ?string $icon = null;
2318
private string $cssClass = '';
2419
private string $addedCssClass = '';
@@ -71,10 +66,10 @@ public function setName(string $name): void
7166

7267
public function isDynamicLabel(): bool
7368
{
74-
return \is_callable($this->labelCallable);
69+
return \is_callable($this->label);
7570
}
7671

77-
public function getLabel(): TranslatableInterface|string|false|null
72+
public function getLabel(): TranslatableInterface|string|callable|false|null
7873
{
7974
return $this->label;
8075
}
@@ -84,13 +79,6 @@ public function getLabel(): TranslatableInterface|string|false|null
8479
*/
8580
public function setLabel(TranslatableInterface|string|callable|false|null $label): void
8681
{
87-
if (\is_callable($label)) {
88-
$this->labelCallable = $label;
89-
$this->label = null;
90-
91-
return;
92-
}
93-
9482
$this->label = $label;
9583
}
9684

@@ -282,25 +270,6 @@ public function setDisplayCallable(callable $displayCallable): void
282270
$this->displayCallable = $displayCallable;
283271
}
284272

285-
public function computeLabel(EntityDto $entityDto): void
286-
{
287-
if (null !== $this->label) {
288-
return;
289-
}
290-
291-
if (!\is_callable($this->labelCallable)) {
292-
return;
293-
}
294-
295-
$label = \call_user_func_array($this->labelCallable, array_filter([$entityDto->getInstance()]));
296-
297-
if (!\is_string($label) && !$label instanceof TranslatableInterface) {
298-
throw new \RuntimeException(sprintf('Action label callable must return a string or a %s instance but it returned a(n) "%s" value instead.', TranslatableInterface::class, \gettype($label)));
299-
}
300-
301-
$this->label = $label;
302-
}
303-
304273
/**
305274
* @internal
306275
*/

src/Factory/ActionFactory.php

+30-15
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ public function processEntityActions(EntityDto $entityDto, ActionConfigDto $acti
4949
continue;
5050
}
5151

52-
$actionDto->computeLabel($entityDto);
53-
5452
// if CSS class hasn't been overridden, apply the default ones
5553
if ('' === $actionDto->getCssClass()) {
5654
$defaultCssClass = 'action-'.$actionDto->getName();
@@ -123,19 +121,7 @@ private function processAction(string $pageName, ActionDto $actionDto, ?EntityDt
123121

124122
$actionDto->setHtmlAttribute('data-action-name', $actionDto->getName());
125123

126-
if (false === $actionDto->getLabel()) {
127-
$actionDto->setHtmlAttribute('title', $actionDto->getName());
128-
} elseif (!$actionDto->getLabel() instanceof TranslatableInterface) {
129-
$translationParameters = array_merge(
130-
$defaultTranslationParameters,
131-
$actionDto->getTranslationParameters()
132-
);
133-
$label = $actionDto->getLabel();
134-
$translatableActionLabel = (null === $label || '' === $label) ? $label : t($label, $translationParameters, $translationDomain);
135-
$actionDto->setLabel($translatableActionLabel);
136-
} else {
137-
$actionDto->setLabel(TranslatableMessageBuilder::withParameters($actionDto->getLabel(), $defaultTranslationParameters));
138-
}
124+
$this->processActionLabel($actionDto, $entityDto, $translationDomain, $defaultTranslationParameters);
139125

140126
$defaultTemplatePath = $adminContext->getTemplatePath('crud/action');
141127
$actionDto->setTemplatePath($actionDto->getTemplatePath() ?? $defaultTemplatePath);
@@ -168,6 +154,35 @@ private function processAction(string $pageName, ActionDto $actionDto, ?EntityDt
168154
return $actionDto;
169155
}
170156

157+
private function processActionLabel(ActionDto $actionDto, ?EntityDto $entityDto, string $translationDomain, array $defaultTranslationParameters): void
158+
{
159+
$label = $actionDto->getLabel();
160+
161+
// FALSE means that action doesn't show a visible label in the interface
162+
if (false === $label) {
163+
$actionDto->setHtmlAttribute('title', $actionDto->getName());
164+
165+
return;
166+
}
167+
168+
if (\is_callable($label)) {
169+
$label = \call_user_func_array($label, array_filter([$entityDto?->getInstance()]));
170+
171+
if (!\is_string($label) && !$label instanceof TranslatableInterface) {
172+
throw new \RuntimeException(sprintf('The callable used to define the label of the "%s" action label %s must return a string or a %s instance but it returned a(n) "%s" value instead.', $actionDto->getName(), null !== $entityDto ? 'in the "'.$entityDto->getName().'" entity' : '', TranslatableInterface::class, \gettype($label)));
173+
}
174+
}
175+
176+
$translationParameters = array_merge($defaultTranslationParameters, $actionDto->getTranslationParameters());
177+
178+
if ($label instanceof TranslatableInterface) {
179+
$actionDto->setLabel(TranslatableMessageBuilder::withParameters($label, $translationParameters));
180+
} else {
181+
$translatableActionLabel = (null === $label || '' === $label) ? $label : t($label, $translationParameters, $translationDomain);
182+
$actionDto->setLabel($translatableActionLabel);
183+
}
184+
}
185+
171186
private function generateActionUrl(Request $request, ActionDto $actionDto, ?EntityDto $entityDto = null): string
172187
{
173188
$entityInstance = $entityDto?->getInstance();

tests/Config/ActionTest.php

+49-33
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,42 @@
33
namespace EasyCorp\Bundle\EasyAdminBundle\Tests\Config;
44

55
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
6-
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
76
use PHPUnit\Framework\TestCase;
7+
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
8+
use function Symfony\Component\Translation\t;
89

910
class ActionTest extends TestCase
1011
{
11-
public function testStringLabelForStaticLabelGeneration()
12+
use ExpectDeprecationTrait;
13+
14+
/**
15+
* @group legacy
16+
*/
17+
public function testDeprecatedActionLabels()
1218
{
13-
$actionConfig = Action::new(Action::DELETE)
14-
->setLabel('Delete Me!')
15-
->linkToCrudAction('');
19+
$this->expectDeprecation('Since easycorp/easyadmin-bundle 4.0.5: Argument "$label" for "EasyCorp\Bundle\EasyAdminBundle\Config\Action::new" must be one of these types: "Symfony\Contracts\Translation\TranslatableInterface", "string", "callable", "false" or "null". Passing type "integer" will cause an error in 5.0.0.');
20+
21+
Action::new(Action::EDIT, 7);
22+
}
23+
24+
/**
25+
* @dataProvider provideAutomaticActionLabels
26+
*/
27+
public function testActionWithAutomaticLabel(string $actionName, string $automaticLabel)
28+
{
29+
$actionConfig = Action::new($actionName)->linkToCrudAction('');
30+
31+
$this->assertSame($automaticLabel, $actionConfig->getAsDto()->getLabel());
32+
}
33+
34+
/**
35+
* @dataProvider provideActionLabels
36+
*/
37+
public function testAllPossibleValuesForActionLabels($label)
38+
{
39+
$actionConfig = Action::new(Action::EDIT, $label)->linkToCrudAction('');
1640

17-
$this->assertSame('Delete Me!', $actionConfig->getAsDto()->getLabel());
41+
$this->assertSame($label, $actionConfig->getAsDto()->getLabel());
1842
}
1943

2044
public function testCallableLabelForDynamicLabelGeneration()
@@ -29,11 +53,7 @@ public function testCallableLabelForDynamicLabelGeneration()
2953

3054
$dto = $actionConfig->getAsDto();
3155

32-
$this->assertNull($dto->getLabel());
33-
34-
$dto->computeLabel($this->getEntityDto('1337'));
35-
36-
$this->assertSame('Delete #1337', $dto->getLabel());
56+
$this->assertSame($callable, $dto->getLabel());
3757
}
3858

3959
public function testDefaultCssClass()
@@ -80,28 +100,24 @@ public function testSetAndAddCssClassWithSpaces()
80100
$this->assertSame('bar1 bar2', $actionConfig->getAsDto()->getAddedCssClass());
81101
}
82102

83-
private function getEntityDto(string $entityId): EntityDto
103+
public function provideAutomaticActionLabels(): iterable
104+
{
105+
// format: (action name, automatic label generated for the action)
106+
yield ['Edit', 'Edit'];
107+
yield ['FooBar', 'Foo Bar'];
108+
yield ['fooBar', 'Foo Bar'];
109+
yield ['foo_Bar', 'Foo Bar'];
110+
}
111+
112+
public function provideActionLabels(): iterable
84113
{
85-
$entityDtoMock = $this->createMock(EntityDto::class);
86-
$entityDtoMock
87-
->expects($this->any())
88-
->method('getInstance')
89-
->willReturn(
90-
new class($entityId) {
91-
private $entityId;
92-
93-
public function __construct(string $entityId)
94-
{
95-
$this->entityId = $entityId;
96-
}
97-
98-
public function __toString(): string
99-
{
100-
return sprintf('#%s', $this->entityId);
101-
}
102-
}
103-
);
104-
105-
return $entityDtoMock;
114+
yield [false];
115+
yield [''];
116+
yield ['Edit'];
117+
yield [fn (object $entity) => sprintf('Edit %s', $entity)];
118+
yield [static function (object $entity) {
119+
return sprintf('Edit %s', $entity);
120+
}];
121+
yield [t('Edit')];
106122
}
107123
}

tests/Controller/ActionsCrudControllerTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,13 @@ public function testCssClasses()
4242

4343
static::assertSame('action-new btn btn-primary', trim($crawler->filter('.global-actions > a')->first()->attr('class')));
4444
}
45+
46+
public function testDynamicLabels()
47+
{
48+
$crawler = $this->client->request('GET', $this->generateIndexUrl());
49+
50+
static::assertSame('Action 5: Category 0', $crawler->filter('a.dropdown-item:contains("Action 5")')->text());
51+
static::assertSame('Action 6: Category 0', $crawler->filter('a.dropdown-item:contains("Action 6")')->text());
52+
static::assertSame('Action 7: Category 0', $crawler->filter('a.dropdown-item:contains("Action 7")')->text());
53+
}
4554
}

tests/Dto/ActionDtoTest.php

-70
This file was deleted.

tests/TestApplication/src/Controller/ActionsCrudController.php

+19
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
77
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
88
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
9+
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
910
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
1011
use EasyCorp\Bundle\EasyAdminBundle\Tests\TestApplication\Entity\Category;
12+
use function Symfony\Component\Translation\t;
1113

1214
/**
1315
* Tests the configureActions() method and the generated actions.
@@ -32,15 +34,32 @@ public function configureActions(Actions $actions): Actions
3234
$action2 = Action::new('action2')->linkToCrudAction('')->setCssClass('foo');
3335
$action3 = Action::new('action3')->linkToCrudAction('')->addCssClass('bar');
3436
$action4 = Action::new('action4')->linkToCrudAction('')->setCssClass('foo')->addCssClass('bar');
37+
$action5 = Action::new('action5')->linkToCrudAction('')->setLabel(fn (Category $category) => 'Action 5: '.$category->getName());
38+
39+
$labelGenerator = new LabelGenerator();
40+
$action6 = Action::new('action6')->linkToCrudAction('')->setLabel(fn (Category $category) => $labelGenerator->generateLabel($category));
41+
42+
$action7 = Action::new('action7')->linkToCrudAction('')->setLabel(fn (Category $category) => t('Action %number%: %name%', ['%number%' => 7, '%name%' => $category->getName()]));
3543

3644
return $actions
3745
->add(Crud::PAGE_INDEX, $action1)
3846
->add(Crud::PAGE_INDEX, $action2)
3947
->add(Crud::PAGE_INDEX, $action3)
4048
->add(Crud::PAGE_INDEX, $action4)
49+
->add(Crud::PAGE_INDEX, $action5)
50+
->add(Crud::PAGE_INDEX, $action6)
51+
->add(Crud::PAGE_INDEX, $action7)
4152
->update(Crud::PAGE_INDEX, Action::NEW, function (Action $action) {
4253
return $action->setIcon('fa fa-fw fa-plus')->setLabel(false);
4354
})
4455
;
4556
}
4657
}
58+
59+
final class LabelGenerator
60+
{
61+
public function generateLabel(Category $category): string
62+
{
63+
return 'Action 6: '.$category->getName();
64+
}
65+
}

0 commit comments

Comments
 (0)