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
Add SnippetAreaController #87
Add SnippetAreaController #87
Conversation
@wachterjohannes @alexander-schranz @nnatter Are you okay with introducing the |
@luca-rath @alexander-schranz would go with |
First I thought the same, but this is not really a serializer, because it loads a snippet by uuid |
@luca-rath hmm OK seems wrong because we used resolver so much in the bundle 🙈 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of DefaultSnippetManager::load
it should use int he content types DefaultSnippetManager::loadIdentifier
so we do not load the snippet twice.
Controller/SnippetAreaController.php
Outdated
|
||
$loadExcerpt = (bool) $this->getRequestParameter($request, 'loadExcerpt', true, false); | ||
|
||
$snippet = $this->defaultSnippetManager->load($webspaceKey, $area, $locale); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be loadIdentifier
when the resolver only works with uuid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i guess it would be nice to use this method in the SnippetSelectionResolver
and SingleSnippetSelectionResolver
too
Content/SnippetResolver.php
Outdated
*/ | ||
public function resolve( | ||
string $uuid, | ||
string $webspaceKey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I remember the webspace key is actually not used in the contentMapper
and so we don't need it here.
Content/SnippetResolver.php
Outdated
bool $loadExcerpt = false | ||
): array { | ||
/** @var SnippetBridge $snippet */ | ||
$snippet = $this->contentMapper->load($uuid, $webspaceKey, $locale); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null can be given as webspaceKey here
Content/SnippetResolver.php
Outdated
|
||
if (!$snippet->getHasTranslation() && null !== $shadowLocale) { | ||
/** @var SnippetBridge $snippet */ | ||
$snippet = $this->contentMapper->load($uuid, $webspaceKey, $shadowLocale); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null can be given as webspaceKey here
Controller/SnippetAreaController.php
Outdated
|
||
$resolvedSnippet = $this->snippetResolver->resolve( | ||
$snippet->getUuid(), | ||
$webspaceKey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be removed as no webspaceKey is needed to load snippets
Content/SnippetResolverInterface.php
Outdated
*/ | ||
public function resolve( | ||
string $uuid, | ||
string $webspaceKey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Snippets has no webspacekey so and contentmapper does since long time not longer require it to load something
I would stay with |
Content/SnippetResolver.php
Outdated
* @return mixed[] | ||
*/ | ||
public function resolve( | ||
string $uuid, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think the other resolvers do not load the data by themselves but get the loaded data passed to the resolve
function, eg the StructureResolver
receives a StructureBridge $structure
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i guess we should pass a SnippetBridge $snippet
here for consistency because of this - what do you think? @sulu/core-team
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you're right, but then the functionality regarding loading the snippet in the shadow locale, if the original locale is not available, will be duplicated in the SingleSnippetSelectionResolver
and the SnippetSelectionResolver
... But on the other hand, then this service would really just be a serializer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think it would be okay for me to duplicate the fallback to the shadow locale in the SingleSnippetSelectionResolver
and SnippetSelectionResolver
. i guess this is only required when a snippet is resolved as part of a page/article, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implementing this as SnippetSerializer
in the Serializer
namespace would feel better for me too. but dont have a too strong opinion 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we don't even need a service for that, because we can just use the StructureResolver
directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thats right, sorry 🙈 can you think about a case where we need a shadow locale outside of the SingleSnippetSelectionResolver
/SnippetSelectionResolver
? @sulu/core-team
if no, i would prefer to duplicate the shadow locale handling in the SingleSnippetSelectionResolver
/SnippetSelectionResolver
and use the StructureResolver
directly in all other cases. that way we dont provide a resolver service that is inconsistent with the other resolvers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay seem slike there is no shadow handling needed in the controller so it sounds good for me if the controller then just does.
$snippet = $defaultSnippetManager->load($defaultSnippet);
$structureResolver->resolve($snippet, ...);
And the call just SingleSnippetSelection
calls like SingleMediaSelection
the SnippetSelection
so we have the shadow handling only at this case.
@@ -81,18 +72,13 @@ public function resolve($data, PropertyInterface $property, string $locale, arra | |||
return new ContentView(null, ['id' => null]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice to use the DefaultSnippetManager::loadIdentifier()
method in this class too
@@ -79,18 +70,13 @@ public function resolve($data, PropertyInterface $property, string $locale, arra | |||
|
|||
$snippets = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice to use the DefaultSnippetManager::loadIdentifier()
method in this class too
Resources/config/routing_website.yml
Outdated
@@ -7,3 +7,8 @@ sulu_headless.api.search: | |||
path: /api/search | |||
defaults: | |||
_controller: sulu_headless.controller.search:getAction | |||
|
|||
sulu_headless.api.snippet_area: | |||
path: /api/snippet/{area} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if we should use /api/snippet-areas/{area}
here. maybe we want to provide an api for loading a snippet by its id in the future? 🤔 @sulu/core-team
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sounds good 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nnatter i would say that would be another API /api/snippets/{id}
or /api/snippets/{key}
would keep the path /api/snippet-areas/{area}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wachterjohannes currently it's /api/snippet/{area}
and @nnatter suggested using /api/snippet-areas/{area}
🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then @nnatter and i want the same 😅
* | ||
* @internal | ||
*/ | ||
class HeadlessBundleKernelBrowser extends KernelBrowser |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be used. The headless bundle works differently to other API's it need to ignore the Accept
header and always return the .json
also when the browser does not send the Accept
header with introducing this KernelBrowser we are not longer testing the HeadlessBundle correctly. This KernelBrowser should be removed and jsonRequest
should not be used to test the HeadlessBundle endpoints. Detection on the format is just done by the .json
at the end or that the api like navigaiton and snippet just always return a json.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But exceptions are returned as symfony exception page and not as json, if I use $client->request()
... and an url like /api/snippet-areas/default.json
won't work, because then symfony assumes default.json
is the {area}
instead of default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So how can i test the exceptions then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exception should still be json. Seems then the _format
is not correctly set for this route try add something like:
defaults:
_format: json
Check if in the controller $request->getRequestFormat()
returns you json
. For navigation and snippet its okay to have .json
optional e.g.: /api/snippet-areas/{area}.{_format}
but the $request->getRequestFormat()
should return json.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did add the same also to the navigation route
$snippetId = $data ?: null; | ||
|
||
$contentView = $this->snippetSelectionResolver->resolve( | ||
$snippetId ? [$snippetId] : null, | ||
$property, | ||
$locale, | ||
$attributes | ||
); | ||
$content = $contentView->getContent(); | ||
$view = $contentView->getView(); | ||
|
||
return new ContentView( | ||
$content[0] ?? null, | ||
['id' => $view['ids'][0] ?? null] | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason for implementing this different (eg. no early return) to the SingleMediaSelectionResolver
and SinglePageSelectionResolver
?
guess it will work fine, just curious 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, because if using an early return, if data is null, the default snippet won't be taken into account, because that handling is only in the SnippetSelectionResolver
now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense - thanks!
} | ||
|
||
return $snippet->getUuid(); | ||
return new ContentView($snippets, ['ids' => $snippetIds ?: []]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if we returned $data
(does not contain default snippet id) instead of $snippetIds
(does contain default snippet id) here intentionally. cant think how someone would use this, so its okay for me both ways 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just thought, it would be confusing, if an actual snippet is returned (the default snippet) but the view data says the id is null
Added a
SnippetAreaController
and refactored theSingleSnippetSelectionResolver
fixes #42