Skip to content
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

Merged
merged 9 commits into from Apr 16, 2021

Conversation

luca-rath
Copy link
Contributor

@luca-rath luca-rath commented Apr 15, 2021

Added a SnippetAreaController and refactored the SingleSnippetSelectionResolver

fixes #42

@luca-rath luca-rath marked this pull request as draft April 15, 2021 10:38
@luca-rath
Copy link
Contributor Author

@wachterjohannes @alexander-schranz @nnatter Are you okay with introducing the SnippetResolver service? If so, I will refactor the tests

@wachterjohannes
Copy link
Member

@luca-rath
Copy link
Contributor Author

First I thought the same, but this is not really a serializer, because it loads a snippet by uuid

@wachterjohannes
Copy link
Member

@luca-rath hmm OK seems wrong because we used resolver so much in the bundle 🙈

Copy link
Member

@alexander-schranz alexander-schranz left a 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.


$loadExcerpt = (bool) $this->getRequestParameter($request, 'loadExcerpt', true, false);

$snippet = $this->defaultSnippetManager->load($webspaceKey, $area, $locale);
Copy link
Member

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

Copy link
Contributor

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

*/
public function resolve(
string $uuid,
string $webspaceKey,
Copy link
Member

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.

bool $loadExcerpt = false
): array {
/** @var SnippetBridge $snippet */
$snippet = $this->contentMapper->load($uuid, $webspaceKey, $locale);
Copy link
Member

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


if (!$snippet->getHasTranslation() && null !== $shadowLocale) {
/** @var SnippetBridge $snippet */
$snippet = $this->contentMapper->load($uuid, $webspaceKey, $shadowLocale);
Copy link
Member

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


$resolvedSnippet = $this->snippetResolver->resolve(
$snippet->getUuid(),
$webspaceKey,
Copy link
Member

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

*/
public function resolve(
string $uuid,
string $webspaceKey,
Copy link
Member

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

@alexander-schranz
Copy link
Member

I would stay with SnippetResolver

* @return mixed[]
*/
public function resolve(
string $uuid,
Copy link
Contributor

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

Copy link
Contributor

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

Copy link
Contributor Author

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

Copy link
Contributor

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?

Copy link
Contributor

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 🙂

Copy link
Contributor Author

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

Copy link
Contributor

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.

Copy link
Member

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]);
Copy link
Contributor

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 = [];
Copy link
Contributor

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

@@ -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}
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sounds good 👍

Copy link
Member

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}

Copy link
Contributor Author

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} 🙂

Copy link
Member

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 😅

@alexander-schranz alexander-schranz added the Feature New functionality not yet included in the Bundle label Apr 15, 2021
@luca-rath luca-rath marked this pull request as ready for review April 15, 2021 16:14
*
* @internal
*/
class HeadlessBundleKernelBrowser extends KernelBrowser
Copy link
Member

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.

Copy link
Contributor Author

@luca-rath luca-rath Apr 16, 2021

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

Copy link
Contributor Author

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?

Copy link
Member

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.

Copy link
Contributor Author

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

Comment on lines +41 to +55
$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]
);
Copy link
Contributor

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 🙂

Copy link
Contributor Author

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

Copy link
Contributor

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 ?: []]);
Copy link
Contributor

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 🙂

Copy link
Contributor Author

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

@wachterjohannes wachterjohannes merged commit 83562fa into sulu:0.x Apr 16, 2021
@luca-rath luca-rath deleted the feature/snippet-area-controller branch April 16, 2021 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature New functionality not yet included in the Bundle
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add api to get snippet areas / default snippets
4 participants