From 6d3fd98d951a2b82aa168281d80ad1244c6653be Mon Sep 17 00:00:00 2001 From: ilGala Date: Thu, 24 Sep 2020 18:13:20 +0200 Subject: [PATCH 1/7] Issues 56 and 46 fix proposal --- .../Responses/UseApiResourceTags.php | 17 +- tests/Fixtures/TestUser.php | 1 + tests/Fixtures/TestUserApiResource.php | 4 + .../TestUserApiResourceCollection.php | 8 +- .../Responses/UseApiResourceTagsTest.php | 183 ++++++++++++++---- 5 files changed, 163 insertions(+), 50 deletions(-) diff --git a/src/Extracting/Strategies/Responses/UseApiResourceTags.php b/src/Extracting/Strategies/Responses/UseApiResourceTags.php index ffb66c7d..c060c707 100644 --- a/src/Extracting/Strategies/Responses/UseApiResourceTags.php +++ b/src/Extracting/Strategies/Responses/UseApiResourceTags.php @@ -49,7 +49,7 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu $methodDocBlock = $docBlocks['method']; try { - return $this->getApiResourceResponse($methodDocBlock->getTags()); + return $this->getApiResourceResponse($methodDocBlock->getTags(), $route); } catch (Exception $e) { c::warn('Exception thrown when fetching Eloquent API resource response for [' . implode(',', $route->methods) . "] {$route->uri}."); e::dumpExceptionIfVerbose($e); @@ -64,7 +64,7 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu * * @return array|null */ - public function getApiResourceResponse(array $tags) + public function getApiResourceResponse(array $tags, Route $route) { if (empty($apiResourceTag = $this->getApiResourceTag($tags))) { return null; @@ -111,8 +111,12 @@ public function getApiResourceResponse(array $tags) : $apiResourceClass::collection($list); } + $this->endDbTransaction(); + /** @var Response $response */ - $response = $resource->toResponse(app(Request::class)); + $response = $resource->toResponse(app(Request::class)->setRouteResolver(function () use ($route) { + return $route; + })); return [ [ @@ -181,7 +185,10 @@ protected function instantiateApiResourceModel(string $type, array $factoryState $factory = Utils::getModelFactory($type, $factoryStates); try { - return $factory->create(); + $model = $factory->create(); + $model->load($relations); + + return $model; } catch (Exception $e) { // If there was no working database, it would fail. return $factory->make(); @@ -204,8 +211,6 @@ protected function instantiateApiResourceModel(string $type, array $factoryState e::dumpExceptionIfVerbose($e); } } - } finally { - $this->endDbTransaction(); } return $instance; diff --git a/tests/Fixtures/TestUser.php b/tests/Fixtures/TestUser.php index 8b9c8f32..386dbe52 100644 --- a/tests/Fixtures/TestUser.php +++ b/tests/Fixtures/TestUser.php @@ -6,6 +6,7 @@ class TestUser extends Model { + public function children() { return $this->hasMany(TestUser::class, 'parent_id'); diff --git a/tests/Fixtures/TestUserApiResource.php b/tests/Fixtures/TestUserApiResource.php index 1f79218f..7a0c57fa 100644 --- a/tests/Fixtures/TestUserApiResource.php +++ b/tests/Fixtures/TestUserApiResource.php @@ -24,6 +24,10 @@ public function toArray($request) }), ]; + if($request->route()->named('test')) { + $result['test'] = true; + } + if ($this['state1'] && $this['random-state']) { $result['state1'] = $this['state1']; $result['random-state'] = $this['random-state']; diff --git a/tests/Fixtures/TestUserApiResourceCollection.php b/tests/Fixtures/TestUserApiResourceCollection.php index 199a9901..b39f3869 100644 --- a/tests/Fixtures/TestUserApiResourceCollection.php +++ b/tests/Fixtures/TestUserApiResourceCollection.php @@ -15,11 +15,17 @@ class TestUserApiResourceCollection extends ResourceCollection */ public function toArray($request) { - return [ + $data = [ 'data' => $this->collection, 'links' => [ 'self' => 'link-value', ], ]; + + if($request->route()->named('test')) { + $data['test'] = true; + } + + return $data; } } diff --git a/tests/Strategies/Responses/UseApiResourceTagsTest.php b/tests/Strategies/Responses/UseApiResourceTagsTest.php index b87696c4..6920591c 100644 --- a/tests/Strategies/Responses/UseApiResourceTagsTest.php +++ b/tests/Strategies/Responses/UseApiResourceTagsTest.php @@ -2,11 +2,13 @@ namespace Knuckles\Scribe\Tests\Strategies\Responses; +use Illuminate\Routing\Route; use Knuckles\Scribe\Extracting\Strategies\Responses\UseApiResourceTags; use Knuckles\Scribe\ScribeServiceProvider; use Knuckles\Scribe\Tests\Fixtures\TestUser; use Knuckles\Scribe\Tools\DocumentationConfig; use Knuckles\Scribe\Tools\Utils; +use Mockery; use Mpociot\Reflection\DocBlock\Tag; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; use Orchestra\Testbench\TestCase; @@ -29,7 +31,7 @@ protected function getPackageProviders($app) return $providers; } - public function setUp(): void + public function setUp(): void { parent::setUp(); @@ -51,12 +53,18 @@ public function can_parse_apiresource_tags() { $config = new DocumentationConfig([]); + $route = Mockery::mock(Route::class); + $route->shouldReceive('named') + ->once() + ->with('test') + ->andReturn(true); + $strategy = new UseApiResourceTags($config); $tags = [ new Tag('apiResource', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResource'), new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser'), ]; - $results = $strategy->getApiResourceResponse($tags); + $results = $strategy->getApiResourceResponse($tags, $route); $this->assertArraySubset([ [ @@ -66,6 +74,7 @@ public function can_parse_apiresource_tags() 'id' => 4, 'name' => 'Tested Again', 'email' => 'a@b.com', + 'test' => true ], ]), ], @@ -77,12 +86,18 @@ public function can_parse_apiresource_tags_with_model_factory_states() { $config = new DocumentationConfig([]); + $route = Mockery::mock(Route::class); + $route->shouldReceive('named') + ->once() + ->with('test') + ->andReturn(true); + $strategy = new UseApiResourceTags($config); $tags = [ new Tag('apiResource', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResource'), new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser states=state1,random-state'), ]; - $results = $strategy->getApiResourceResponse($tags); + $results = $strategy->getApiResourceResponse($tags, $route); $this->assertArraySubset([ [ @@ -92,6 +107,7 @@ public function can_parse_apiresource_tags_with_model_factory_states() 'id' => 4, 'name' => 'Tested Again', 'email' => 'a@b.com', + 'test' => true, 'state1' => true, 'random-state' => true, ], @@ -100,58 +116,120 @@ public function can_parse_apiresource_tags_with_model_factory_states() ], $results); } - /** @test */ - public function loads_specified_relations_for_model() - { - $factory = app(\Illuminate\Database\Eloquent\Factory::class); - $factory->afterMaking(TestUser::class, function (TestUser $user, $faker) { - if ($user->id === 4) { - $child = Utils::getModelFactory(TestUser::class)->make(['id' => 5, 'parent_id' => 4]); - $user->setRelation('children', collect([$child])); - } - }); + /** @test */ + public function loads_specified_relations_for_model() + { + $factory = app(\Illuminate\Database\Eloquent\Factory::class); + $factory->afterMaking(TestUser::class, function (TestUser $user, $faker) { + if ($user->id === 4) { + $child = Utils::getModelFactory(TestUser::class)->make(['id' => 5, 'parent_id' => 4]); + $user->setRelation('children', collect([$child])); + } + }); - $config = new DocumentationConfig([]); + $config = new DocumentationConfig([]); - $strategy = new UseApiResourceTags($config); - $tags = [ - new Tag('apiResource', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResource'), - new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser'), - ]; - $results = $strategy->getApiResourceResponse($tags); + $route = Mockery::mock(Route::class); + $route->shouldReceive('named') + ->times(2) + ->with('test') + ->andReturn(true); - $this->assertArraySubset([ - [ - 'status' => 200, - 'content' => json_encode([ - 'data' => [ - 'id' => 4, - 'name' => 'Tested Again', - 'email' => 'a@b.com', - 'children' => [ - [ - 'id' => 5, - 'name' => 'Tested Again', - 'email' => 'a@b.com', + $strategy = new UseApiResourceTags($config); + $tags = [ + new Tag('apiResource', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResource'), + new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser'), + ]; + $results = $strategy->getApiResourceResponse($tags, $route); + + $this->assertArraySubset([ + [ + 'status' => 200, + 'content' => json_encode([ + 'data' => [ + 'id' => 4, + 'name' => 'Tested Again', + 'email' => 'a@b.com', + 'children' => [ + [ + 'id' => 5, + 'name' => 'Tested Again', + 'email' => 'a@b.com', + "test" => true + ], ], + "test" => true ], - ], - ]), - ], - ], $results); - } + ]), + ], + ], $results); + } + + /** @test */ + public function loads_specified_relations_for_generated_model() + { + $factory = app(\Illuminate\Database\Eloquent\Factory::class); + $factory->afterMaking(TestUser::class, function (TestUser $user, $faker) { + if ($user->id === 4) { + $child = Utils::getModelFactory(TestUser::class)->make(['id' => 5, 'parent_id' => 4]); + $user->setRelation('children', collect([$child])); + } + }); + $config = new DocumentationConfig([]); + + $route = Mockery::mock(Route::class); + $route->shouldReceive('named') + ->times(2) + ->with('test') + ->andReturn(true); + + $strategy = new UseApiResourceTags($config); + $tags = [ + new Tag('apiResource', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResource'), + new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser with=children') + ]; + $results = $strategy->getApiResourceResponse($tags, $route); + + $this->assertArraySubset([ + [ + 'status' => 200, + 'content' => json_encode([ + 'data' => [ + 'id' => 4, + 'name' => 'Tested Again', + 'email' => 'a@b.com', + 'children' => [ + [ + 'id' => 5, + 'name' => 'Tested Again', + 'email' => 'a@b.com', + 'test' => true + ], + ], + 'test' => true + ], + ]), + ], + ], $results); + } /** @test */ public function can_parse_apiresourcecollection_tags() { $config = new DocumentationConfig([]); + $route = Mockery::mock(Route::class); + $route->shouldReceive('named') + ->times(2) + ->with('test') + ->andReturn(true); + $strategy = new UseApiResourceTags($config); $tags = [ new Tag('apiResourceCollection', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResource'), new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser'), ]; - $results = $strategy->getApiResourceResponse($tags); + $results = $strategy->getApiResourceResponse($tags, $route); $this->assertArraySubset([ [ @@ -162,11 +240,13 @@ public function can_parse_apiresourcecollection_tags() 'id' => 4, 'name' => 'Tested Again', 'email' => 'a@b.com', + 'test' => true, ], [ 'id' => 4, 'name' => 'Tested Again', 'email' => 'a@b.com', + 'test' => true, ], ], ]), @@ -179,12 +259,18 @@ public function can_parse_apiresourcecollection_tags_with_collection_class() { $config = new DocumentationConfig([]); + $route = Mockery::mock(Route::class); + $route->shouldReceive('named') + ->times(3) + ->with('test') + ->andReturn(true); + $strategy = new UseApiResourceTags($config); $tags = [ - new Tag('apiResourceCollection', 'Knuckles\Scribe\Tests\Fixtures\TestUserApiResourceCollection'), + new Tag('apiResourceCollection', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResourceCollection'), new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser'), ]; - $results = $strategy->getApiResourceResponse($tags); + $results = $strategy->getApiResourceResponse($tags, $route); $this->assertArraySubset([ [ @@ -195,16 +281,19 @@ public function can_parse_apiresourcecollection_tags_with_collection_class() 'id' => 4, 'name' => 'Tested Again', 'email' => 'a@b.com', + 'test' => true ], [ 'id' => 4, 'name' => 'Tested Again', 'email' => 'a@b.com', + 'test' => true ], ], 'links' => [ 'self' => 'link-value', ], + 'test' => true, ]), ], ], $results); @@ -215,12 +304,18 @@ public function can_parse_apiresourcecollection_tags_with_collection_class_and_p { $config = new DocumentationConfig([]); + $route = Mockery::mock(Route::class); + $route->shouldReceive('named') + ->times(2) + ->with('test') + ->andReturn(true); + $strategy = new UseApiResourceTags($config); $tags = [ - new Tag('apiResourceCollection', 'Knuckles\Scribe\Tests\Fixtures\TestUserApiResourceCollection'), + new Tag('apiResourceCollection', '\Knuckles\Scribe\Tests\Fixtures\TestUserApiResourceCollection'), new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestUser paginate=1,simple'), ]; - $results = $strategy->getApiResourceResponse($tags); + $results = $strategy->getApiResourceResponse($tags, $route); $this->assertArraySubset([ [ @@ -231,6 +326,7 @@ public function can_parse_apiresourcecollection_tags_with_collection_class_and_p 'id' => 4, 'name' => 'Tested Again', 'email' => 'a@b.com', + 'test' => true, ], ], 'links' => [ @@ -240,6 +336,7 @@ public function can_parse_apiresourcecollection_tags_with_collection_class_and_p "prev" => null, "next" => '/?page=2', ], + 'test' => true, "meta" => [ "current_page" => 1, "from" => 1, From c1c4292757ab91d1ef3160141628ec0153fa70dc Mon Sep 17 00:00:00 2001 From: ilGala Date: Thu, 24 Sep 2020 18:37:32 +0200 Subject: [PATCH 2/7] Transaction fix --- .../Responses/UseApiResourceTags.php | 92 ++++++++++--------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/src/Extracting/Strategies/Responses/UseApiResourceTags.php b/src/Extracting/Strategies/Responses/UseApiResourceTags.php index c060c707..b4634f97 100644 --- a/src/Extracting/Strategies/Responses/UseApiResourceTags.php +++ b/src/Extracting/Strategies/Responses/UseApiResourceTags.php @@ -66,53 +66,60 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu */ public function getApiResourceResponse(array $tags, Route $route) { - if (empty($apiResourceTag = $this->getApiResourceTag($tags))) { - return null; - } + try { + $this->startDbTransaction(); - [$statusCode, $apiResourceClass] = $this->getStatusCodeAndApiResourceClass($apiResourceTag); - [$model, $factoryStates, $relations, $pagination] = $this->getClassToBeTransformedAndAttributes($tags); - $modelInstance = $this->instantiateApiResourceModel($model, $factoryStates, $relations); + if (empty($apiResourceTag = $this->getApiResourceTag($tags))) { + return null; + } - try { - $resource = new $apiResourceClass($modelInstance); - } catch (Exception $e) { - // If it is a ResourceCollection class, it might throw an error - // when trying to instantiate with something other than a collection - $resource = new $apiResourceClass(collect([$modelInstance])); - } - if (strtolower($apiResourceTag->getName()) == 'apiresourcecollection') { - // Collections can either use the regular JsonResource class (via `::collection()`, - // or a ResourceCollection (via `new`) - // See https://laravel.com/docs/5.8/eloquent-resources - $models = [$modelInstance, $this->instantiateApiResourceModel($model, $factoryStates, $relations)]; - // Pagination can be in two forms: - // [15] : means ::paginate(15) - // [15, 'simple'] : means ::simplePaginate(15) - if (count($pagination) == 1) { - $perPage = $pagination[0]; - $paginator = new LengthAwarePaginator( - // For some reason, the LengthAware paginator needs only first page items to work correctly - collect($models)->slice(0, $perPage), - count($models), - $perPage - ); - $list = $paginator; - } elseif (count($pagination) == 2 && $pagination[1] == 'simple') { - $perPage = $pagination[0]; - $paginator = new Paginator($models, $perPage); - $list = $paginator; - } else { - $list = collect($models); + [$statusCode, $apiResourceClass] = $this->getStatusCodeAndApiResourceClass($apiResourceTag); + [$model, $factoryStates, $relations, $pagination] = $this->getClassToBeTransformedAndAttributes($tags); + $modelInstance = $this->instantiateApiResourceModel($model, $factoryStates, $relations); + + try { + $resource = new $apiResourceClass($modelInstance); + } catch (Exception $e) { + // If it is a ResourceCollection class, it might throw an error + // when trying to instantiate with something other than a collection + $resource = new $apiResourceClass(collect([$modelInstance])); } - /** @var JsonResource $resource */ - $resource = $resource instanceof ResourceCollection - ? new $apiResourceClass($list) - : $apiResourceClass::collection($list); + if (strtolower($apiResourceTag->getName()) == 'apiresourcecollection') { + // Collections can either use the regular JsonResource class (via `::collection()`, + // or a ResourceCollection (via `new`) + // See https://laravel.com/docs/5.8/eloquent-resources + $models = [$modelInstance, $this->instantiateApiResourceModel($model, $factoryStates, $relations)]; + // Pagination can be in two forms: + // [15] : means ::paginate(15) + // [15, 'simple'] : means ::simplePaginate(15) + if (count($pagination) == 1) { + $perPage = $pagination[0]; + $paginator = new LengthAwarePaginator( + // For some reason, the LengthAware paginator needs only first page items to work correctly + collect($models)->slice(0, $perPage), + count($models), + $perPage + ); + $list = $paginator; + } elseif (count($pagination) == 2 && $pagination[1] == 'simple') { + $perPage = $pagination[0]; + $paginator = new Paginator($models, $perPage); + $list = $paginator; + } else { + $list = collect($models); + } + /** @var JsonResource $resource */ + $resource = $resource instanceof ResourceCollection + ? new $apiResourceClass($list) + : $apiResourceClass::collection($list); + } + } catch (Exception $e) { + c::debug($e->getMessage()); + e::dumpExceptionIfVerbose($e); + } finally { + $this->endDbTransaction(); } - $this->endDbTransaction(); - /** @var Response $response */ $response = $resource->toResponse(app(Request::class)->setRouteResolver(function () use ($route) { return $route; @@ -175,7 +182,6 @@ private function getClassToBeTransformedAndAttributes(array $tags): array */ protected function instantiateApiResourceModel(string $type, array $factoryStates = [], array $relations = []) { - $this->startDbTransaction(); try { // Try Eloquent model factory From 51afafe08b5ed28e3c79864663a55e5dffab8889 Mon Sep 17 00:00:00 2001 From: ilGala Date: Thu, 24 Sep 2020 21:34:40 +0200 Subject: [PATCH 3/7] Transaction fix --- .../Responses/UseApiResourceTags.php | 93 +++++++++---------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/src/Extracting/Strategies/Responses/UseApiResourceTags.php b/src/Extracting/Strategies/Responses/UseApiResourceTags.php index b4634f97..4e3ef42f 100644 --- a/src/Extracting/Strategies/Responses/UseApiResourceTags.php +++ b/src/Extracting/Strategies/Responses/UseApiResourceTags.php @@ -49,11 +49,14 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu $methodDocBlock = $docBlocks['method']; try { + $this->startDbTransaction(); return $this->getApiResourceResponse($methodDocBlock->getTags(), $route); } catch (Exception $e) { c::warn('Exception thrown when fetching Eloquent API resource response for [' . implode(',', $route->methods) . "] {$route->uri}."); e::dumpExceptionIfVerbose($e); return null; + } finally { + $this->endDbTransaction(); } } @@ -66,60 +69,52 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu */ public function getApiResourceResponse(array $tags, Route $route) { - try { - $this->startDbTransaction(); - - if (empty($apiResourceTag = $this->getApiResourceTag($tags))) { - return null; - } + if (empty($apiResourceTag = $this->getApiResourceTag($tags))) { + return null; + } - [$statusCode, $apiResourceClass] = $this->getStatusCodeAndApiResourceClass($apiResourceTag); - [$model, $factoryStates, $relations, $pagination] = $this->getClassToBeTransformedAndAttributes($tags); - $modelInstance = $this->instantiateApiResourceModel($model, $factoryStates, $relations); + [$statusCode, $apiResourceClass] = $this->getStatusCodeAndApiResourceClass($apiResourceTag); + [$model, $factoryStates, $relations, $pagination] = $this->getClassToBeTransformedAndAttributes($tags); + $modelInstance = $this->instantiateApiResourceModel($model, $factoryStates, $relations); - try { - $resource = new $apiResourceClass($modelInstance); - } catch (Exception $e) { - // If it is a ResourceCollection class, it might throw an error - // when trying to instantiate with something other than a collection - $resource = new $apiResourceClass(collect([$modelInstance])); - } - if (strtolower($apiResourceTag->getName()) == 'apiresourcecollection') { - // Collections can either use the regular JsonResource class (via `::collection()`, - // or a ResourceCollection (via `new`) - // See https://laravel.com/docs/5.8/eloquent-resources - $models = [$modelInstance, $this->instantiateApiResourceModel($model, $factoryStates, $relations)]; - // Pagination can be in two forms: - // [15] : means ::paginate(15) - // [15, 'simple'] : means ::simplePaginate(15) - if (count($pagination) == 1) { - $perPage = $pagination[0]; - $paginator = new LengthAwarePaginator( - // For some reason, the LengthAware paginator needs only first page items to work correctly - collect($models)->slice(0, $perPage), - count($models), - $perPage - ); - $list = $paginator; - } elseif (count($pagination) == 2 && $pagination[1] == 'simple') { - $perPage = $pagination[0]; - $paginator = new Paginator($models, $perPage); - $list = $paginator; - } else { - $list = collect($models); - } - /** @var JsonResource $resource */ - $resource = $resource instanceof ResourceCollection - ? new $apiResourceClass($list) - : $apiResourceClass::collection($list); + try { + $resource = new $apiResourceClass($modelInstance); + } catch (Exception $e) { + // If it is a ResourceCollection class, it might throw an error + // when trying to instantiate with something other than a collection + $resource = new $apiResourceClass(collect([$modelInstance])); + } + if (strtolower($apiResourceTag->getName()) == 'apiresourcecollection') { + // Collections can either use the regular JsonResource class (via `::collection()`, + // or a ResourceCollection (via `new`) + // See https://laravel.com/docs/5.8/eloquent-resources + $models = [$modelInstance, $this->instantiateApiResourceModel($model, $factoryStates, $relations)]; + // Pagination can be in two forms: + // [15] : means ::paginate(15) + // [15, 'simple'] : means ::simplePaginate(15) + if (count($pagination) == 1) { + $perPage = $pagination[0]; + $paginator = new LengthAwarePaginator( + // For some reason, the LengthAware paginator needs only first page items to work correctly + collect($models)->slice(0, $perPage), + count($models), + $perPage + ); + $list = $paginator; + } elseif (count($pagination) == 2 && $pagination[1] == 'simple') { + $perPage = $pagination[0]; + $paginator = new Paginator($models, $perPage); + $list = $paginator; + } else { + $list = collect($models); } - } catch (Exception $e) { - c::debug($e->getMessage()); - e::dumpExceptionIfVerbose($e); - } finally { - $this->endDbTransaction(); + /** @var JsonResource $resource */ + $resource = $resource instanceof ResourceCollection + ? new $apiResourceClass($list) + : $apiResourceClass::collection($list); } + /** @var Response $response */ $response = $resource->toResponse(app(Request::class)->setRouteResolver(function () use ($route) { return $route; From 1f8ce41e23f688748af4c15f72f0ebc8f2a77df6 Mon Sep 17 00:00:00 2001 From: ilGala Date: Fri, 25 Sep 2020 09:14:57 +0200 Subject: [PATCH 4/7] Fixed transactions also for `Knuckles\Scribe\Extracting\Strategies\Responses\UseTransformerTags` class. --- src/Extracting/Strategies/Responses/UseApiResourceTags.php | 3 +++ src/Extracting/Strategies/Responses/UseTransformerTags.php | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Extracting/Strategies/Responses/UseApiResourceTags.php b/src/Extracting/Strategies/Responses/UseApiResourceTags.php index 4e3ef42f..fc3e2dfa 100644 --- a/src/Extracting/Strategies/Responses/UseApiResourceTags.php +++ b/src/Extracting/Strategies/Responses/UseApiResourceTags.php @@ -54,6 +54,7 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu } catch (Exception $e) { c::warn('Exception thrown when fetching Eloquent API resource response for [' . implode(',', $route->methods) . "] {$route->uri}."); e::dumpExceptionIfVerbose($e); + return null; } finally { $this->endDbTransaction(); @@ -65,7 +66,9 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu * * @param Tag[] $tags * + * @param \Illuminate\Routing\Route $route * @return array|null + * @throws \Exception */ public function getApiResourceResponse(array $tags, Route $route) { diff --git a/src/Extracting/Strategies/Responses/UseTransformerTags.php b/src/Extracting/Strategies/Responses/UseTransformerTags.php index 30e6588f..67d078b9 100644 --- a/src/Extracting/Strategies/Responses/UseTransformerTags.php +++ b/src/Extracting/Strategies/Responses/UseTransformerTags.php @@ -47,12 +47,15 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionFu $methodDocBlock = $docBlocks['method']; try { + $this->startDbTransaction(); return $this->getTransformerResponse($methodDocBlock->getTags()); } catch (Exception $e) { c::warn('Exception thrown when fetching transformer response for [' . implode(',', $route->methods) . "] {$route->uri}."); e::dumpExceptionIfVerbose($e); return null; + } finally { + $this->endDbTransaction(); } } @@ -160,7 +163,6 @@ private function getClassToBeTransformed(array $tags, ReflectionFunctionAbstract protected function instantiateTransformerModel(string $type, array $factoryStates = [], array $relations = []) { - $this->startDbTransaction(); try { // try Eloquent model factory @@ -193,8 +195,6 @@ protected function instantiateTransformerModel(string $type, array $factoryState e::dumpExceptionIfVerbose($e); } } - } finally { - $this->endDbTransaction(); } return $instance; From a9ec31ae523a4958fddca00951dc8a4af3cfc298 Mon Sep 17 00:00:00 2001 From: Shalvah Date: Thu, 1 Oct 2020 08:19:10 +0100 Subject: [PATCH 5/7] Update UseApiResourceTagsTest.php --- tests/Strategies/Responses/UseApiResourceTagsTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Strategies/Responses/UseApiResourceTagsTest.php b/tests/Strategies/Responses/UseApiResourceTagsTest.php index 6920591c..b17f0e25 100644 --- a/tests/Strategies/Responses/UseApiResourceTagsTest.php +++ b/tests/Strategies/Responses/UseApiResourceTagsTest.php @@ -177,6 +177,7 @@ public function loads_specified_relations_for_generated_model() }); $config = new DocumentationConfig([]); + // Creating a mock route so we can test that the route is set properly during resolution $route = Mockery::mock(Route::class); $route->shouldReceive('named') ->times(2) From 640af34d029a6a3a6498e1af613a3b5818bfb8b3 Mon Sep 17 00:00:00 2001 From: Shalvah Date: Thu, 1 Oct 2020 08:22:31 +0100 Subject: [PATCH 6/7] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 733ae0e8..2af08897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project aims to adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.9.0 (Thursday, 1 October, 2020) +### Changes +- Start database transaction much earlier and close it much later for ApiResource and Transformer strategies. Also set current route properly when resolving (https://github.com/knuckleswtf/scribe/pull/104) + ## 1.8.3 (Thursday, 17 September, 2020) ### Fixes - Reverts 1.8.2 as it broke a few things (https://github.com/knuckleswtf/scribe/commit/5a2217513945bcb92ca26e463f7717c0efb99ac1) From ecdb5a925e0afc4c26f1508f94dcbadf86e41a7e Mon Sep 17 00:00:00 2001 From: Shalvah Date: Thu, 1 Oct 2020 08:29:52 +0100 Subject: [PATCH 7/7] Update customization.md --- docs/customization.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/customization.md b/docs/customization.md index 532bcfc4..3319c1e0 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -67,12 +67,12 @@ In the template, you have the `$baseUrl` and `$route` variables available to you .. Important:: Parameters which have been excluded from the example requests (see `Specifying Example Values `_) will not be present in :code:`cleanQueryParameters`, :code:`cleanBodyParameters`, or :code:`fileParameters`. ``` +Finally, add the language to the `example_languages` array in your config and generate your documentation as usual. + ```eval_rst -.. Tip:: You can make use of some utilities in the class :code:`\Knuckles\Scribe\Tools\WritingUtils` to help you easily output data in various forms (such as in key=value format or as a PHP array). Please take a look at that class and its usages in the included example request templates for details. +.. Note:: Scribe makes use of CSS from [ighlight.js](https://highlightjs.org) for its syntax highlighting. The bundle we use only includes support for a bunch of the most popular languages. If your language isn't supported (all code appears white), you can [download a new CSS bundle](https://highlightjs.org/download/) yourself, and include your desired language. Then locate the highlight.js CSS file that Scribe outputs for you after generation, and replace that with the one you downloaded. ``` -Finally, add the language to the `example_languages` array in your config and generate your documentation as usual. - ## Customizing the code used in examples Customising existing language templates follows the same process as described above: publish assets, then modify the Blade templates in `resources/views/vendor/scribe/partials/example-requests` as necessary. @@ -124,4 +124,4 @@ There are also a number of included components that you can utilize in your Blad - `badges/base.blade.php`: The base badge component, used by `auth` and `http-method`. Takes in `colour` and `text` attributes, and uses Pastel's badge classes to create a badge. ## Changing the CSS styles -The CSS styling is provided by Pastel, which currently supports only one template. Consider making a pull request to add your alternative styles. +The CSS styling is provided by Pastel, which currently supports only one template. Consider making a pull request to add your alternative styles. In the meantime, you can manualy add CSS files to the generated output directory.