dachcom-digital / pimcore-dynamic-search-data-provider-trinity

A Data Fetch Extension for Pimcore Dynamic Search. Crawl Pimcore Data assets, documents and objects.
Other
6 stars 7 forks source link

[Improvement]: Add ObjectUrlSlugExtractor #17

Open passioneight opened 2 years ago

passioneight commented 2 years ago

It would be really great to see an ObjectUrlSlugExtractor or something similar, which should extract all URLs (i.e., for every Site), so we can index URLs to detail pages and their likes.

Probably needs an implementation similar to ObjectPathGenerator.

passioneight commented 2 years ago

Our current workaround is a custom Normalizer, which loops over all available Sites (if any) and uses them to add the Sites ID to the index document ID. Further, the $normalizerOptions contain the Site, so we can access it in our Definition class.

The Definition class then passes on the Site to our custom ObjectUrlSlugExtractor, which only loads the URL of the object for the given site.

Since we also need localization, the LocalizedResourceNormalizer was extended.

Here's the Normalizer:

<?php

namespace App\DynamicSearch\Normalizer;

use DsTrinityDataBundle\Normalizer\LocalizedResourceNormalizer;
use DynamicSearchBundle\Context\ContextDefinitionInterface;
use DynamicSearchBundle\Normalizer\Resource\NormalizedDataResource;
use DynamicSearchBundle\Normalizer\Resource\ResourceMeta;
use DynamicSearchBundle\Resource\Container\ResourceContainerInterface;
use Pimcore\Model\DataObject;
use Pimcore\Model\Site;

class LocalizedSiteResourceNormalizer extends LocalizedResourceNormalizer
{
    /**
     * @inheritDoc
     */
    protected function normalizeDataObject(ContextDefinitionInterface $contextDefinition, ResourceContainerInterface $resourceContainer): array
    {
        /** @var DataObject\Concrete $object */
        $object = $resourceContainer->getResource();

        $sites = new Site\Listing();

        if($sites->count() > 0) {
            $normalizedResources = [];

            foreach ($sites as $site) {
                foreach ($this->getLocales() as $locale) {
                    $documentId = sprintf('%s_%s_%s_%d', $site->getId(), 'object', $locale, $object->getId());
                    $resourceMeta = new ResourceMeta($documentId, $object->getId(), 'object', $object->getType(), $object->getClassName(), [], [
                        'locale' => $locale,
                        'site' => $site
                    ]);
                    $returnResourceContainer = $contextDefinition->getContextDispatchType() === ContextDefinitionInterface::CONTEXT_DISPATCH_TYPE_DELETE ? null : $resourceContainer;
                    $normalizedResources[] = new NormalizedDataResource($returnResourceContainer, $resourceMeta);
                }
            }
        } else {
            $normalizedResources = parent::normalizeDataObject($contextDefinition, $resourceContainer);
        }

        return $normalizedResources;
    }
}

Note that this is a very basic implementation, as we only need this for data objects.