Skip to research

Ajouter une image au background des blocks de Drupal 8

Temps de lecture
Environ 6 minutes

Nous allons développer un module qui nous permettra d'ajouter un background-image aux blocks de Drupal 8.
Notre module s'appelle background_block.

 

background_block.info.yml

Nous commençons avec le fichier background_block.info.yml, simple.

name: 'Background Block'
type: module
description: 'Add a background style to the blocks'
core: 8.x
package: 'MM'

 

Nous poursuivons avec le fichier background_block.module, que nous laissons vide pour le moment.

<?php

 

background_block.permissions.yml

Puis nous ajoutons une permission dans le fichier background_block.permissions.yml, qui nous permettra d'attribuer cette permission uniquement à certains utilisateurs.

administer block bgi:
  title: 'Administer block background-image'

 

background_block.schema.yml

A l'installation du module nous allons créer un schéma de configuration avec le fichier background_block.schema.yml que nous plaçons dans un dossier background_block/config/schema à la racine de notre module, qui nous permettra d'organiser nos configurations de block.

block.block.*.third_party.background_block:
  type: mapping
  label: Background block third party settings
  mapping:
    bgi_active:
      type: integer
      label: Background settings active
    bgi:
      type: sequence
      label: Additional background-image
      sequence:
        type: integer
    bgc:
      type: string
      label: Additional background-color
    attachment:
      type: string
      label: Additional background-attachment
    repeat:
      type: string
      label: Additional background-repeat
    positionx:
      type: string
      label: Additional background-position x
    positionz:
      type: string
      label: Additional background-position y
    size:
      type: string
      label: Additional background-size
    padding:
      type: integer
      label: Additional block padding

 

Ce schéma de configuration utilise la ThirdPartySettingsInterface pour ajouter des données supplémentaires aux entités de configuration existantes, ici, aux blocks.
Le premier élément, bgi_active, typé interger, nous permettre d'activer la nouvelle configuration.
L'élément bgi, typé en séquence, nous permettra de stocker les informations de l'image.
L'élément bgc, typé string, enregistrera, une couleur.
Les autres éléments décrive les règles d'usages en css pour le background.
Enfin, le dernier élément, ajoute un padding au block, pour plus de respiration.

Nous pouvons enfin nous attaquer à la logique de notre module que l'on va placer dans le fichier background_block.module.

Nous commençons avec un commentaire pour expliquer à la communauté l'utilité du module, puis, comme nous allons avoir besoin de travailler avec différentes class de Drupal, notamment, la Drupal\Core\Form\FormStateInterface,  la Drupal\block\Entity\Block, la \Drupal\file\Entity\File et la Drupal\Component\Render\FormattableMarkup, nous allons tout de suite les appeler avec des use, de suite après notre tag d'ouverture php.

<?php

/**
 * @file
 * Module for adding background settings to blocks.
 */

use Drupal\block\Entity\Block;
use Drupal\Core\Form\FormStateInterface;
use \Drupal\file\Entity\File;
use Drupal\Component\Render\FormattableMarkup;

 

hook_form_FORM_ID_alter()

Nous implémentons le hook_form_FORM_ID_alter() par l'intermédiaire duquel nous injectons nos éléments de form. Ces éléments de form ne sont visibles que pour les utilisateurs dont le rôle possède la permission "administer block bgi".

/**
 * Implements hook_form_FORM_ID_alter().
 */
function background_block_form_block_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  // if use have access to administer block bgi permission
  if (\Drupal::currentUser()->hasPermission('administer block bgi')) {

    // This will automatically be saved in the third party settings.
    $form['third_party_settings']['#tree'] = TRUE;

    /** @var \Drupal\block\BlockInterface $block */
    $block = $form_state->getFormObject()->getEntity();

    // Element bg_settings details
    $form['third_party_settings']['background_block']['bg_settings']= [
      '#type' => 'details',
      '#title' => t('Background settings'),
      '#open' => FALSE,
      '#weight' => -59,
    ];

    // Element form bg active
    $active = $block->getThirdPartySetting('background_block', 'bg_settings')['bgi_active'];
    $default_active = ($active != null) ? $active : 0;
    $form['third_party_settings']['background_block']['bg_settings']['bgi_active'] = array(
      '#type' => 'radios',
      '#title' => t('Active Background settings'),
      '#options' => [0 => t('Closed'), 1 => t('Active')],
      '#description' => t("Active the background image and color settings"),
      '#default_value' => $default_active,
    );
    
    // Element form bg image
    $form['third_party_settings']['background_block']['bg_settings']['bgi'] = array(
      '#type' => 'managed_file',
      '#upload_location' => 'public://background-block/images/',
      '#title' => t('Image'),
      '#description' => t("Image to show on the background"),
      '#default_value' => $block->getThirdPartySetting('background_block', 'bg_settings')['bgi'],
      '#upload_validators' => array(
        'file_validate_extensions' => array('gif png jpg jpeg'),
      ),
    );

    // Element form bg color
    $form['third_party_settings']['background_block']['bg_settings']['bgc'] = array(
      '#type' => 'color',
      '#title' => t('Background color'),
      '#default_value' => '#ffffff',
      '#description' => t("Color to show on the background"),
      '#default_value' => $block->getThirdPartySetting('background_block', 'bg_settings')['bgc'],
    );

    // Element form bg size
    $size = $block->getThirdPartySetting('background_block', 'bg_settings')['size'];
    $default_size = ($size != null) ? $size : 0;
    $form['third_party_settings']['background_block']['bg_settings']['size'] = array(
      '#type' => 'select',
      '#title' => t('Background size'),
      '#options' => [
        'cover' => t('Cover'),
        'auto' => t('Auto'),
      ],
      '#default_value' => $default_size,
      '#description' => t("set Background size : cover for block orckester, auto for image orckester."),
    );

    // Element form bg attachment
    $attachment = $block->getThirdPartySetting('background_block', 'bg_settings')['attachment'];
    $default_attachment = ($attachment != null) ? $attachment : 'scroll';
    $form['third_party_settings']['background_block']['bg_settings']['attachment'] = array(
      '#type' => 'select',
      '#title' => t('Background attachment'),
      '#options' => [
        'fixed' => t('Fixed'),
        'scroll' => t('Scroll'),
      ],
      '#default_value' => $default_attachment,
      '#description' => t("set Background attachment :fixed or scroll. "),
    );

    // Element form bg repeat
    $repeat = $block->getThirdPartySetting('background_block', 'bg_settings')['repeat'];
    $default_repeat = ($repeat != null) ? $repeat : 'no-repeat';
    $form['third_party_settings']['background_block']['bg_settings']['repeat'] = array(
      '#type' => 'select',
      '#title' => t('Background repeat'),
      '#options' => [
        'no-repeat' => t('No-repeat'),
        'repeat' => t('Repeat'),
      ],
      '#default_value' => $default_repeat,
      '#description' => t("set Background repeat/no-repeat."),
    );

    // Element form bg posiiton-x
    $positionx = $block->getThirdPartySetting('background_block', 'bg_settings')['positionx'];
    $default_positionx = ($positionx != null) ? $positionx : 'left';
    $form['third_party_settings']['background_block']['bg_settings']['positionx'] = array(
      '#type' => 'select',
      '#title' => t('Background-position x'),
      '#options' => [
        'left' => t('left'),
        'center' => t('center'),
        'right' => t('right'),
      ],
      '#default_value' => $default_positionx,
      '#description' => t("set Background-position x"),
    );

    // Element form bg posiiton-y
    $positionz = $block->getThirdPartySetting('background_block', 'bg_settings')['positionz'];
    $default_positionz = ($positionz != null) ? $positionz : 'top';
    $form['third_party_settings']['background_block']['bg_settings']['positionz'] = array(
      '#type' => 'select',
      '#title' => t('Background-position z'),
      '#options' => [
        'top' => t('top'),
        'center' => t('center'),
        'bottom' => t('bottom'),
      ],
      '#default_value' => $default_positionz,
      '#description' => t("set Background-position z"),
    );

    // Element form padding
    $padding = $block->getThirdPartySetting('background_block', 'bg_settings')['padding'];
    $default_padding = ($padding != null) ? $padding : 0;
    $form['third_party_settings']['background_block']['bg_settings']['padding'] = array(
      '#type' => 'select',
      '#title' => t('Padding'),
      '#options' => [
        0 => t('0 px'),
        10 => t('10 px'),
        15 => t('15 px'),
        20 => t('20 px'),
        25 => t('25 px'),
        30 => t('30 px'),
        35 => t('35 px'),
        40 => t('40 px'),
        45 => t('45 px'),
        50 => t('50 px'),
        60 => t('60 px'),
        70 => t('70 px'),
        80 => t('80 px'),
        90 => t('90 px'),
        100 => t('100 px'),
        150 => t('150 px'),
        200 => t('200 px'),
        250 => t('250 px'),
        300 => t('300 px'),
      ],
      '#default_value' => $default_padding,
      '#description' => t("Padding Block"),
    );

    foreach (array_keys($form['actions']) as $action) {
      if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
        $form['actions'][$action]['#submit'][] = 'background_block_form_block_submit';
      }
    }
  }
}

En configurant sur TRUE le $form['third_party_settings']['#tree'], les informations seront sauvegarder automatiquement dans le third party settings du block au submit, tout comme la configuration est récuperable également en appelant le $block->getThirdPartySetting('background_block', 'bg_settings')['bgi'] de l'élément désiré.

Notons que nous téléchargeons les images dans le dossiers public://background-block/images/ c'est à dire dans /sites/default/file/background-block/images.

// Element form bg image
$form['third_party_settings']['background_block']['bg_settings']['bgi'] = array(
  '#type' => 'managed_file', 
  '#upload_location' => 'public://background-block/images/',
  '#title' => t('Image'),
  '#description' => t("Image to show on the background"),
  '#default_value' => $block->getThirdPartySetting('background_block', 'bg_settings')['bgi'],
  '#upload_validators' => array(
    'file_validate_extensions' => array('gif png jpg jpeg'),
  ),
);

 

background_block_form_block_submit()

Nous devons créer notre function de submit qui permettra une sauvegarde permanente de l'image.

/**
 * Implements background_block_form_block_submit().
 * @params $form
 * @params FormStateInterface $form_state
 */
function background_block_form_block_submit(array $form, FormStateInterface $form_state){
  // We do not want orphan image, prepare the fid of the current image, if there is one
  $current_fid = $form['third_party_settings']['background_block']['bg_settings']['bgi']['#default_value'][0];
  // get the image background block field
  $image = $form_state->getValue('third_party_settings')['background_block']['bg_settings']['bgi'][0];
  // If an image valid in the form run image archive process
  // ElseIf, no image, but a default referensed image (we come to delete an image), so, delete it.
  if ($image) {
    // Load the object of the image file by it's fid
    $file = File::load($image);
    // Check if file is permanent
    if ($file->isTemporary()) {
      // Set the status flag permanent of the image file object
      $file->setPermanent();
      // Save the file in database ( "managed_file" table)
      $file->save();
      // Let's check if the image has changed
      if ($current_fid && ($current_fid != $image)) {
        file_delete($current_fid);
      }
    }
  } elseif ($current_fid && (is_null($image))) {
    file_delete($current_fid);
  }
}


Enfin nous terminons avec avec le rendu que nous implémentons avec le hook_preprocess_HOOK(), le HOOK final équivaux à block, nous nous adressons aux blocks.

/**
 * Implements hook_preprocess_HOOK().
 */
function background_block_preprocess_block(&$variables) {
  // Blocks coming from page manager widget does not have id.
  if (!empty($variables['elements']['#id'])) {
    $block = Block::load($variables['elements']['#id']);
    if ($bg_settings = $block->getThirdPartySetting('background_block', 'bg_settings')) {
      $active = (int)$bg_settings['bgi_active'];
      if ($active != 0) {
        // Check variable settings
        $url_fichier = null;
        $bgi = (isset($bg_settings['bgi'][0])) ? (int)$bg_settings['bgi'][0] : null;
        $bgc = (string)$bg_settings['bgc'];
        $padding = (int)$bg_settings['padding'];
        $size = (string)$bg_settings['size'];
        $repeat = (string)$bg_settings['repeat'];
        $attachment = (string)$bg_settings['attachment'];
        $positionx = (string)$bg_settings['positionx'];
        $positionz = (string)$bg_settings['positionz'];
        $position = ($size == 'auto') ? $positionx . ' ' . $positionz : 'center';
        // Check if array settings is not empty
        if ($bgi) {
          // Prepare the file
          $file =  File::load($bgi);
          // Check if is a file
          if ($file) {
            $url_fichier = 'url(' . $file->url() . ')';
          }
        }
        // Clean the render
        $image = new FormattableMarkup('margin:0;padding:@paddingpx !important;background:@color @image @repeat @position @attachment;-webkit-background-size: @size;background-size: @size;', [
          '@image' => $url_fichier,
          '@padding' => $padding,
          '@size' => $size,
          '@color' => $bgc,
          '@repeat' => $repeat,
          '@position' => $position,
          '@attachment' => $attachment,
        ]);
        // Set variables attributes
        $variables['attributes']['style'][] = $image;
      }
    }
  }
}

 

Vous pouvez observer le résultat en vous rendant sur la page d'administration des blocks et en ouvrant la configuration d'un block.
background block configuration