1 | <?php |
||
36 | final class EagerLoadingExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface |
||
37 | { |
||
38 | private $propertyNameCollectionFactory; |
||
39 | private $propertyMetadataFactory; |
||
40 | private $resourceMetadataFactory; |
||
41 | private $maxJoins; |
||
42 | private $forceEager; |
||
43 | private $serializerContextBuilder; |
||
44 | private $requestStack; |
||
45 | |||
46 | public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, int $maxJoins = 30, bool $forceEager = true, RequestStack $requestStack = null, SerializerContextBuilderInterface $serializerContextBuilder = null) |
||
56 | |||
57 | /** |
||
58 | * {@inheritdoc} |
||
59 | */ |
||
60 | public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) |
||
74 | |||
75 | /** |
||
76 | * {@inheritdoc} |
||
77 | * The context may contain serialization groups which helps defining joined entities that are readable. |
||
78 | */ |
||
79 | public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []) |
||
99 | |||
100 | /** |
||
101 | * Joins relations to eager load. |
||
102 | * |
||
103 | * @param QueryBuilder $queryBuilder |
||
104 | * @param QueryNameGeneratorInterface $queryNameGenerator |
||
105 | * @param string $resourceClass |
||
106 | * @param bool $forceEager |
||
107 | * @param string $parentAlias |
||
108 | * @param array $propertyMetadataOptions |
||
109 | * @param bool $wasLeftJoin if the relation containing the new one had a left join, we have to force the new one to left join too |
||
110 | * @param int $joinCount the number of joins |
||
111 | * |
||
112 | * @throws RuntimeException when the max number of joins has been reached |
||
113 | */ |
||
114 | private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, bool $forceEager, string $parentAlias, array $propertyMetadataOptions = [], bool $wasLeftJoin = false, int &$joinCount = 0) |
||
167 | |||
168 | private function addSelect(QueryBuilder $queryBuilder, string $entity, string $associationAlias, array $propertyMetadataOptions) |
||
190 | |||
191 | /** |
||
192 | * Gets serializer groups if available, if not it returns the $options array. |
||
193 | * |
||
194 | * @param string $resourceClass |
||
195 | * @param array $options represents the operation name so that groups are the one of the specific operation |
||
196 | * @param string $context normalization_context or denormalization_context |
||
197 | * |
||
198 | * @return array |
||
199 | */ |
||
200 | private function getSerializerGroups(string $resourceClass, array $options, string $context): array |
||
201 | { |
||
202 | $request = null; |
||
203 | |||
204 | if (null !== $this->requestStack && null !== $this->serializerContextBuilder) { |
||
205 | $request = $this->requestStack->getCurrentRequest(); |
||
206 | } |
||
207 | |||
208 | if (null !== $this->serializerContextBuilder && null !== $request) { |
||
209 | $contextFromRequest = $this->serializerContextBuilder->createFromRequest($request, $context === 'normalization_context'); |
||
210 | |||
211 | if (isset($contextFromRequest['groups'])) { |
||
212 | return ['serializer_groups' => $contextFromRequest['groups']]; |
||
213 | } |
||
214 | } |
||
215 | |||
216 | $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); |
||
217 | |||
218 | if (isset($options['collection_operation_name'])) { |
||
219 | $context = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], $context, null, true); |
||
220 | } elseif (isset($options['item_operation_name'])) { |
||
221 | $context = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], $context, null, true); |
||
222 | } else { |
||
223 | $context = $resourceMetadata->getAttribute($context); |
||
224 | } |
||
225 | |||
226 | if (empty($context['groups'])) { |
||
227 | return $options; |
||
228 | } |
||
229 | |||
230 | return ['serializer_groups' => $context['groups']]; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Does an operation force eager? |
||
235 | * |
||
236 | * @param string $resourceClass |
||
237 | * @param array $options |
||
238 | * |
||
239 | * @return bool |
||
240 | */ |
||
241 | private function isForceEager(string $resourceClass, array $options): bool |
||
255 | } |
||
256 |