Skip to content

Commit 5d1e0cf

Browse files
committed
Updates
1 parent fb07b32 commit 5d1e0cf

7 files changed

Lines changed: 70 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [2.0.0] - xxxx-xx-xx
99

10+
### Added
11+
12+
- `ExpressionValues` to enable resolution of route parameter values via expressions by @HypeMC
13+
in https://github.com/sofascore/purgatory-bundle/pull/112
14+
1015
### Removed
1116

1217
- Symfony v5 support by @HypeMC in https://github.com/sofascore/purgatory-bundle/pull/128
18+
- `InverseValuesAwareInterface`, use dedicated builder services instead by @HypeMC
19+
in https://github.com/sofascore/purgatory-bundle/pull/123
1320

1421
## [1.3.0] - 2025-12-15
1522

docs/complex-route-params.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,38 @@ public function listAction(string $lang)
119119
In this example, multiple URLs are generated based on all values from the `LanguageCodes` enum and the raw value `XK`
120120
for the `lang` parameter.
121121

122+
### Using Values Provided by an Expression
123+
124+
You can also map route parameters to values provided dynamically using a **Symfony ExpressionLanguage** expression.
125+
This is useful when a route parameter cannot be mapped directly to a single property and needs to be composed or
126+
transformed.
127+
128+
In these expressions, the entity is available as the `obj` variable:
129+
130+
```php
131+
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\ExpressionValues;
132+
133+
#[Route('/posts-by-author/{full_name}', name: 'posts_list_by_author', methods: 'GET')]
134+
#[PurgeOn(Author::class, routeParams: ['full_name' => new ExpressionValues('obj.firstName~"-"~obj.lastName')])]
135+
public function listAction(Author $author)
136+
{
137+
}
138+
```
139+
140+
You can also add [custom Expression Language functions](custom-expression-language-functions.md) to extend the available
141+
expression syntax.
142+
122143
### Using Values Provided by a Service
123144

124-
You can also map route parameters to values provided dynamically by a service. This is particularly useful when you need
125-
route parameters that depend on context or runtime information:
145+
As an alternative to expressions, route parameter values can be provided by a service. This is particularly useful when
146+
you need route parameters that depend on context or runtime information:
126147

127148
```php
128149
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\DynamicValues;
129150

130151
#[Route('/posts/{type}', name: 'posts_list', methods: 'GET')]
131152
#[PurgeOn(Post::class, routeParams: ['type' => new DynamicValues('my_service')])]
132-
public function listAction(string $lang)
153+
public function listAction()
133154
{
134155
}
135156
```
@@ -146,7 +167,7 @@ use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\DynamicValues;
146167

147168
#[Route('/posts/{type}', name: 'posts_list', methods: 'GET')]
148169
#[PurgeOn(Post::class, routeParams: ['type' => new DynamicValues('my_service', 'property')])]
149-
public function listAction(string $lang)
170+
public function listAction()
150171
{
151172
}
152173
```

docs/custom-expression-language-functions.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Custom Expression Language Functions
22

3-
You can add custom functions to the Expression Language for use with the `if` parameter.
3+
You can add custom Expression Language functions that can be used by expressions defined in `ExpressionValues` or the
4+
`if` parameter.
45

56
```php
67
#[Route('/post/{id<\d+>}', name: 'post_details', methods: 'GET')]

docs/purge-subscriptions-using-yaml.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ posts_list:
5858
- !enum App\Enum\LanguageCodes
5959
- !raw XK
6060

61+
# Using values provided by an expression
62+
posts_list_by_author:
63+
class: App\Entity\Author
64+
route_params:
65+
full_name: !expression 'obj.firstName~"-"~obj.lastName'
66+
6167
# Using values provided by a service
6268
posts_list:
6369
class: App\Entity\Post

src/Cache/PropertyResolver/ExpressionLanguage/InverseRelationExpressionTransformer.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use Symfony\Component\PropertyInfo\PropertyReadInfo;
1010
use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
1111

12+
/**
13+
* @internal
14+
*/
1215
final class InverseRelationExpressionTransformer
1316
{
1417
public function __construct(

tests/Command/DebugCommandTest.php

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function testOptionAll(): void
5656

5757
self::assertNumberOfDisplayedSubscriptions(
5858
command: $this->command,
59-
expectedNumberOfSubscriptions: 10,
59+
expectedNumberOfSubscriptions: 12,
6060
);
6161
self::assertNumberOfDisplayedEntities(
6262
command: $this->command,
@@ -65,7 +65,7 @@ public function testOptionAll(): void
6565
);
6666
self::assertNumberOfDisplayedEntities(
6767
command: $this->command,
68-
expectedNumberOfEntities: 5,
68+
expectedNumberOfEntities: 7,
6969
entityClass: Author::class,
7070
);
7171

@@ -96,6 +96,11 @@ public function testOptionAll(): void
9696
needle: 'page: Dynamic("purgatory.get_page", null)',
9797
haystack: $display,
9898
);
99+
self::assertSubstringCount(
100+
expectedCount: 2,
101+
needle: 'full_name: Expression("obj.firstName~\"-\"~obj.lastName")',
102+
haystack: $display,
103+
);
99104
}
100105

101106
public function testOptionRoute(): void
@@ -134,7 +139,7 @@ public function testOptionRoute(): void
134139

135140
#[TestWith([Post::class, 1, Post::class, 'ANY'])]
136141
#[TestWith([Author::class, 1, Author::class, 'ANY'])]
137-
#[TestWith([Author::class.'::firstName', 2, Author::class, 'firstName'])]
142+
#[TestWith([Author::class.'::firstName', 3, Author::class, 'firstName'])]
138143
public function testOptionSubscription(string $subscriptionOption, int $numberOfSubscriptions, string $entity, string $property): void
139144
{
140145
$this->command->execute([
@@ -170,11 +175,11 @@ public function testOptionSubscriptionWithProperties(): void
170175

171176
self::assertNumberOfDisplayedSubscriptions(
172177
command: $this->command,
173-
expectedNumberOfSubscriptions: 5,
178+
expectedNumberOfSubscriptions: 7,
174179
);
175180
self::assertNumberOfDisplayedEntities(
176181
command: $this->command,
177-
expectedNumberOfEntities: 5,
182+
expectedNumberOfEntities: 7,
178183
entityClass: Author::class,
179184
);
180185
}
@@ -191,12 +196,12 @@ public function testInteractiveMode(): void
191196

192197
self::assertNumberOfDisplayedEntities(
193198
command: $this->command,
194-
expectedNumberOfEntities: 2,
199+
expectedNumberOfEntities: 3,
195200
entityClass: Author::class,
196201
);
197202
self::assertNumberOfDisplayedProperties(
198203
command: $this->command,
199-
expectedNumberOfProperties: 2,
204+
expectedNumberOfProperties: 3,
200205
property: 'lastName',
201206
);
202207
}
@@ -213,7 +218,7 @@ public function testInteractiveModeWithAllProperties(): void
213218

214219
self::assertNumberOfDisplayedEntities(
215220
command: $this->command,
216-
expectedNumberOfEntities: 5,
221+
expectedNumberOfEntities: 7,
217222
entityClass: Author::class,
218223
);
219224
self::assertNumberOfDisplayedProperties(
@@ -223,12 +228,12 @@ public function testInteractiveModeWithAllProperties(): void
223228
);
224229
self::assertNumberOfDisplayedProperties(
225230
command: $this->command,
226-
expectedNumberOfProperties: 2,
231+
expectedNumberOfProperties: 3,
227232
property: 'firstName',
228233
);
229234
self::assertNumberOfDisplayedProperties(
230235
command: $this->command,
231-
expectedNumberOfProperties: 2,
236+
expectedNumberOfProperties: 3,
232237
property: 'lastName',
233238
);
234239
}

tests/Functional/DebugCommand/Controller/PostController.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\CompoundValues;
99
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\DynamicValues;
1010
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\EnumValues;
11+
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\ExpressionValues;
1112
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\RawValues;
1213
use Sofascore\PurgatoryBundle\Attribute\Target\ForGroups;
1314
use Sofascore\PurgatoryBundle\Listener\Enum\Action;
@@ -73,4 +74,15 @@ public function list()
7374
public function filterByAuthorAndTag(Author $author)
7475
{
7576
}
77+
78+
#[Route('/author-full-name/{full_name}', 'post_filter_by_author_full_name')]
79+
#[PurgeOn(Author::class,
80+
target: ['firstName', 'lastName'],
81+
routeParams: [
82+
'full_name' => new ExpressionValues('obj.firstName~"-"~obj.lastName'),
83+
],
84+
)]
85+
public function filterByAuthorFullName()
86+
{
87+
}
7688
}

0 commit comments

Comments
 (0)