Utiliser la Cron API de Drupal 8

Une file de gens faisant la queue

Nous avons vu dans un précédent billet comment nous pouvions générer automatiquement les styles d'images définis sur un site pour chaque image source téléversée. Nous allons poursuivre ce billet pour cette fois réaliser la même opération au moyen de la Cron API de Drupal 8, ce qui nous permet de désynchroniser ces opérations de masse, et qui donc peuvent être pénalisantes sur les performances ressenties, lors des actions réalisées par les utilisateurs.

Pour mémoire, l'objectif recherché est de pouvoir générer tous les styles d'images d'une image source au moment de son import, permettant ainsi d'améliorer la performance globale du site, notamment lors des premières consultations de ses pages.

Pour parvenir à nos fins, nous allons créer un nouveau Plugin qui va étendre le plugin QueueWorker. Ce plugin va nous permettre de créer une tache cron spécifique que nous pourrons appeler et instancier au moment de l'import d'une image source et ainsi planifier la création automatique de tous les styles d'image.

Pour créer notre Plugin, il nous suffit de créer le fichier MyModuleImageStyle.php dans le dossier src/Plugin/QueueWorker de notre module.

<?php

namespace Drupal\my_module\Plugin\QueueWorker;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Queue\QueueWorkerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Executes interface translation queue tasks.
 *
 * @QueueWorker(
 *   id = "my_module_image_style",
 *   title = @Translation("Generate image styles"),
 *   cron = {"time" = 60}
 * )
 */
class MyModuleImageStyle extends QueueWorkerBase implements ContainerFactoryPluginInterface {

  /**
   * The image style entity storage.
   *
   * @var \Drupal\image\ImageStyleStorageInterface
   */
  protected $imageStyleStorage;

  /**
   * Constructs a new LocaleTranslation object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param array $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityStorageInterface $image_style_storage
   *   The image style storage.
   */
  public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityStorageInterface $image_style_storage) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->imageStyleStorage = $image_style_storage;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager')->getStorage('image_style')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function processItem($data) {
    /** @var \Drupal\file\Entity\File $entity */
    $entity = $data['entity'];
    $styles = $this->imageStyleStorage->loadMultiple();
    $image_uri = $entity->getFileUri();
    /** @var \Drupal\image\Entity\ImageStyle $style */
    foreach ($styles as $style) {
      $destination = $style->buildUri($image_uri);
      $style->createDerivative($image_uri, $destination);
    }
  }

}

 

La méthode la plus significative de notre plugin est la méthode processItem, qui va générer les différents styles d'images quand la tache planifiée sera appelée via le cron.

Ainsi, pour reprendre notre exemple précédent sur la génération des styles d'image au moment de l'import de l'image source, il nous suffit désormais d'invoquer notre nouvelle tache planifiée (QueueWorker).

use Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_entity_insert().
 * Generate all image styles once an Image is uploaded.
 */
function my_module_entity_insert(EntityInterface $entity) {
  /** @var \Drupal\file\Entity\File $entity */
  if ($entity instanceof FileInterface) {
    $image = \Drupal::service('image.factory')->get($entity->getFileUri());
    /** @var \Drupal\Core\Image\Image $image */
    if ($image->isValid()) {
      $queue = \Drupal::queue('my_module_image_style');
      $data = ['entity' => $entity];
      $queue->createItem($data);
    }
  }
}

Il conviendra alors de configurer le cron pour être exécuté de façon régulière, de préférence de façon décorrélée des interactions utilisateurs en déclenchant par exemple le cron du site depuis des appels Curl planifiés au niveau du serveur. Mais ceci alors ne relève plus à proprement parler des compétences d'un développeur Drupal 8, mais de votre administrateur système qui pourra paramétrer votre serveur en conséquence.

 

Ajouter un commentaire