| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | /* | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  * This file is part of the Silverback API Components Bundle Project | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  * (c) Daniel West <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  * For the full copyright and license information, please view the LICENSE | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  * file that was distributed with this source code. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | namespace Silverback\ApiComponentsBundle\DataTransformer; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | use ApiPlatform\Core\DataTransformer\DataTransformerInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | use ApiPlatform\Core\Util\AttributesExtractor; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | use ApiPlatform\Core\Util\RequestParser; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | use Silverback\ApiComponentsBundle\Entity\Component\Collection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | use Silverback\ApiComponentsBundle\Exception\OutOfBoundsException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | use Silverback\ApiComponentsBundle\Helper\Collection\CollectionHelper; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | use Silverback\ApiComponentsBundle\Serializer\SerializeFormatResolver; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | use Symfony\Component\HttpFoundation\Request; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | use Symfony\Component\HttpFoundation\RequestStack; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | use Symfony\Component\Serializer\Normalizer\NormalizerInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |  * @author Daniel West <[email protected]> | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 32 |  |  |  */ | 
            
                                                                        
                            
            
                                    
            
            
                | 33 |  |  | class CollectionOutputDataTransformer implements DataTransformerInterface | 
            
                                                                        
                            
            
                                    
            
            
                | 34 |  |  | { | 
            
                                                                        
                            
            
                                    
            
            
                | 35 |  |  |     private CollectionHelper $iriConverter; | 
            
                                                                        
                            
            
                                    
            
            
                | 36 |  |  |     private CollectionDataProviderInterface $collectionDataProvider; | 
            
                                                                        
                            
            
                                    
            
            
                | 37 |  |  |     private RequestStack $requestStack; | 
            
                                                                        
                            
            
                                    
            
            
                | 38 |  |  |     private SerializerContextBuilderInterface $serializerContextBuilder; | 
            
                                                                        
                            
            
                                    
            
            
                | 39 |  |  |     private NormalizerInterface $itemNormalizer; | 
            
                                                                        
                            
            
                                    
            
            
                | 40 |  |  |     private SerializeFormatResolver $serializeFormatResolver; | 
            
                                                                        
                            
            
                                    
            
            
                | 41 |  |  |     private string $itemsPerPageParameterName; | 
            
                                                                        
                            
            
                                    
            
            
                | 42 |  |  |     private string $paginationEnabledParameterName; | 
            
                                                                        
                            
            
                                    
            
            
                | 43 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 44 |  |  |     public function __construct(CollectionHelper $iriConverter, CollectionDataProviderInterface $collectionDataProvider, RequestStack $requestStack, SerializerContextBuilderInterface $serializerContextBuilder, NormalizerInterface $itemNormalizer, SerializeFormatResolver $serializeFormatResolver, string $itemsPerPageParameterName, string $paginationEnabledParameterName) | 
            
                                                                        
                            
            
                                    
            
            
                | 45 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 46 |  |  |         $this->iriConverter = $iriConverter; | 
            
                                                                        
                            
            
                                    
            
            
                | 47 |  |  |         $this->collectionDataProvider = $collectionDataProvider; | 
            
                                                                        
                            
            
                                    
            
            
                | 48 |  |  |         $this->requestStack = $requestStack; | 
            
                                                                        
                            
            
                                    
            
            
                | 49 |  |  |         $this->serializerContextBuilder = $serializerContextBuilder; | 
            
                                                                        
                            
            
                                    
            
            
                | 50 |  |  |         $this->itemNormalizer = $itemNormalizer; | 
            
                                                                        
                            
            
                                    
            
            
                | 51 |  |  |         $this->serializeFormatResolver = $serializeFormatResolver; | 
            
                                                                        
                            
            
                                    
            
            
                | 52 |  |  |         $this->itemsPerPageParameterName = $itemsPerPageParameterName; | 
            
                                                                        
                            
            
                                    
            
            
                | 53 |  |  |         $this->paginationEnabledParameterName = $paginationEnabledParameterName; | 
            
                                                                        
                            
            
                                    
            
            
                | 54 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 55 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 56 |  |  |     public function supportsTransformation($data, string $to, array $context = []): bool | 
            
                                                                        
                            
            
                                    
            
            
                | 57 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 58 |  |  |         return $data instanceof Collection && Collection::class === $to; | 
            
                                                                        
                            
            
                                    
            
            
                | 59 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 60 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 61 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 62 |  |  |      * @param Collection $object | 
            
                                                                        
                            
            
                                    
            
            
                | 63 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 64 |  |  |     public function transform($object, string $to, array $context = []) | 
            
                                                                        
                            
            
                                    
            
            
                | 65 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  |         $parameters = $this->iriConverter->getRouterParametersFromIri($object->getResourceIri()); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                        
                            
            
                                    
            
            
                | 67 |  |  |         $attributes = AttributesExtractor::extractAttributes($parameters); | 
            
                                                                        
                            
            
                                    
            
            
                | 68 |  |  |         $request = $this->requestStack->getMasterRequest(); | 
            
                                                                        
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 70 |  |  |         if (!$this->collectionDataProvider instanceof ContextAwareCollectionDataProviderInterface) { | 
            
                                                                        
                            
            
                                    
            
            
                | 71 |  |  |             $collectionData = $this->collectionDataProvider->getCollection($attributes['resource_class'], $attributes['collection_operation_name']); | 
            
                                                                        
                            
            
                                    
            
            
                | 72 |  |  |         } else { | 
            
                                                                        
                            
            
                                    
            
            
                | 73 |  |  |             $filters = []; | 
            
                                                                        
                            
            
                                    
            
            
                | 74 |  |  |             if ($perPage = $object->getPerPage()) { | 
            
                                                                        
                            
            
                                    
            
            
                | 75 |  |  |                 $filters[$this->itemsPerPageParameterName] = $perPage; | 
            
                                                                        
                            
            
                                    
            
            
                | 76 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 77 |  |  |             if ($request) { | 
            
                                                                        
                            
            
                                    
            
            
                | 78 |  |  |                 if ($requestFilters = $this->getFilters($object, $request)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 79 |  |  |                     $filters = array_merge($filters, $requestFilters); | 
            
                                                                        
                            
            
                                    
            
            
                | 80 |  |  |                 } | 
            
                                                                        
                            
            
                                    
            
            
                | 81 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 82 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 83 |  |  |             if (isset($filters[$this->itemsPerPageParameterName]) && $filters[$this->itemsPerPageParameterName] <= 0) { | 
            
                                                                        
                            
            
                                    
            
            
                | 84 |  |  |                 $filters[$this->paginationEnabledParameterName] = false; | 
            
                                                                        
                            
            
                                    
            
            
                | 85 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 87 |  |  |             $collectionContext = ['filters' => $filters]; | 
            
                                                                        
                            
            
                                    
            
            
                | 88 |  |  |             if ($request) { | 
            
                                                                        
                            
            
                                    
            
            
                | 89 |  |  |                 // Comment copied from ApiPlatform\Core\EventListener\ReadListener | 
            
                                                                        
                            
            
                                    
            
            
                | 90 |  |  |                 // Builtin data providers are able to use the serialization context to automatically add join clauses | 
            
                                                                        
                            
            
                                    
            
            
                | 91 |  |  |                 $normalizationContext = $this->serializerContextBuilder->createFromRequest( | 
            
                                                                        
                            
            
                                    
            
            
                | 92 |  |  |                     $request, | 
            
                                                                        
                            
            
                                    
            
            
                | 93 |  |  |                     true, | 
            
                                                                        
                            
            
                                    
            
            
                | 94 |  |  |                     $attributes | 
            
                                                                        
                            
            
                                    
            
            
                | 95 |  |  |                 ); | 
            
                                                                        
                            
            
                                    
            
            
                | 96 |  |  |                 $collectionContext += $normalizationContext; | 
            
                                                                        
                            
            
                                    
            
            
                | 97 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 98 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 99 |  |  |             $collectionData = $this->collectionDataProvider->getCollection($attributes['resource_class'], Request::METHOD_GET, $collectionContext); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                        
                            
            
                                    
            
            
                | 100 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 101 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 102 |  |  |         // Pagination disabled | 
            
                                                                        
                            
            
                                    
            
            
                | 103 |  |  |         if (\is_array($collectionData)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 104 |  |  |             $collection = $collectionData; | 
            
                                                                        
                            
            
                                    
            
            
                | 105 |  |  |         } else { | 
            
                                                                        
                            
            
                                    
            
            
                | 106 |  |  |             if (!$collectionData instanceof \Traversable) { | 
            
                                                                        
                            
            
                                    
            
            
                | 107 |  |  |                 throw new OutOfBoundsException('$collectionData should be Traversable'); | 
            
                                                                        
                            
            
                                    
            
            
                | 108 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 109 |  |  |             $collection = iterator_count($collectionData) ? $collectionData : null; | 
            
                                                                        
                            
            
                                    
            
            
                | 110 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 111 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 112 |  |  |         $format = $request ? $this->serializeFormatResolver->getFormatFromRequest($request) : null; | 
            
                                                                        
                            
            
                                    
            
            
                | 113 |  |  |         $normalizerContext = [ | 
            
                                                                        
                            
            
                                    
            
            
                | 114 |  |  |             'resource_class' => $attributes['resource_class'], | 
            
                                                                        
                            
            
                                    
            
            
                | 115 |  |  |             'request_uri' => $object->getResourceIri(), | 
            
                                                                        
                            
            
                                    
            
            
                | 116 |  |  |             'jsonld_has_context' => false, | 
            
                                                                        
                            
            
                                    
            
            
                | 117 |  |  |             'api_sub_level' => null, | 
            
                                                                        
                            
            
                                    
            
            
                | 118 |  |  |             'subresource_operation_name' => Request::METHOD_GET, | 
            
                                                                        
                            
            
                                    
            
            
                | 119 |  |  |         ]; | 
            
                                                                        
                            
            
                                    
            
            
                | 120 |  |  |         $normalizedCollection = $this->itemNormalizer->normalize($collection, $format, $normalizerContext); | 
            
                                                                        
                            
            
                                    
            
            
                | 121 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 122 |  |  |         $object->setCollection($normalizedCollection); | 
            
                                                                        
                            
            
                                    
            
            
                | 123 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 124 |  |  |         return $object; | 
            
                                                                        
                            
            
                                    
            
            
                | 125 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |     private function getFilters(Collection $object, Request $request) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |         if ($queryParams = $object->getDefaultQueryParameters()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |             $request = clone $request; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |             foreach ($queryParams as $defaultKey => $defaultValue) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |                 if ($request->query->has($defaultKey)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |                     continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |                 $request->query->set($defaultKey, $defaultValue); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |             $request->server->set('QUERY_STRING', http_build_query($request->query->all())); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |         $queryString = RequestParser::getQueryString($request); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |  | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 142 |  |  |         return $queryString ? RequestParser::parseRequestParams($queryString) : null; | 
            
                                                                        
                                                                
            
                                    
            
            
                | 143 |  |  |     } | 
            
                                                                        
                                                                
            
                                    
            
            
                | 144 |  |  | } | 
            
                                                                        
                                                                
            
                                    
            
            
                | 145 |  |  |  |