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

Provide an extension point for adding data that is passed to the website #139

Open
niklasnatter opened this issue May 7, 2020 · 1 comment
Labels
DX Only affecting the end developer

Comments

@niklasnatter
Copy link
Contributor

niklasnatter commented May 7, 2020

The ContentRouteDefaultsProvider returns a ContentStructureBridge instance to make content-rich entities compatible with the DefaultController of Sulu. Because of this implementation, the data that is managed by the TemplateInterface (and the ExcerptInterface) is resolved and provided in the .twig template automatically .

When implementing a complex content-rich entity, it might be desirable to store a selected category in a property directly on the DimensionContent instead of the templateData of the TemplateInterface. For example, this makes it easier to filter entities for a specific category.

Unfortunately, because this category is stored directly on the DimensionContent object, it will not be available in the .twig template automatically. To provide it in the twig template, it is required to implement a new controller that looks something like this:

class ExampleController extends WebsiteController
{
    public function indexAction(ContentStructureBridge $structure, bool $preview = false, bool $partial = false): Response
    {
        $projection = $structure->getContent();
        $selectedCategory = $projection->getSelectedCategory()

        return $this->renderStructure(
            $structure,
            ['category' => $selectedCategory],
            $preview,
            $partial
        );
    }
}

While creating such a controller is easily possible in a project, it is inconvenient inside of a bundle. Firstly, the user must remember that he needs to use the provided controller when using the entity of the bundle. Secondly, this prevents that the user can use a common base controller for all of the entities of the project.

To solve this issue, the SuluContentBundle could decorate the StructureResolver service of Sulu. If the StructureResolver is called with a ContentStructureBridge instance, the decorated service could call a ContentViewAttributesProvider service (the name includes attributes because it is related to the getAttributes method of the Sulu WebsiteController - I am open for suggestions here 😉 ) to gather additional attributes that should be passed to the .twig template.

This ContentViewAttributesProvider service itself would be implemented similar to the ContentNormalizer (or ContentDataMapper) service. This means that it would be a registry of ViewAttributesProvider services that would have an interface that looks something like this:

interface ViewAttributesProvider
{
    public function getAttributes(object $object): array;
}
@alexander-schranz alexander-schranz added the DX Only affecting the end developer label May 17, 2020
@alexander-schranz alexander-schranz added this to the Stable Release milestone Sep 17, 2021
@alexander-schranz
Copy link
Member

alexander-schranz commented Sep 17, 2021

The ContentRouteDefaultsProvider should just be there to maybe simplify things but every entity should implement the loading of the Entity itself.

This is nothing which the ContentBundle should take care of. How many is loaded and what is loaded to the website is part of the bundle / model which use the ContentBundle not. The Models Repository should use then the DimensionContentQueryEnhancer to load the correct content but can then load more with additional joins in its own Repository.

#192

So we have here 2 options the first one would be we the bundle create the RouteDefaultsProviderInterface.
Or there is only AbstractContentRouteDefaultsProvider where the loading of the entity needs to be implemented by the bundle which implement it.

    public function getModel($id, $dimensionAttributes): object
    {
         return $this->exampleRepository->getOneBy($id, $dimensionAttributes, ['content_website' => true, 'with-something-else' => true]);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DX Only affecting the end developer
Projects
None yet
Development

No branches or pull requests

2 participants