Implement custom PURL providers

Your custom PURL provider must implement Drupal\purl\Plugin\Purl\Provider\ProviderInterface.

The purl module uses annotation as the plugin discovery method, and expects custom PURL providers to exist under the modules/<module name>/src/Plugin/Purl/Provider directory. Implementations must tag themselves using the Drupal\purl\Annotation\PurlProvider annotation.

Here is a very simple example that illustrates what a PURL provider is responsible for:

<?php

namespace App\microsites\Plugin\Purl\Provider;

use Drupal\purl\Plugin\Purl\Provider\ProviderInterface;
use Drupal\purl\Annotation\PurlProvider;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

/**
 * @PurlProvider(id="microsites")
 */
class Microsites implements ProviderInterface, ContainerAwareInterface
{
    use ContainerAwareTrait;

    protected $storage;

  /**
   * This provider is responsible for registering all known micro-sites to the purl
   * provider.
   * 
   * This will need to return an associative array of modifiers, with the modifier name
   * as keys and the modifier values as the values.
   */
    public function getModifiers()
    {
        $storage = $this->container->get('entity.manager')->getStorage('microsites');
        $query = $storage->getQuery()->condition('status', 1);
        $nids = $query->execute();

        $entities = $storage->loadMultiple($nids);

        $modifiers = array();

        foreach ($entities as $entity) {
            $titleSlug = $this->slugify($entity->getTitle());
            $modifiers[$titleSlug] = $entity->getId();
        };

        return $modifiers;
    }

    public function slugify($str)
    {
        $slug = preg_replace('/[^0-9a-zA-Z]+/', '-', $str);
        return preg_replace('/-+/', '-', $slug);
    }
}

The modifier index (@purl.modifier_index)

For efficiency, the modifiers returned by all active providers registered in the system are indexed in the database by the @purl.modifier_index. This ensures that we don't call ProviderInterface#getModifiers on every request, which can be expensive depending on the specific implementations of the interface. For example, the provider above could involve hundreds of microsites. We don't really want to query for all of them every single request. That's why we keep an index.

Because of this intermediary layer between your providers and the consumers of the data within purl's internals, there will be instances when the data is out-of-sync. If there is a content/module change that calls for an addition, modification, or removal of modifiers (for example, adding a new microsites entity), you will need to tell @purl.modifier_index to rebuild its index of the microsites PURL provider:

<?php

// After inserting/deleting/modifying a `microsite` entity, 
// tell the modifier index to rebuild its data for the `microsites` PURL provider:

\Drupal::service('@purl.modifier_index')->rebuild('microsites');