sulu / SuluHeadlessBundle

Bundle that provides controllers and services for using Sulu as headless content management system
MIT License
45 stars 25 forks source link

Add api endpoint for providing a breadcrumb #70

Open alexander-schranz opened 3 years ago

alexander-schranz commented 3 years ago

Like the sulu_breadcrumb twig extension it should be possible to provide a breadcrumb over an endpoint. It should work similar to the navigation context api. An example api endpint url could be /api/breadcrumb/<uuid>.

Another possibility could be that we add the breadcrumb directly to the json response example:

/my-page-url.json?with-breadcrumb=true

Would return the breadcrumb on the root level:

{
      "id": "<uuid>",
      "breadcrumb": [{
               "uuid": "uuid",
               "title": "Homepage",
               "url": "/",
      }],
      "content": {},
      "view": {},
}

Update:

We want to provide the breadcrumb as a flag in the bundle and directly then via the website controller and an extension pint point in #100. So we avoid an additional request for this kind of data. I'm not yet sure if the extension point need to be in the structureresolver or in the headless controller. I already added a comment to the exist PR to update the interface for our usecase with the breadcrumb.

niklasnatter commented 3 years ago

We recently added the breadcrumbs of a page directly to the .json response in one of our projects. To do this, we used the following custom controller:

<?php

namespace App\Controller\Website;

use Sulu\Bundle\HeadlessBundle\Controller\HeadlessWebsiteController as SuluHeadlessWebsiteController;
use Sulu\Bundle\WebsiteBundle\Navigation\NavigationMapperInterface;
use Sulu\Component\Content\Compat\StructureInterface;

class HeadlessWebsiteController extends SuluHeadlessWebsiteController
{
    /**
     * @var NavigationMapperInterface
     */
    private $navigationMapper;

    public function __construct(
        NavigationMapperInterface $navigationMapper
    ) {
        $this->navigationMapper = $navigationMapper;
    }

    protected function resolveStructure(StructureInterface $structure): array
    {
        $data = parent::resolveStructure($structure);
        $data['breadcrumbs'] = $this->getBreadcrumbs($structure);

        return $data;
    }

    /**
     * @return array<array{
     *     id: string,
     *     title: string,
     *     url: string,
     * }>
     */
    private function getBreadcrumbs(StructureInterface $structure): array
    {
        $breadcrumbs = [];

        foreach ($this->navigationMapper->getBreadcrumb(
            $structure->getUuid(),
            $structure->getWebspaceKey(),
            $structure->getLanguageCode()
        ) as $item) {
            $breadcrumbs[] = [
                'uuid' => $item->getUuid(),
                'title' => $item->getTitle(),
                'url' => $item->getUrl(),
            ];
        }

        return $breadcrumbs;
    }
}

And register that controller in our templates:

    <controller>App\Controller\Website\HeadlessWebsiteController::indexAction</controller>
alexander-schranz commented 1 year ago

The problem with using getBreadCrumb directly in the HeadlessWebsiteController that it will not work with Articles in case of articles we need to get the breadcrumb not by the article uuid instead of the page tree parent page uuid.

As discussed with @chirimoya we should enable or disable the breadcrumb via sulu_headless option currently.

As we have different cases Page and Article Breadcrumb we maybe adopt the community pull request here: https://github.com/sulu/SuluHeadlessBundle/pull/100

But instead of the current implementation which has a extension->getKey() the provider should just be able to return all data and overwrite existing props e.g.:

return ['breadcrumb' => $this->getBreadCrumb()];