diff --git a/src/Controllers/ApiDataTrait.php b/src/Controllers/ApiDataTrait.php index 76aa611ee..dbdf0f140 100644 --- a/src/Controllers/ApiDataTrait.php +++ b/src/Controllers/ApiDataTrait.php @@ -16,6 +16,7 @@ use Exceedone\Exment\Enums\SearchType; use Exceedone\Exment\Enums\ValueType; use Exceedone\Exment\Enums\ErrorCode; +use Exceedone\Exment\Enums\RelationType; use Validator; /** @@ -202,6 +203,7 @@ protected function modifyAfterGetValue(Request $request, $target, $options = []) 'id', 'target_view_id', 'children', + 'parents', ]), $options['appends'] ); @@ -267,6 +269,11 @@ protected function modifyCustomValue(Request $request, $custom_value, $recursive $custom_value = $this->modifyChildrenValue($request, $custom_value); } + // Change relation key name + if (!$recursive && $request->has('parents') && boolval($request->get('parents'))) { + $custom_value = $this->modifyParentsValue($request, $custom_value); + } + // convert to custom values $valuetype = $request->get('valuetype'); if ($request->has('valuetype') && ValueType::isRegetApiCustomValue($valuetype)) { @@ -386,10 +393,22 @@ protected function setQueryInfo($query) $query->with($relation->getRelationName()); } } + if ($request->has('parents') && boolval($request->get('parents'))) { + $relations = CustomRelation::getRelationsByChild($this->custom_table); + foreach ($relations as $relation) { + $query->with($relation->getRelationName()); + } + } return $query; } + /** + * Modify children values (exclude virtual columns from children values) + * + * @param Request $request + * @return CustomValue $custom_value + */ protected function modifyChildrenValue(Request $request, $custom_value) { $relations = CustomRelation::getRelationsByParent($this->custom_table); @@ -417,4 +436,46 @@ protected function modifyChildrenValue(Request $request, $custom_value) $custom_value['children'] = $results; return $custom_value; } + + /** + * Modify parents values (exclude virtual columns from parents values) + * + * @param Request $request + * @return CustomValue $custom_value + */ + protected function modifyParentsValue(Request $request, $custom_value) + { + $relations = CustomRelation::getRelationsByChild($this->custom_table); + + $results = []; + foreach ($relations as $relation) { + // If getted relation name, change key name + $reltionName = $relation->getRelationName(); + if (array_has($custom_value, $reltionName)) { + $relationValues = $custom_value[$reltionName]; + $makeHiddenArray = $relation->parent_custom_table_cache->getMakeHiddenArray(); + + if ($relation->relation_type == RelationType::ONE_TO_MANY) { + // Call makehidden + $relationValues = $relationValues->makeHidden($makeHiddenArray); + // Call modify custom value + $relationValues = $this->modifyCustomValue($request, $relationValues, true); + } else { + $relationValues = $relationValues->map(function ($relationValue) use ($makeHiddenArray, $request) { + // Call makehidden + $relationValue = $relationValue->makeHidden($makeHiddenArray); + // Call modify custom value + $relationValue = $this->modifyCustomValue($request, $relationValue, true); + return $relationValue; + }); + } + // Set key name + $results[$relation->parent_custom_table_cache->table_name] = $relationValues; + unset($custom_value[$reltionName]); + } + } + + $custom_value['parents'] = $results; + return $custom_value; + } } diff --git a/tests/Feature/Api2Test.php b/tests/Feature/Api2Test.php index 2618fff15..cfc4315d4 100644 --- a/tests/Feature/Api2Test.php +++ b/tests/Feature/Api2Test.php @@ -662,6 +662,56 @@ public function testGetValuesWithChildren2() } } + /** + * Getting values parents(1:N), and match ids + */ + /** + * @return void + */ + public function testGetValuesWithParents() + { + $token = $this->getAdminAccessToken([ApiScope::VALUE_READ]); + + $response = $this->withHeaders([ + 'Authorization' => "Bearer $token", + ])->get(admin_urls('api', 'data', TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE).'?parents=1&count=5') + ->assertStatus(200) + ->assertJsonCount(5, 'data'); + + // check children + $json = json_decode_ex($response->baseResponse->getContent(), true); + $data = array_get($json, 'data'); + + foreach ($data as $d) { + $this->_testParentsValues($d, TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE, array_get($d, 'id')); + } + } + + /** + * Getting values parents(N:N), and match ids + */ + /** + * @return void + */ + public function testGetValuesWithParents2() + { + $token = $this->getAdminAccessToken([ApiScope::VALUE_READ]); + + $response = $this->withHeaders([ + 'Authorization' => "Bearer $token", + ])->get(admin_urls('api', 'data', TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE_MANY_TO_MANY).'?parents=1&count=5&page=2') + ->assertStatus(200) + ->assertJsonCount(5, 'data'); + + // check children + $json = json_decode_ex($response->baseResponse->getContent(), true); + $data = array_get($json, 'data'); + + foreach ($data as $d) { + $this->_testParentsValues($d, TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE_MANY_TO_MANY, array_get($d, 'id')); + } + } + /** * @return void */ @@ -808,6 +858,52 @@ public function testGetValueWithChildren2() $this->_testChildrenValues($d, TestDefine::TESTDATA_TABLE_NAME_PARENT_TABLE_MANY_TO_MANY, array_get($d, 'id')); } + /** + * Getting value with parents, and match ids + */ + /** + * @return void + */ + public function testGetValueWithParents() + { + $token = $this->getAdminAccessToken([ApiScope::VALUE_READ]); + + $response = $this->withHeaders([ + 'Authorization' => "Bearer $token", + ])->get(admin_urls('api', 'data', TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE, '1?parents=1')) + ->assertStatus(200) + ->assertJsonFragment([ + 'id' => 1 + ]); + + // check children + $d = json_decode_ex($response->baseResponse->getContent(), true); + $this->_testParentsValues($d, TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE, array_get($d, 'id')); + } + + /** + * Getting value with parents, and match ids + */ + /** + * @return void + */ + public function testGetValueWithParents2() + { + $token = $this->getAdminAccessToken([ApiScope::VALUE_READ]); + + $response = $this->withHeaders([ + 'Authorization' => "Bearer $token", + ])->get(admin_urls('api', 'data', TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE_MANY_TO_MANY, '2?parents=1')) + ->assertStatus(200) + ->assertJsonFragment([ + 'id' => 2 + ]); + + // check children + $d = json_decode_ex($response->baseResponse->getContent(), true); + $this->_testParentsValues($d, TestDefine::TESTDATA_TABLE_NAME_CHILD_TABLE_MANY_TO_MANY, array_get($d, 'id')); + } + /** * @return void */ @@ -3038,4 +3134,55 @@ protected function _testChildrenValues($data, $table_name, $id) } } } + + /** + * @param mixed $data + * @param string $table_name + * @param mixed $id + * @return void + */ + protected function _testParentsValues($data, $table_name, $id) + { + $relations = CustomRelation::getRelationsByChild($table_name); + + // Whether has children + $this->assertTrue(array_has($data, 'parents')); + foreach ($relations as $relation) { + $this->assertTrue(array_has($data, 'parents.' . $relation->parent_custom_table_cache->table_name)); + $parents = array_get($data, 'parents.' . $relation->parent_custom_table_cache->table_name); + + if ($relation->relation_type == RelationType::ONE_TO_MANY) { + // Get value directly with parent_id + $value = $relation->child_custom_table_cache->getValueQuery()->find($id); + $parentId = array_get($parents, 'id'); + $this->assertTrue($parentId == $value->parent_id, "parent_id expects equals {$value->parent_id}', but {$parentId}."); + } + ////// Check as n:n + else { + // get parents id + $parents_ids = collect($parents)->map(function ($parent) { + return array_get($parent, 'id'); + })->toArray(); + + // Get value using pivot table + $parentIds = \DB::table($relation->getRelationName()) + ->where('child_id', $id) + ->select('parent_id') + ->distinct() + ->pluck('parent_id') + ->toArray(); + + if (count($parentIds) == 0) { + $this->assertTrue(count($parents_ids) == 0, "{$id}' parents count expects 0, but real count is " . count($parents_ids)); + } else { + foreach ($parentIds as $parentId) { + $this->assertTrue(in_array($parentId, $parents_ids), "{$parentId} expects containing {$id}' parents, but not has."); + } + foreach ($parents_ids as $parentId) { + $this->assertTrue(in_array($parentId, $parentIds), "{$parentId} expects containing {$id}' parents, but not has."); + } + } + } + } + } }