diff --git a/.prettyci.composer.json b/.prettyci.composer.json new file mode 100644 index 00000000..6d9218d1 --- /dev/null +++ b/.prettyci.composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16" + } +} diff --git a/Controller/AbstractContentController.php b/Controller/AbstractContentController.php index 837e6474..0f05c7c2 100755 --- a/Controller/AbstractContentController.php +++ b/Controller/AbstractContentController.php @@ -22,6 +22,7 @@ use Sulu\Bundle\ContentBundle\Model\Content\Query\FindContentQuery; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\MessageBusInterface; abstract class AbstractContentController implements ClassResourceInterface @@ -60,7 +61,11 @@ public function getAction(Request $request, string $id): Response $message = new FindContentQuery($this->getContentResourceKey(), $id, $request->query->get('locale')); $this->messageBus->dispatch($message); $content = $message->getContent(); - } catch (ContentNotFoundException $exception) { + } catch (HandlerFailedException $exception) { + if (!$exception->getPrevious() instanceof ContentNotFoundException) { + throw $exception; + } + // need to return an empty content-view object because the sulu frontend does not expect any errors here // TODO: review this code when subresource handling is implemented in the sulu frontend $content = new ContentView( diff --git a/Controller/AbstractExcerptController.php b/Controller/AbstractExcerptController.php index 26428482..f8cf34ad 100755 --- a/Controller/AbstractExcerptController.php +++ b/Controller/AbstractExcerptController.php @@ -23,6 +23,7 @@ use Sulu\Bundle\ContentBundle\Model\Excerpt\Query\FindExcerptQuery; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\MessageBusInterface; abstract class AbstractExcerptController implements ClassResourceInterface @@ -54,7 +55,11 @@ public function getAction(Request $request, string $id): Response $message = new FindExcerptQuery($this->getExcerptResourceKey(), $id, $request->query->get('locale')); $this->messageBus->dispatch($message); $excerpt = $message->getExcerpt(); - } catch (ExcerptNotFoundException $exception) { + } catch (HandlerFailedException $exception) { + if (!$exception->getPrevious() instanceof ExcerptNotFoundException) { + throw $exception; + } + // need to return an empty excerpt-view object because the sulu frontend does not expect any errors here // TODO: review this code when subresource handling is implemented in the sulu frontend $excerpt = new ExcerptView($this->getExcerptResourceKey(), $id, $request->query->get('locale')); diff --git a/Controller/AbstractSeoController.php b/Controller/AbstractSeoController.php index 897cd2ca..10e195a5 100755 --- a/Controller/AbstractSeoController.php +++ b/Controller/AbstractSeoController.php @@ -23,6 +23,7 @@ use Sulu\Bundle\ContentBundle\Model\Seo\SeoView; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\MessageBusInterface; abstract class AbstractSeoController implements ClassResourceInterface @@ -54,7 +55,11 @@ public function getAction(Request $request, string $id): Response $message = new FindSeoQuery($this->getSeoResourceKey(), $id, $request->query->get('locale')); $this->messageBus->dispatch($message); $seo = $message->getSeo(); - } catch (SeoNotFoundException $exception) { + } catch (HandlerFailedException $exception) { + if (!$exception->getPrevious() instanceof SeoNotFoundException) { + throw $exception; + } + // need to return an empty seo-view object because the sulu frontend does not expect any errors here // TODO: review this code when subresource handling is implemented in the sulu frontend $seo = new SeoView($this->getSeoResourceKey(), $id, $request->query->get('locale')); diff --git a/EventSubscriber/ContentViewSerializationSubscriber.php b/EventSubscriber/ContentViewSerializationSubscriber.php index 2b67d228..377739c7 100644 --- a/EventSubscriber/ContentViewSerializationSubscriber.php +++ b/EventSubscriber/ContentViewSerializationSubscriber.php @@ -16,13 +16,13 @@ use JMS\Serializer\EventDispatcher\Events; use JMS\Serializer\EventDispatcher\EventSubscriberInterface; use JMS\Serializer\EventDispatcher\ObjectEvent; -use JMS\Serializer\JsonSerializationVisitor; +use JMS\Serializer\Metadata\StaticPropertyMetadata; +use JMS\Serializer\Visitor\SerializationVisitorInterface; use Sulu\Bundle\ContentBundle\Model\Content\ContentViewInterface; use Sulu\Component\Content\Compat\StructureInterface; use Sulu\Component\Content\Compat\StructureManagerInterface; use Sulu\Component\Content\ContentTypeManagerInterface; use Sulu\Component\Content\Metadata\Factory\StructureMetadataFactoryInterface; -use Sulu\Component\Serializer\ArraySerializationVisitor; class ContentViewSerializationSubscriber implements EventSubscriberInterface { @@ -83,21 +83,16 @@ public function onPostSerializeJson(ObjectEvent $event): void return; } - /** @var JsonSerializationVisitor $visitor */ + /** @var SerializationVisitorInterface $visitor */ $visitor = $event->getVisitor(); foreach ($metadata->getProperties() as $property) { - $name = $property->getName(); - if (\is_float($name)) { - $name = (string) $name; - } - - if (\array_key_exists($name, $data)) { - $visitor->setData((string) $name, $data[$name]); + $name = (string) $property->getName(); + $value = $data[$name] ?? null; - continue; - } - - $visitor->setData((string) $name, null); + $visitor->visitProperty( + new StaticPropertyMetadata('', $name, $value), + $value + ); } } @@ -115,10 +110,20 @@ public function onPostSerializeArray(ObjectEvent $event): void $data = $object->getData() ?? []; - /** @var ArraySerializationVisitor $visitor */ + /** @var SerializationVisitorInterface $visitor */ $visitor = $event->getVisitor(); - $visitor->setData('content', $this->resolveContent($structure, $data)); - $visitor->setData('view', $this->resolveView($structure, $data)); + + $content = $this->resolveContent($structure, $data); + $visitor->visitProperty( + new StaticPropertyMetadata('', 'content', $content), + $content + ); + + $view = $this->resolveView($structure, $data); + $visitor->visitProperty( + new StaticPropertyMetadata('', 'view', $view), + $view + ); } private function getStructure(ContentViewInterface $contentView): ?StructureInterface diff --git a/Model/Excerpt/MessageHandler/ModifyExcerptMessageHandler.php b/Model/Excerpt/MessageHandler/ModifyExcerptMessageHandler.php index 519bc325..67d22004 100755 --- a/Model/Excerpt/MessageHandler/ModifyExcerptMessageHandler.php +++ b/Model/Excerpt/MessageHandler/ModifyExcerptMessageHandler.php @@ -231,10 +231,7 @@ private function findTagByName(string $tagName): TagInterface { $tag = $this->tagRepository->findTagByName($tagName); if (!$tag) { - throw EntityNotFoundException::fromClassNameAndIdentifier( - TagInterface::class, - ['name' => $tagName] - ); + throw EntityNotFoundException::fromClassNameAndIdentifier(TagInterface::class, ['name' => $tagName]); } return $tag; @@ -244,10 +241,7 @@ private function findCategoryById(int $categoryId): CategoryInterface { $category = $this->categoryRepository->findCategoryById($categoryId); if (!$category) { - throw EntityNotFoundException::fromClassNameAndIdentifier( - CategoryInterface::class, - ['id' => (string) $categoryId] - ); + throw EntityNotFoundException::fromClassNameAndIdentifier(CategoryInterface::class, ['id' => (string) $categoryId]); } return $category; @@ -258,10 +252,7 @@ private function findMediaById(int $mediaId): MediaInterface /** @var ?MediaInterface */ $media = $this->mediaRepository->findMediaById($mediaId); if (!$media) { - throw EntityNotFoundException::fromClassNameAndIdentifier( - MediaInterface::class, - ['id' => (string) $mediaId] - ); + throw EntityNotFoundException::fromClassNameAndIdentifier(MediaInterface::class, ['id' => (string) $mediaId]); } return $media; diff --git a/Tests/Functional/Controller/AbstractContentControllerTest.php b/Tests/Functional/Controller/AbstractContentControllerTest.php index 8343042d..70e8bb1a 100644 --- a/Tests/Functional/Controller/AbstractContentControllerTest.php +++ b/Tests/Functional/Controller/AbstractContentControllerTest.php @@ -44,8 +44,14 @@ public function testGet(): void $client->request('GET', '/api/test-resource-contents/test-resource-1?locale=en'); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -64,8 +70,14 @@ public function testGetAbsent(): void $client->request('GET', '/api/test-resource-contents/absent-resource?locale=en'); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -94,8 +106,14 @@ public function testPut(): void $client->request('PUT', '/api/test-resource-contents/test-resource-1?locale=en', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -124,8 +142,14 @@ public function testPutAbsent(): void $client->request('PUT', '/api/test-resource-contents/absent-resource?locale=en', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -156,8 +180,14 @@ public function testPutWithPublishAction(): void $client->request('PUT', '/api/test-resource-contents/test-resource-1?locale=en&action=publish', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -185,6 +215,6 @@ public function testDelete(): void $client->request('DELETE', '/api/test-resource-contents/test-resource-1?locale=en'); $response = $client->getResponse(); - $this->assertSame(204, $response->getStatusCode()); + $this->assertHttpStatusCode(204, $response); } } diff --git a/Tests/Functional/Controller/AbstractExcerptControllerTest.php b/Tests/Functional/Controller/AbstractExcerptControllerTest.php index 363cf141..ca325c31 100644 --- a/Tests/Functional/Controller/AbstractExcerptControllerTest.php +++ b/Tests/Functional/Controller/AbstractExcerptControllerTest.php @@ -105,8 +105,14 @@ public function testGet(): void $client->request('GET', '/api/test-resource-excerpts/test-resource-1?locale=en'); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -133,8 +139,14 @@ public function testGetAbsent(): void $client->request('GET', '/api/test-resource-excerpts/absent-resource?locale=en'); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -196,8 +208,14 @@ public function testPut(): void $client->request('PUT', '/api/test-resource-excerpts/test-resource-1?locale=en', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -246,8 +264,14 @@ public function testPutAbsent(): void $client->request('PUT', '/api/test-resource-excerpts/absent-resource?locale=en', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -298,8 +322,14 @@ public function testPutWithPublishAction(): void $client->request('PUT', '/api/test-resource-excerpts/test-resource-1?locale=en&action=publish', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -335,6 +365,6 @@ public function testDelete(): void $client->request('DELETE', '/api/test-resource-excerpts/test-resource-1?locale=en'); $response = $client->getResponse(); - $this->assertSame(204, $response->getStatusCode()); + $this->assertHttpStatusCode(204, $response); } } diff --git a/Tests/Functional/Controller/AbstractSeoControllerTest.php b/Tests/Functional/Controller/AbstractSeoControllerTest.php index 47780155..f9a05970 100644 --- a/Tests/Functional/Controller/AbstractSeoControllerTest.php +++ b/Tests/Functional/Controller/AbstractSeoControllerTest.php @@ -49,8 +49,14 @@ public function testGet(): void $client->request('GET', '/api/test-resource-seos/test-resource-1?locale=en'); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -73,8 +79,14 @@ public function testGetAbsent(): void $client->request('GET', '/api/test-resource-seos/absent-resource?locale=en'); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -117,8 +129,14 @@ public function testPut(): void $client->request('PUT', '/api/test-resource-seos/test-resource-1?locale=en', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -159,8 +177,14 @@ public function testPutAbsent(): void $client->request('PUT', '/api/test-resource-seos/absent-resource?locale=en', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -203,8 +227,14 @@ public function testPutWithPublishAction(): void $client->request('PUT', '/api/test-resource-seos/test-resource-1?locale=en&action=publish', $payload); $response = $client->getResponse(); - $result = json_decode($client->getResponse()->getContent(), true); - $this->assertSame(200, $response->getStatusCode()); + $this->assertHttpStatusCode(200, $response); + + $responseContent = $response->getContent(); + if (!$responseContent) { + $this->fail(); + } + + $result = json_decode($responseContent, true); $this->assertSame( [ @@ -236,6 +266,6 @@ public function testDelete(): void $client->request('DELETE', '/api/test-resource-seos/test-resource-1?locale=en'); $response = $client->getResponse(); - $this->assertSame(204, $response->getStatusCode()); + $this->assertHttpStatusCode(204, $response); } } diff --git a/Tests/Functional/EventSubscriber/ContentViewSerializationSubscriberTest.php b/Tests/Functional/EventSubscriber/ContentViewSerializationSubscriberTest.php index 231525d8..0ca07910 100644 --- a/Tests/Functional/EventSubscriber/ContentViewSerializationSubscriberTest.php +++ b/Tests/Functional/EventSubscriber/ContentViewSerializationSubscriberTest.php @@ -13,6 +13,7 @@ namespace Sulu\Bundle\ContentBundle\Tests\Functional\EventSubscriber; +use JMS\Serializer\SerializationContext; use Sulu\Bundle\ContentBundle\Model\Content\ContentView; use Sulu\Bundle\TestBundle\Testing\SuluTestCase; @@ -30,7 +31,11 @@ public function testSerializeToJson(): void ['title' => 'Sulu', 'article' => '

Sulu is awesome

'] ); - $result = $this->getContainer()->get('jms_serializer')->serialize($contentView, 'json'); + $result = $this->getContainer()->get('jms_serializer')->serialize( + $contentView, + 'json', + SerializationContext::create()->setSerializeNull(true) + ); $this->assertSame( [ @@ -53,7 +58,11 @@ public function testSerializeToJsonMissingField(): void ['title' => 'Sulu'] ); - $result = $this->getContainer()->get('jms_serializer')->serialize($contentView, 'json'); + $result = $this->getContainer()->get('jms_serializer')->serialize( + $contentView, + 'json', + SerializationContext::create()->setSerializeNull(true) + ); $this->assertSame( [ @@ -65,62 +74,4 @@ public function testSerializeToJsonMissingField(): void json_decode($result, true) ); } - - public function testSerializeToArray(): void - { - $contentView = new ContentView( - self::RESOURCE_KEY, - '123-123-123', - 'de', - 'default', - ['title' => 'Sulu', 'article' => '

Sulu is awesome

'] - ); - - $result = $this->getContainer()->get('jms_serializer')->serialize($contentView, 'array'); - - $this->assertSame( - [ - 'id' => '123-123-123', - 'template' => 'default', - 'content' => [ - 'title' => 'Sulu', - 'article' => '

Sulu is awesome

', - ], - 'view' => [ - 'title' => [], - 'article' => [], - ], - ], - $result - ); - } - - public function testSerializeToArrayMissingField(): void - { - $contentView = new ContentView( - self::RESOURCE_KEY, - '123-123-123', - 'de', - 'default', - ['title' => 'Sulu'] - ); - - $result = $this->getContainer()->get('jms_serializer')->serialize($contentView, 'array'); - - $this->assertSame( - [ - 'id' => '123-123-123', - 'template' => 'default', - 'content' => [ - 'title' => 'Sulu', - 'article' => null, - ], - 'view' => [ - 'title' => [], - 'article' => [], - ], - ], - $result - ); - } } diff --git a/composer.json b/composer.json index b353e66d..121d7945 100644 --- a/composer.json +++ b/composer.json @@ -11,21 +11,20 @@ "homepage": "https://github.com/sulu/SuluContentBundle", "license": "MIT", "require": { - "php": "^7.1.3", - "doctrine/doctrine-bundle": "^1.6", - "friendsofsymfony/rest-bundle": "^2.2", - "jms/serializer": "^1.13", - "sulu/sulu": "dev-develop || ^2.0", - "symfony/config": "^4.1", - "symfony/dependency-injection": "^4.1", - "symfony/http-foundation": "^4.1", - "symfony/http-kernel": "^4.1", - "symfony/messenger": "^4.1", + "php": "^7.2", + "doctrine/doctrine-bundle": "^1.10", + "friendsofsymfony/rest-bundle": "^2.6", + "jms/serializer": "^3.0", + "sulu/sulu": "^2.0.2", + "symfony/config": "^4.3", + "symfony/dependency-injection": "^4.3", + "symfony/http-foundation": "^4.3", + "symfony/http-kernel": "^4.3", + "symfony/messenger": "^4.3", "webmozart/assert": "^1.3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.12", - "jackalope/jackalope-doctrine-dbal": "^1.2.5", + "jackalope/jackalope-doctrine-dbal": "^1.3", "jangregor/phpstan-prophecy": "^0.2", "phpstan/phpstan": "^0.10", "phpstan/phpstan-doctrine": "^0.10", @@ -33,8 +32,8 @@ "phpstan/phpstan-symfony": "^0.10.2", "phpstan/phpstan-webmozart-assert": "^0.10.0", "phpunit/phpunit": "^7.2", - "symfony/browser-kit": "^4.2", - "symfony/dotenv": "^4.1", + "symfony/browser-kit": "^4.3", + "symfony/dotenv": "^4.3", "symfony/monolog-bundle": "^3.3", "zendframework/zend-stdlib": "~2.3", "zendframework/zendsearch": "@dev" @@ -59,13 +58,10 @@ "@phpunit" ], "lint": [ - "@phpstan", - "@php-cs" + "@phpstan" ], "phpunit": "@php vendor/bin/phpunit", - "phpstan": "@php vendor/bin/phpstan analyze -c ./phpstan.neon . -l max", - "php-cs": "@php vendor/bin/php-cs-fixer fix --verbose --diff --dry-run", - "php-cs-fix": "@php vendor/bin/php-cs-fixer fix" + "phpstan": "@php vendor/bin/phpstan analyze -c ./phpstan.neon . -l max" }, "extra": { "branch-alias": {