@@ -160,7 +160,7 @@ protected function getUpdateHandlers($id, $current_user): array {
160160 * Implementations should use $includedData to collect related resources that should be included
161161 * in the API response, such as related entities or additional data.
162162 */
163- public static function aggregateData (object $ object , array &$ includedData=[] ): array
163+ public static function aggregateData (object $ object , array &$ includedData = [], array $ aggregateFieldsets = null ): array
164164 {
165165 return [];
166166 }
@@ -561,7 +561,7 @@ protected function obj2Array(object $obj): array {
561561 * @throws NotFoundExceptionInterface
562562 * @throws ContainerExceptionInterface
563563 */
564- protected function obj2Resource (object $ obj , array &$ expandResult = []): array {
564+ protected function obj2Resource (object $ obj , array &$ expandResult = [], array $ sparseFieldsets = null , array $ aggregateFieldsets = null ): array {
565565 // Convert values to JSON supported types
566566 $ features = $ obj ->getFeatures ();
567567 $ kv = $ obj ->getKeyValueDict ();
@@ -571,6 +571,11 @@ protected function obj2Resource(object $obj, array &$expandResult = []): array {
571571
572572 $ attributes = [];
573573 $ relationships = [];
574+
575+ $ sparseFieldsetsForObj = null ;
576+ if (is_array ($ sparseFieldsets ) && array_key_exists ($ this ->getObjectTypeName ($ obj ), $ sparseFieldsets )) {
577+ $ sparseFieldsetsForObj = explode (", " , $ sparseFieldsets [$ this ->getObjectTypeName ($ obj )]);
578+ }
574579
575580 /* Collect attributes */
576581 foreach ($ features as $ name => $ feature ) {
@@ -579,6 +584,12 @@ protected function obj2Resource(object $obj, array &$expandResult = []): array {
579584 if ($ feature ['private ' ] === true ) {
580585 continue ;
581586 }
587+
588+ // If sparse fieldsets (https://jsonapi.org/format/#fetching-sparse-fieldsets) is used, return only the requested data
589+ if (is_array ($ sparseFieldsetsForObj ) && !in_array ($ feature ['alias ' ], $ sparseFieldsetsForObj )) {
590+ continue ;
591+ }
592+
582593 // Hide the primaryKey from the attributes since this is used as indentifier (id) in response
583594 if ($ feature ['pk ' ] === true ) {
584595 continue ;
@@ -590,9 +601,8 @@ protected function obj2Resource(object $obj, array &$expandResult = []): array {
590601
591602 $ attributes [$ feature ['alias ' ]] = $ apiClass ::db2json ($ feature , $ kv [$ name ]);
592603 }
593-
594- //TODO: only aggregate data when it has been included
595- $ aggregatedData = $ apiClass ::aggregateData ($ obj , $ expandResult );
604+
605+ $ aggregatedData = $ apiClass ::aggregateData ($ obj , $ expandResult , $ aggregateFieldsets );
596606 $ attributes = array_merge ($ attributes , $ aggregatedData );
597607
598608 /* Build JSON::API relationship resource */
@@ -1187,7 +1197,9 @@ protected function processExpands(
11871197 array $ expands ,
11881198 object $ object ,
11891199 array $ expandResult ,
1190- array $ includedResources
1200+ array $ includedResources ,
1201+ array $ sparseFieldsets = null ,
1202+ array $ aggregateFieldsets = null
11911203): array {
11921204
11931205 // Add missing expands to expands in case they have been added in aggregateData()
@@ -1204,14 +1216,16 @@ protected function processExpands(
12041216
12051217 if (is_array ($ expandResultObject )) {
12061218 foreach ($ expandResultObject as $ expandObject ) {
1207- $ includedResources = self ::addToRelatedResources ($ includedResources , $ apiClass ->obj2Resource ($ expandObject ));
1219+ $ noFurtherExpands = [];
1220+ $ includedResources = self ::addToRelatedResources ($ includedResources , $ apiClass ->obj2Resource ($ expandObject , $ noFurtherExpands , $ sparseFieldsets , $ aggregateFieldsets ));
12081221 }
12091222 } else {
12101223 if ($ expandResultObject === null ) {
12111224 // to-only relation which is nullable
12121225 continue ;
12131226 }
1214- $ includedResources = self ::addToRelatedResources ($ includedResources , $ apiClass ->obj2Resource ($ expandResultObject ));
1227+ $ noFurtherExpands = [];
1228+ $ includedResources = self ::addToRelatedResources ($ includedResources , $ apiClass ->obj2Resource ($ expandResultObject , $ noFurtherExpands , $ sparseFieldsets , $ aggregateFieldsets ));
12151229 }
12161230 }
12171231
@@ -1493,8 +1507,8 @@ protected static function getOneResource(object $apiClass, object $object, Reque
14931507 // Convert objects to data resources
14941508 foreach ($ objects as $ object ) {
14951509 // Create object
1496- $ newObject = $ apiClass ->obj2Resource ($ object , $ expandResult );
1497- $ includedResources = $ apiClass ->processExpands ($ apiClass , $ expands , $ object , $ expandResult , $ includedResources );
1510+ $ newObject = $ apiClass ->obj2Resource ($ object , $ expandResult, $ request -> getQueryParams ()[ ' fields ' ] ?? null , $ request -> getQueryParams ()[ ' aggregate ' ] ?? null );
1511+ $ includedResources = $ apiClass ->processExpands ($ apiClass , $ expands , $ object , $ expandResult , $ includedResources, $ request -> getQueryParams ()[ ' fields ' ] ?? null , $ request -> getQueryParams ()[ ' aggregate ' ] ?? null );
14981512
14991513 // Add to result output
15001514 $ dataResources [] = $ newObject ;
0 commit comments