Skip to content

Commit 1ac87a7

Browse files
committed
Extract inverse values builders into services
1 parent d65edca commit 1ac87a7

15 files changed

Lines changed: 273 additions & 96 deletions

config/services.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
use Sofascore\PurgatoryBundle\Cache\Configuration\ConfigurationLoader;
99
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\AssociationResolver;
1010
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\EmbeddableResolver;
11+
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\InverseValuesBuilder\CompoundInverseValuesBuilder;
12+
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\InverseValuesBuilder\DynamicInverseValuesBuilder;
13+
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\InverseValuesBuilder\PropertyInverseValuesBuilder;
1114
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\MethodResolver;
1215
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\PropertyResolver;
1316
use Sofascore\PurgatoryBundle\Cache\RouteMetadata\AttributeMetadataProvider;
@@ -37,6 +40,7 @@
3740
use Sofascore\PurgatoryBundle\RouteProvider\RemovedEntityRouteProvider;
3841
use Sofascore\PurgatoryBundle\RouteProvider\UpdatedEntityRouteProvider;
3942
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
43+
use Symfony\Component\HttpKernel\Kernel;
4044

4145
return static function (ContainerConfigurator $container) {
4246
$container->services()
@@ -93,6 +97,7 @@
9397
->tag('purgatory.subscription_resolver')
9498
->args([
9599
service('property_info.reflection_extractor'),
100+
tagged_locator('purgatory.inverse_values_builder', defaultIndexMethod: 'for'),
96101
])
97102

98103
->set('sofascore.purgatory.subscription_resolver.embeddable', EmbeddableResolver::class)
@@ -101,6 +106,20 @@
101106
service('doctrine'),
102107
])
103108

109+
->set('sofascore.purgatory.inverse_values_builder.compound', CompoundInverseValuesBuilder::class)
110+
->tag('purgatory.inverse_values_builder')
111+
->args([
112+
Kernel::MAJOR_VERSION <= 5
113+
? tagged_locator('purgatory.inverse_values_builder', defaultIndexMethod: 'for')
114+
: tagged_locator('purgatory.inverse_values_builder', defaultIndexMethod: 'for', excludeSelf: false),
115+
])
116+
117+
->set('sofascore.purgatory.inverse_values_builder.dynamic', DynamicInverseValuesBuilder::class)
118+
->tag('purgatory.inverse_values_builder')
119+
120+
->set('sofascore.purgatory.inverse_values_builder.property', PropertyInverseValuesBuilder::class)
121+
->tag('purgatory.inverse_values_builder')
122+
104123
->set('sofascore.purgatory.configuration_loader', ConfigurationLoader::class)
105124
->args([
106125
service('sofascore.purgatory.purge_subscription_provider'),

phpstan-baseline.neon

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
11
parameters:
22
ignoreErrors:
3-
-
4-
message: '#^Comparison operation "\>" between 8 and 5 is always true\.$#'
5-
identifier: greater.alwaysTrue
6-
count: 1
7-
path: src/Attribute/RouteParamValue/DynamicValues.php
8-
93
-
104
message: '#^Call to function is_a\(\) with arguments class\-string\<BackedEnum\>, ''BackedEnum'' and true will always evaluate to true\.$#'
115
identifier: function.alreadyNarrowedType
126
count: 1
137
path: src/Attribute/RouteParamValue/EnumValues.php
148

15-
-
16-
message: '#^Comparison operation "\>" between 8 and 5 is always true\.$#'
17-
identifier: greater.alwaysTrue
18-
count: 1
19-
path: src/Attribute/RouteParamValue/PropertyValues.php
20-
219
-
2210
message: '#^Parameter \#1 \$configuration of class Sofascore\\PurgatoryBundle\\Cache\\Configuration\\Configuration constructor expects array\<non\-empty\-string, list\<array\{routeName\: string, routeParams\?\: array\<string, array\{type\: string, values\: list\<mixed\>, optional\?\: true\}\>, if\?\: string, actions\?\: non\-empty\-list\<Sofascore\\PurgatoryBundle\\Listener\\Enum\\Action\>\}\>\>, mixed given\.$#'
2311
identifier: argument.type
@@ -36,6 +24,18 @@ parameters:
3624
count: 1
3725
path: src/Cache/PropertyResolver/AssociationResolver.php
3826

27+
-
28+
message: '#^Comparison operation "\>" between 8 and 5 is always true\.$#'
29+
identifier: greater.alwaysTrue
30+
count: 1
31+
path: src/Cache/PropertyResolver/InverseValuesBuilder/DynamicInverseValuesBuilder.php
32+
33+
-
34+
message: '#^Comparison operation "\>" between 8 and 5 is always true\.$#'
35+
identifier: greater.alwaysTrue
36+
count: 1
37+
path: src/Cache/PropertyResolver/InverseValuesBuilder/PropertyInverseValuesBuilder.php
38+
3939
-
4040
message: '#^Parameter \#1 \$alias of class Sofascore\\PurgatoryBundle\\Attribute\\RouteParamValue\\DynamicValues constructor expects string, bool\|float\|int\|string\|Symfony\\Component\\Yaml\\Tag\\TaggedValue given\.$#'
4141
identifier: argument.type

psalm-baseline.xml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<files psalm-version="6.3.0@222dda8483516044c2ed7a4c3f197d7c9d6c3ddb">
2+
<files psalm-version="6.14.2@bbd217fc98c0daa0a13aea2a7f119d03ba3fc9a0">
33
<file src="src/Cache/Configuration/CachedConfigurationLoader.php">
44
<MixedArgument>
55
<code><![CDATA[require $cache->getPath()]]></code>
@@ -8,6 +8,21 @@
88
<code><![CDATA[require $cache->getPath()]]></code>
99
</UnresolvableInclude>
1010
</file>
11+
<file src="src/Cache/PropertyResolver/InverseValuesBuilder/CompoundInverseValuesBuilder.php">
12+
<InvalidArgument>
13+
<code><![CDATA[array_map(
14+
fn (ValuesInterface $values): ValuesInterface => $this->getInverseValuesBuilderFor($values)
15+
?->build($values, $associationClass, $associationTarget)
16+
?? $values,
17+
$values->getValues(),
18+
)]]></code>
19+
</InvalidArgument>
20+
</file>
21+
<file src="src/Cache/PropertyResolver/InverseValuesBuilder/DynamicInverseValuesBuilder.php">
22+
<PossiblyUndefinedArrayOffset>
23+
<code><![CDATA[$alias]]></code>
24+
</PossiblyUndefinedArrayOffset>
25+
</file>
1126
<file src="src/Cache/RouteMetadata/AttributeMetadataProvider.php">
1227
<PossiblyUndefinedArrayOffset>
1328
<code><![CDATA[$method]]></code>

src/Attribute/RouteParamValue/CompoundValues.php

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Sofascore\PurgatoryBundle\Attribute\PurgeOn;
88
use Sofascore\PurgatoryBundle\Exception\InvalidArgumentException;
99

10-
final class CompoundValues extends AbstractValues implements InverseValuesAwareInterface
10+
final class CompoundValues extends AbstractValues
1111
{
1212
/**
1313
* @var non-empty-list<ValuesInterface>
@@ -60,18 +60,6 @@ public function toArray(): array
6060
];
6161
}
6262

63-
public function buildInverseValuesFor(string $association): ValuesInterface
64-
{
65-
return new self(
66-
...array_map(
67-
static fn (ValuesInterface $values): ValuesInterface => $values instanceof InverseValuesAwareInterface
68-
? $values->buildInverseValuesFor($association)
69-
: $values,
70-
$this->values,
71-
),
72-
);
73-
}
74-
7563
public static function type(): string
7664
{
7765
return 'compound';

src/Attribute/RouteParamValue/DynamicValues.php

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
namespace Sofascore\PurgatoryBundle\Attribute\RouteParamValue;
66

7-
use Symfony\Component\HttpKernel\Kernel;
8-
9-
final class DynamicValues extends AbstractValues implements InverseValuesAwareInterface
7+
final class DynamicValues extends AbstractValues
108
{
119
/**
1210
* @param string $alias Alias defined in {@see AsRouteParamService} attribute
@@ -25,14 +23,6 @@ public function getValues(): array
2523
return [$this->alias, $this->arg];
2624
}
2725

28-
public function buildInverseValuesFor(string $association): ValuesInterface
29-
{
30-
return new self(
31-
alias: $this->alias,
32-
arg: null !== $this->arg ? \sprintf('%s%s.%s', $association, Kernel::MAJOR_VERSION > 5 ? '?' : '', $this->arg) : $association,
33-
);
34-
}
35-
3626
public static function type(): string
3727
{
3828
return 'dynamic';

src/Attribute/RouteParamValue/InverseValuesAwareInterface.php

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/Attribute/RouteParamValue/PropertyValues.php

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
namespace Sofascore\PurgatoryBundle\Attribute\RouteParamValue;
66

7-
use Symfony\Component\HttpKernel\Kernel;
8-
9-
final class PropertyValues extends AbstractValues implements InverseValuesAwareInterface
7+
final class PropertyValues extends AbstractValues
108
{
119
/** @var non-empty-list<string> */
1210
private readonly array $properties;
@@ -26,16 +24,6 @@ public function getValues(): array
2624
return $this->properties;
2725
}
2826

29-
public function buildInverseValuesFor(string $association): ValuesInterface
30-
{
31-
return new self(
32-
...array_map(
33-
static fn (string $property): string => \sprintf('%s%s.%s', $association, Kernel::MAJOR_VERSION > 5 ? '?' : '', $property),
34-
$this->properties,
35-
),
36-
);
37-
}
38-
3927
public static function type(): string
4028
{
4129
return 'property';

src/Cache/PropertyResolver/AssociationResolver.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
use Doctrine\ORM\Mapping\ClassMetadata as ORMClassMetadata;
99
use Doctrine\ORM\Mapping\OneToOneOwningSideMapping;
1010
use Doctrine\Persistence\Mapping\ClassMetadata;
11-
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\InverseValuesAwareInterface;
11+
use Psr\Container\ContainerInterface;
1212
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\ValuesInterface;
13+
use Sofascore\PurgatoryBundle\Cache\PropertyResolver\InverseValuesBuilder\InverseValuesBuilderInterface;
1314
use Sofascore\PurgatoryBundle\Cache\RouteMetadata\RouteMetadata;
1415
use Sofascore\PurgatoryBundle\Cache\Subscription\PurgeSubscription;
1516
use Sofascore\PurgatoryBundle\Exception\PropertyNotAccessibleException;
@@ -21,6 +22,7 @@ final class AssociationResolver implements SubscriptionResolverInterface
2122
{
2223
public function __construct(
2324
private readonly PropertyReadInfoExtractorInterface $extractor,
25+
private readonly ContainerInterface $inverseValuesBuilderLocator,
2426
) {
2527
}
2628

@@ -68,7 +70,9 @@ public function resolveSubscription(
6870
/** @var array<string, ValuesInterface> $inverseRouteParams */
6971
$inverseRouteParams = [];
7072
foreach ($routeParams as $routeParam => $values) {
71-
$inverseRouteParams[$routeParam] = $this->getInverseValuesFor($values, $associationTarget);
73+
$inverseRouteParams[$routeParam] = $this->getInverseValuesBuilderFor($values)
74+
?->build($values, $associationClass, $associationTarget)
75+
?? $values;
7276
}
7377

7478
if (null !== $if = $routeMetadata->purgeOn->if) {
@@ -91,9 +95,21 @@ class: $associationClass,
9195
return true;
9296
}
9397

94-
private function getInverseValuesFor(ValuesInterface $values, string $associationTarget): ValuesInterface
98+
/**
99+
* @template T of ValuesInterface
100+
*
101+
* @param T $values
102+
*
103+
* @return ?InverseValuesBuilderInterface<T>
104+
*/
105+
private function getInverseValuesBuilderFor(ValuesInterface $values): ?InverseValuesBuilderInterface
95106
{
96-
return $values instanceof InverseValuesAwareInterface ? $values->buildInverseValuesFor($associationTarget) : $values;
107+
/** @var ?InverseValuesBuilderInterface<T> $builder */
108+
$builder = $this->inverseValuesBuilderLocator->has($type = $values::type())
109+
? $this->inverseValuesBuilderLocator->get($type)
110+
: null;
111+
112+
return $builder;
97113
}
98114

99115
private function createGetter(string $class, string $property): string
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sofascore\PurgatoryBundle\Cache\PropertyResolver\InverseValuesBuilder;
6+
7+
use Psr\Container\ContainerInterface;
8+
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\CompoundValues;
9+
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\ValuesInterface;
10+
11+
/**
12+
* @implements InverseValuesBuilderInterface<CompoundValues>
13+
*/
14+
final class CompoundInverseValuesBuilder implements InverseValuesBuilderInterface
15+
{
16+
public function __construct(
17+
private readonly ContainerInterface $inverseValuesBuilderLocator,
18+
) {
19+
}
20+
21+
public static function for(): string
22+
{
23+
return CompoundValues::type();
24+
}
25+
26+
public function build(ValuesInterface $values, string $associationClass, string $associationTarget): ValuesInterface
27+
{
28+
return new CompoundValues(
29+
...array_map(
30+
fn (ValuesInterface $values): ValuesInterface => $this->getInverseValuesBuilderFor($values)
31+
?->build($values, $associationClass, $associationTarget)
32+
?? $values,
33+
$values->getValues(),
34+
),
35+
);
36+
}
37+
38+
/**
39+
* @template T of ValuesInterface
40+
*
41+
* @param T $values
42+
*
43+
* @return ?InverseValuesBuilderInterface<T>
44+
*/
45+
private function getInverseValuesBuilderFor(ValuesInterface $values): ?InverseValuesBuilderInterface
46+
{
47+
/** @var ?InverseValuesBuilderInterface<T> $builder */
48+
$builder = $this->inverseValuesBuilderLocator->has($type = $values::type())
49+
? $this->inverseValuesBuilderLocator->get($type)
50+
: null;
51+
52+
return $builder;
53+
}
54+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sofascore\PurgatoryBundle\Cache\PropertyResolver\InverseValuesBuilder;
6+
7+
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\DynamicValues;
8+
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\ValuesInterface;
9+
use Symfony\Component\HttpKernel\Kernel;
10+
11+
/**
12+
* @implements InverseValuesBuilderInterface<DynamicValues>
13+
*/
14+
final class DynamicInverseValuesBuilder implements InverseValuesBuilderInterface
15+
{
16+
public static function for(): string
17+
{
18+
return DynamicValues::type();
19+
}
20+
21+
public function build(ValuesInterface $values, string $associationClass, string $associationTarget): ValuesInterface
22+
{
23+
/** @var string $alias */
24+
[$alias, $arg] = $values->getValues();
25+
26+
return new DynamicValues(
27+
alias: $alias,
28+
arg: null !== $arg ? \sprintf('%s%s.%s', $associationTarget, Kernel::MAJOR_VERSION > 5 ? '?' : '', $arg) : $associationTarget,
29+
);
30+
}
31+
}

0 commit comments

Comments
 (0)