the browser-facing portion of osu!
at master 141 lines 5.1 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace App\Libraries\Transformers; 7 8use App\Transformers\TransformerAbstract; 9use InvalidArgumentException; 10use League\Fractal; 11use League\Fractal\Resource\Collection; 12use League\Fractal\Resource\Item; 13use League\Fractal\Resource\NullResource; 14use League\Fractal\Serializer\Serializer; 15 16class Scope extends Fractal\Scope 17{ 18 /** 19 * {@inheritdoc} 20 * 21 * Exactly the same as overridden function but with a $data !== null check before injectAvailableIncludeData. 22 */ 23 public function toArray(): ?array 24 { 25 [$rawData, $rawIncludedData] = $this->executeResourceTransformers(); 26 27 $serializer = $this->manager->getSerializer(); 28 29 $data = $this->serializeResource($serializer, $rawData); 30 31 // If the serializer wants the includes to be side-loaded then we'll 32 // serialize the included data and merge it with the data. 33 if ($serializer->sideloadIncludes()) { 34 //Filter out any relation that wasn't requested 35 $rawIncludedData = array_map([$this, 'filterFieldsets'], $rawIncludedData); 36 37 $includedData = $serializer->includedData($this->resource, $rawIncludedData); 38 39 // If the serializer wants to inject additional information 40 // about the included resources, it can do so now. 41 $data = $serializer->injectData($data, $rawIncludedData); 42 43 if ($this->isRootScope()) { 44 // If the serializer wants to have a final word about all 45 // the objects that are sideloaded, it can do so now. 46 $includedData = $serializer->filterIncludes( 47 $includedData, 48 $data 49 ); 50 } 51 52 $data = $data + $includedData; 53 } 54 55 if ($data !== null && !empty($this->availableIncludes)) { 56 $data = $serializer->injectAvailableIncludeData($data, $this->availableIncludes); 57 } 58 59 if ($this->resource instanceof Collection) { 60 if ($this->resource->hasCursor()) { 61 $pagination = $serializer->cursor($this->resource->getCursor()); 62 } elseif ($this->resource->hasPaginator()) { 63 $pagination = $serializer->paginator($this->resource->getPaginator()); 64 } 65 66 if (!empty($pagination)) { 67 $this->resource->setMetaValue(key($pagination), current($pagination)); 68 } 69 } 70 71 // Pull out all of OUR metadata and any custom meta data to merge with the main level data 72 $meta = $serializer->meta($this->resource->getMeta()); 73 74 // in case of returning NullResource we should return null and not to go with array_merge 75 if (is_null($data)) { 76 if (!empty($meta)) { 77 return $meta; 78 } 79 return null; 80 } 81 82 return $data + $meta; 83 } 84 85 protected function executeResourceTransformers(): array 86 { 87 $transformer = $this->resource->getTransformer(); 88 $data = $this->resource->getData(); 89 90 $transformedData = $includedData = []; 91 92 if ($this->resource instanceof Item) { 93 [$transformedData, $includedData[]] = $this->fireTransformer($transformer, $data); 94 } elseif ($this->resource instanceof Collection) { 95 foreach ($data as $value) { 96 [$itemTransformedData, $itemIncludedData] = $this->fireTransformer($transformer, $value); 97 if ($itemTransformedData !== null) { 98 $transformedData[] = $itemTransformedData; 99 $includedData[] = $itemIncludedData; 100 } 101 } 102 } elseif ($this->resource instanceof NullResource) { 103 $transformedData = null; 104 $includedData = []; 105 } else { 106 throw new InvalidArgumentException( 107 'Argument $resource should be an instance of League\Fractal\Resource\Item' 108 .' or League\Fractal\Resource\Collection' 109 ); 110 } 111 112 return [$transformedData, $includedData]; 113 } 114 115 protected function fireTransformer($transformer, $data): array 116 { 117 if ($transformer instanceof TransformerAbstract) { 118 $permission = $transformer->getRequiredPermission(); 119 if ($permission !== null && !priv_check($permission, $data)->can()) { 120 return [null, []]; 121 } 122 } 123 124 [$transformedData, $includedData] = parent::fireTransformer($transformer, $data); 125 126 if (empty($transformedData) && empty($includedData)) { 127 return [null, []]; 128 } 129 130 return [$transformedData, $includedData]; 131 } 132 133 protected function serializeResource(Serializer $serializer, $data): ?array 134 { 135 if ($data === null) { 136 return null; 137 } 138 139 return parent::serializeResource($serializer, $data); 140 } 141}