Use of Drupal module uninstall validators and lazy services

Sometimes we do not want to uninstall a Drupal module directly, but instead want to perform some checks first.

Let's take a scenario where a module creates node types along with some fields on install, later on If a user wishes to uninstall that module (assume some content has already been created on the site using the node type created by this module), then it should warn the user about the data that has already been created on the site using this module.

We can use module uninstall validators lazy services, here I am going to take module name as lorem_ipsum for the same.

Define lorem_ipsum.service.yml and add below code


    lorem_ipsum.uninstall_validator:
      class: Drupal\lorem_ipsum\LoremIpsumUninstallValidator
      tags:
      - { name: module_install.uninstall_validator }
      arguments: ['@string_translation', '@entity_type.manager']
      lazy: true
  

Now, create LoremIpsumUninstallValidator.php under 'src' and add below code


    namespace Drupal\lorem_ipsum;

    use Drupal\Core\Entity\EntityTypeManagerInterface;
    use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
    use Drupal\Core\StringTranslation\StringTranslationTrait;
    use Drupal\Core\StringTranslation\TranslationInterface;

    /**
     * Module uninstall validator service.
     */
    class LoremIpsumUninstallValidator implements ModuleUninstallValidatorInterface {

      use StringTranslationTrait;

      /**
       * The entity type manager.
       *
       * @var \Drupal\Core\Entity\EntityTypeManagerInterface
       */
      protected $entityTypeManager;

      /**
       * Constructs a new LoremIpsumUninstallValidator.
       *
       * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
       *   The string translation service.
       * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
       *   The entity type manager.
       */
      public function __construct(TranslationInterface $string_translation, EntityTypeManagerInterface $entity_type_manager) {
        $this->stringTranslation = $string_translation;
        $this->entityTypeManager = $entity_type_manager;
      }

      /**
       * {@inheritdoc}
       */
      public function validate($module) {
        $reasons = [];
        if ($module == 'lorem_ipsum' && $this->doAnotherAction()) {
          $reasons[] = $this->t('There are content available for node type [@type], please delete before uninstallation.',[
            '@type' => 'your_node_type'
          ]);
        }
        return $reasons;
      }

      /**
       * Check if content available for given node_types.
       *
       * @return bool
       *   TRUE if there are content of specified node types.
       */
      protected function doAnotherAction() {
        $nodes = $this->entityTypeManager->getStorage('node')
        ->getQuery()->condition('type','your_node_type');
        retun (bool) nodes;
      }

    }
  

Now, create proxy service class under 'src/ProxyClass' and blow code


    namespace Drupal\lorem_ipsum\ProxyClass;

    use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Drupal\Core\StringTranslation\TranslationInterface;

    /**
     * Module uninstall validator proxy service class.
     */
    class LoremIpsumUninstallValidator implements ModuleUninstallValidatorInterface  {

      use \Drupal\Core\DependencyInjection\DependencySerializationTrait;

      /**
       * The proxy service.
       *
       * @var string
       */
      protected $drupalProxyService;

      /**
       * The lazy loaded proxy service.
       *
       * @var \Drupal\lorem_ipsum\LoremIpsumUninstallValidator
       */
      protected $service;

      /**
       * The service container.
       *
       * @var \Symfony\Component\DependencyInjection\ContainerInterface
       */
      protected $container;

      /**
       * Constructs a ProxyClass Drupal proxy object.
       *
       * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
       *   The container.
       * @param string $drupal_proxy_service
       *   The service ID of the original service.
       */
      public function __construct(ContainerInterface $container, $drupal_proxy_service) {
        $this->container = $container;
        $this->drupalProxyService = $drupal_proxy_service;
      }

      /**
       * Lazy loads the service from the container.
       *
       * @return object
       *   Returns the constructed service.
       */
      protected function lazyLoad() {
        if (!isset($this->service)) {
          $this->service = $this->container->get($this->drupalProxyService);
        }
        return $this->service;
      }

      /**
       * {@inheritdoc}
       */
      public function validate($module) {
        return $this->lazyLoad()->validate($module);
      }

      /**
       * {@inheritdoc}
       */
      public function setStringTranslation(TranslationInterface $translation) {
        return $this->lazyLoad()->setStringTranslation($translation);
      }

    }
  

Clear cache and check

Comments

Popular posts from this blog

How to setup Drupal 8 Multisite on nginx webserver with different domain.

Install drush globally using composer on WSL

Drupal views create exposed filter programmatically