Skip to content

IBX-8190: Update REST custom media type #2688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

adriendupuis
Copy link
Contributor

@adriendupuis adriendupuis commented Apr 1, 2025

Question Answer
JIRA Ticket IBX-8190
Versions 5.0
Edition All
  • Move from removed ValueObjectVisitorDispatcher to new ValueObjectVisitorResolver.

Preview: Adding custom media type

Related PRs

This PR is the minimal mandatory change. In other PRs, some other optional improvement studies are made.

Checklist

  • Text renders correctly
  • Text has been checked with vale
  • Description metadata is up to date
  • Redirects cover removed/moved pages
  • Code samples are working
  • PHP code samples have been fixed with PHP CS fixer
  • Added link to this PR in relevant JIRA ticket or code PR

Move to ValueObjectVisitorDispatcher to ValueObjectVisitorResolver
Copy link

github-actions bot commented Apr 1, 2025

Property App\Rest\Output\ValueObjectVisitorResolver::$visitors type has no value type specified in iterable type array.

Method App\Rest\Output\ValueObjectVisitorResolver::__construct() has parameter $visitors with no value type specified in iterable type iterable.
@adriendupuis adriendupuis marked this pull request as ready for review April 2, 2025 06:59
@adriendupuis adriendupuis requested a review from barw4 April 2, 2025 06:59
Copy link

github-actions bot commented Apr 2, 2025

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/api/rest_api/config/services.yaml

docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@41:``` yaml
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@42:services:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@43: #…

code_samples/api/rest_api/config/services.yaml

docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@41:``` yaml
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@42:services:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@43: #…
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@44:[[= include_file('code_samples/api/rest_api/config/services.yaml', 28, 35) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@44:[[= include_file('code_samples/api/rest_api/config/services.yaml', 33, 41) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@45:```

001⫶services:
002⫶ #…
003⫶ App\Rest\ValueObjectVisitor\RestLocation:
004⫶ class: App\Rest\ValueObjectVisitor\RestLocation
005⫶ parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
006⫶ arguments:
007⫶ $urlAliasService: '@ibexa.api.service.url_alias'
008⫶ tags:
009⫶ - { name: app.rest.output.value_object.visitor, type: Ibexa\Rest\Server\Values\RestLocation }

docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@52:``` yaml
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@53:services:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@54: #…
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@45:```

001⫶services:
002⫶ #…
003⫶ App\Rest\ValueObjectVisitor\RestLocation:
004⫶ class: App\Rest\ValueObjectVisitor\RestLocation
005⫶ parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
006⫶ arguments:
007⫶ $urlAliasService: '@ibexa.api.service.url_alias'
008⫶ tags:
009⫶ - { name: app.rest.output.value_object.visitor, type: Ibexa\Rest\Server\Values\RestLocation }

docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@52:``` yaml
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@53:services:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@54: #…
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@55:[[= include_file('code_samples/api/rest_api/config/services.yaml', 22, 27) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@55:[[= include_file('code_samples/api/rest_api/config/services.yaml', 28, 32) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@56:```

001⫶services:
002⫶ #…
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@56:```

001⫶services:
002⫶ #…
003⫶    App\Rest\Output\ValueObjectVisitorDispatcher:
004⫶ class: App\Rest\Output\ValueObjectVisitorDispatcher
005⫶ arguments:
006⫶ - !tagged_iterator { tag: 'app.rest.output.value_object.visitor', index_by: 'type' }
007⫶ - '@Ibexa\Contracts\Rest\Output\ValueObjectVisitorDispatcher'
003⫶    App\Rest\Output\ValueObjectVisitorResolver:
004⫶ arguments:
005⫶ $visitors: !tagged_iterator { tag: 'app.rest.output.value_object.visitor', index_by: 'type' }
006⫶ $resolver: '@Ibexa\Contracts\Rest\Output\ValueObjectVisitorResolver'

docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@67:``` yaml
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@68:parameters:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@69: #…
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@70:[[= include_file('code_samples/api/rest_api/config/services.yaml', 1, 3) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@71:services:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@72: #…

docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@67:``` yaml
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@68:parameters:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@69: #…
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@70:[[= include_file('code_samples/api/rest_api/config/services.yaml', 1, 3) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@71:services:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@72: #…
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@73:[[= include_file('code_samples/api/rest_api/config/services.yaml', 6, 21) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@73:[[= include_file('code_samples/api/rest_api/config/services.yaml', 6, 27) =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@74:```

001⫶parameters:
002⫶ #…
003⫶ app.rest.output.visitor.xml.regexps: ['(^application/app\.api\.[A-Za-z]+\+xml$)']
004⫶ app.rest.output.visitor.json.regexps: ['(^application/app\.api\.[A-Za-z]+\+json$)']
005⫶
006⫶services:
007⫶ #…
008⫶ app.rest.output.visitor.xml:
009⫶ class: Ibexa\Contracts\Rest\Output\Visitor
010⫶ arguments:
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@74:```

001⫶parameters:
002⫶ #…
003⫶ app.rest.output.visitor.xml.regexps: ['(^application/app\.api\.[A-Za-z]+\+xml$)']
004⫶ app.rest.output.visitor.json.regexps: ['(^application/app\.api\.[A-Za-z]+\+json$)']
005⫶
006⫶services:
007⫶ #…
008⫶ app.rest.output.visitor.xml:
009⫶ class: Ibexa\Contracts\Rest\Output\Visitor
010⫶ arguments:
011⫶            - '@Ibexa\Rest\Output\Generator\Xml'
012⫶ - '@App\Rest\Output\ValueObjectVisitorDispatcher'
013⫶ tags:
014⫶ - { name: ibexa.rest.output.visitor, regexps: app.rest.output.visitor.xml.regexps, priority: 20 }
015⫶
016⫶ app.rest.output.visitor.json:
017⫶ class: Ibexa\Contracts\Rest\Output\Visitor
018⫶ arguments:
019⫶ - '@Ibexa\Rest\Output\Generator\Json'
020⫶ - '@App\Rest\Output\ValueObjectVisitorDispatcher'
021⫶ tags:
022⫶ - { name: ibexa.rest.output.visitor, regexps: app.rest.output.visitor.json.regexps, priority: 20 }
011⫶            $generator: '@Ibexa\Rest\Output\Generator\Xml'
012⫶ $normalizer: '@ibexa.rest.serializer'
013⫶ $encoder: '@ibexa.rest.serializer.encoder.xml'
014⫶ $valueObjectVisitorResolver: '@App\Rest\Output\ValueObjectVisitorResolver'
015⫶ $format: 'xml'
016⫶ tags:
017⫶ - { name: ibexa.rest.output.visitor, regexps: app.rest.output.visitor.xml.regexps, priority: 20 }
018⫶
019⫶ app.rest.output.visitor.json:
020⫶ class: Ibexa\Contracts\Rest\Output\Visitor
021⫶ arguments:
022⫶ $generator: '@Ibexa\Rest\Output\Generator\Json'
023⫶ $normalizer: '@ibexa.rest.serializer'
024⫶ $encoder: '@ibexa.rest.serializer.encoder.json'
025⫶ $valueObjectVisitorResolver: '@App\Rest\Output\ValueObjectVisitorResolver'
026⫶ $format: 'json'
027⫶ tags:
028⫶ - { name: ibexa.rest.output.visitor, regexps: app.rest.output.visitor.json.regexps, priority: 20 }

docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@48:``` yaml
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@49:services:
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@50: #…

docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@48:``` yaml
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@49:services:
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@50: #…
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@51:[[= include_file('code_samples/api/rest_api/config/services.yaml', 36, 42) =]]
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@51:[[= include_file('code_samples/api/rest_api/config/services.yaml', 41, 47) =]]
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@52:```

001⫶services:
002⫶ #…
003⫶ App\Rest\Controller\:
004⫶ resource: '../src/Rest/Controller/'
005⫶ parent: Ibexa\Rest\Server\Controller
006⫶ autowire: true
007⫶ autoconfigure: true
008⫶ tags: [ 'controller.service_arguments' ]

docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@98:``` yaml
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@99:services:
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@100: #…
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@52:```

001⫶services:
002⫶ #…
003⫶ App\Rest\Controller\:
004⫶ resource: '../src/Rest/Controller/'
005⫶ parent: Ibexa\Rest\Server\Controller
006⫶ autowire: true
007⫶ autoconfigure: true
008⫶ tags: [ 'controller.service_arguments' ]

docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@98:``` yaml
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@99:services:
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@100: #…
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@101:[[= include_file('code_samples/api/rest_api/config/services.yaml', 43, 48) =]]
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@101:[[= include_file('code_samples/api/rest_api/config/services.yaml', 48, 53) =]]
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@102:```

001⫶services:
002⫶ #…
003⫶ App\Rest\ValueObjectVisitor\Greeting:
004⫶ parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
005⫶ tags:
006⫶ - { name: ibexa.rest.output.value_object.visitor, type: App\Rest\Values\Greeting }

docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@120:``` yaml
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@121:services:
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@122: #…
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@102:```

001⫶services:
002⫶ #…
003⫶ App\Rest\ValueObjectVisitor\Greeting:
004⫶ parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
005⫶ tags:
006⫶ - { name: ibexa.rest.output.value_object.visitor, type: App\Rest\Values\Greeting }

docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@120:``` yaml
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@121:services:
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@122: #…
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@123:[[= include_file('code_samples/api/rest_api/config/services.yaml', 48, 53) =]]
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@123:[[= include_file('code_samples/api/rest_api/config/services.yaml', 53, 58) =]]
docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@124:```

001⫶services:
002⫶ #…
003⫶ App\Rest\InputParser\GreetingInput:
004⫶ parent: Ibexa\Rest\Server\Common\Parser
005⫶ tags:
006⫶ - { name: ibexa.rest.input.parser, mediaType: application/vnd.ibexa.api.GreetingInput }


code_samples/api/rest_api/src/Rest/Output/ValueObjectVisitorDispatcher.php

docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md@124:```

001⫶services:
002⫶ #…
003⫶ App\Rest\InputParser\GreetingInput:
004⫶ parent: Ibexa\Rest\Server\Common\Parser
005⫶ tags:
006⫶ - { name: ibexa.rest.input.parser, mediaType: application/vnd.ibexa.api.GreetingInput }


code_samples/api/rest_api/src/Rest/Output/ValueObjectVisitorDispatcher.php


code_samples/api/rest_api/src/Rest/Output/ValueObjectVisitorResolver.php

docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@58:``` php
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@58:``` php
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@59:[[= include_file('code_samples/api/rest_api/src/Rest/Output/ValueObjectVisitorDispatcher.php') =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@59:[[= include_file('code_samples/api/rest_api/src/Rest/Output/ValueObjectVisitorResolver.php') =]]
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@60:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\Rest\Output;
004⫶
docs/api/rest_api/extending_rest_api/adding_custom_media_type.md@60:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\Rest\Output;
004⫶
005⫶use Ibexa\Contracts\Rest\Output\Generator;
006⫶use Ibexa\Contracts\Rest\Output\ValueObjectVisitorDispatcher as BaseValueObjectVisitorDispatcher;
007⫶use Ibexa\Contracts\Rest\Output\Visitor;
008⫶
009⫶class ValueObjectVisitorDispatcher // extends BaseValueObjectVisitorDispatcher TODO: Rewrite this example in https://issues.ibexa.co/browse/IBX-8190
010⫶{
005⫶use Ibexa\Contracts\Rest\Output\ValueObjectVisitor;
006⫶use Ibexa\Contracts\Rest\Output\ValueObjectVisitorResolverInterface;
007⫶
008⫶class ValueObjectVisitorResolver implements ValueObjectVisitorResolverInterface
009⫶{
010⫶ /** @var array<string, ValueObjectVisitor> */
011⫶    private array $visitors;
012⫶
011⫶    private array $visitors;
012⫶
013⫶    private BaseValueObjectVisitorDispatcher $valueObjectVisitorDispatcher;
013⫶    private ValueObjectVisitorResolverInterface $valueObjectVisitorResolver;
014⫶
014⫶
015⫶    private Visitor $outputVisitor;
016⫶
017⫶ private Generator $outputGenerator;
018⫶
019⫶ public function __construct(iterable $visitors, BaseValueObjectVisitorDispatcher $valueObjectVisitorDispatcher)
020⫶ {
021⫶ $this->visitors = [];
022⫶ foreach ($visitors as $type => $visitor) {
023⫶ $this->visitors[$type] = $visitor;
024⫶ }
025⫶ $this->valueObjectVisitorDispatcher = $valueObjectVisitorDispatcher;
026⫶ }
027⫶
028⫶ public function setOutputVisitor(Visitor $outputVisitor): void
029⫶ {
030⫶ $this->outputVisitor = $outputVisitor;
031⫶ $this->valueObjectVisitorDispatcher->setOutputVisitor($outputVisitor);
032⫶ }
033⫶
034⫶ public function setOutputGenerator(Generator $outputGenerator): void
035⫶ {
036⫶ $this->outputGenerator = $outputGenerator;
037⫶ $this->valueObjectVisitorDispatcher->setOutputGenerator($outputGenerator);
038⫶ }
039⫶
040⫶ public function visit($data)
041⫶ {
042⫶ $className = get_class($data);
043⫶ if (isset($this->visitors[$className])) {
044⫶ return $this->visitors[$className]->visit($this->outputVisitor, $this->outputGenerator, $data);
045⫶ }
046⫶
047⫶ return $this->valueObjectVisitorDispatcher->visit($data);
048⫶ }
049⫶}


code_samples/api/rest_api/src/Rest/Output/ValueObjectVisitorResolver.php
015⫶    /** @param iterable<string, ValueObjectVisitor> $visitors */
016⫶ public function __construct(iterable $visitors, ValueObjectVisitorResolverInterface $resolver)
017⫶ {
018⫶ $this->visitors = [];
019⫶ foreach ($visitors as $type => $visitor) {
020⫶ $this->visitors[$type] = $visitor;
021⫶ }
022⫶ $this->valueObjectVisitorResolver = $resolver;
023⫶ }
024⫶
025⫶ public function resolveValueObjectVisitor(object $object): ?ValueObjectVisitor
026⫶ {
027⫶ $className = get_class($object);
028⫶ if (isset($this->visitors[$className])) {
029⫶ return $this->visitors[$className];
030⫶ }
031⫶
032⫶ return $this->valueObjectVisitorResolver->resolveValueObjectVisitor($object);
033⫶ }
034⫶}


Download colorized diff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant