Créer des entités par le code

Un écran avec du code

Lors de nos précédents articles sur la conception d'un profil d'installation Drupal 8 en vue d'industrialiser la conception de sites (dans le cas par exemple d'une usine à sites Drupal 8), nous avons abordé la création par le code aussi bien d'entités de configuration, que des entités de contenus. Fournir une configuration par défaut de façon programmatique permet de pouvoir modifier et gérer cette configuration de façon indépendante. Tandis que la création automatisée de contenus par défaut permet de favoriser l'appropriation d'un nouveau site généré dans le cadre d'une usine.

Ce billet est une petite compilation de snippet permettant de générer des entités de configuration ou encore des contenus de façon programmatique.

Afin de pouvoir appeler rapidement ces snippets nous allons les déclarer dans une classe utilitaire Uas qu'il nous suffira d'instancier pour disposer de ses différentes méthodes. A noter que vous devrez déclarer dans le fichier de cette classe les différentes classes à charger. Par exemple.

/**
 * @file
 * Contains \Drupal\uas\Uas.
 */

namespace Drupal\uas;


use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\block_content\Entity\BlockContent;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\block\Entity\Block;
use Drupal\Component\Utility\Random;
use Drupal\node\Entity\Node;
use Drupal\Component\Transliteration\PhpTransliteration;
use Drupal\taxonomy\Entity\Term;
use Drupal\file\Entity\File;
use Drupal\comment\Entity\Comment;
use Drupal\Component\Transliteration\TransliterationInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\pathauto\Entity\PathautoPattern;
use Drupal\Component\Utility\Unicode;
use Drupal\pathauto\PathautoPatternInterface;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\image\Entity\ImageStyle;

 

Créer un style d'image

/**
 * @param string $name
 *   The machine name of image style.
 * @param string $label
 *   The label of image style.
 * @param array $effect
 *   The effect applied to image style.
 * @param integer $width
 *   The width used in effect.
 * @param integer $height
 *   The height used in effect.
 * @param bool $upscale
 *   Upscale or not the image.
 *
 * @return \Drupal\image\Entity\ImageStyle $style
 *   The Image style entity created.
 */
public function createImageStyle($name, $label, $effect, $width, $height, $upscale = FALSE) {
  /** @var \Drupal\image\Entity\ImageStyle $style */
  $style = ImageStyle::create([
    'name' => $name,
    'label' => $label,
  ]);

  // Add an effect to the image style.
  $effect = [
    'id' => $effect ,
    'data' => [
      'width' => $width,
      'height' => $height,
      'upscale' => $upscale,
    ],
    'weight' => 0,
  ];

  $style->addImageEffect($effect);
  $style->save();

  return $style;
}

Les différentes valeurs possibles de la variable $effect sont:

image_convert, image_crop, image_desaturate, image_resize, image_rotate, image_scale, image_scale_and_crop

Créer un motif pour Pathauto

/**
 * Creates a pathauto pattern.
 *
 * @param string $id
 *   The label id.
 * @param string $entity_type_id
 *   The entity type.
 * @param string $pattern
 *   The path pattern.
 * @param array $bundles
 *   The bundles condition. Bundles added must be keyed with bundle name.
 * @param int $weight
 *   (optional) The pattern weight.
 *
 * @return \Drupal\pathauto\PathautoPatternInterface
 *   The created pattern.
 */
public function createPattern($id, $entity_type_id, $pattern, $bundles = [], $weight = 10) {
  /** var \Drupal\pathauto\Entity\PathautoPattern $pattern */
  $pattern = PathautoPattern::create([
    'id' => Unicode::strtolower($id),
    'label' => Unicode::strtolower($id),
    'type' => 'canonical_entities:' . $entity_type_id,
    'pattern' => $pattern,
    'weight' => $weight,
  ]);

  if($bundles) {
    $pattern->addSelectionCondition(
      [
        'id' => 'entity_bundle:' . $entity_type_id,
        'bundles' => $bundles,
        'negate' => FALSE,
        'context_mapping' => [
          $entity_type_id => $entity_type_id,
        ]
      ]
    );

  }

  $pattern->save();

  return $pattern;
}

Placer un block créé depuis Views

/**
 * @param string $id
 *   The id we gave to the block instance.
 * @param string $plugin
 *   The plugin uuid of the block views we want place.
 * @param string $theme
 *   The theme machine name.
 * @param string $region
 *   The region machine name.
 * @param string $visibility_key
 *   The visibility configuration type.
 * @param array $visibility
 *   An array containing visibility configuration.
 */
public function placeViewsBlock($id, $plugin, $theme, $region, $visibility_key = 'request_path',  $visibility = []) {

  $blockManager = $this->entityTypeManager->getStorage('block');
  /** @var \Drupal\block\Entity\Block $block */
  $block = $blockManager->create(
    array(
      'id'=> $id,
      'plugin' => $plugin,
      'theme' => $theme,
    )
  );

  $block->setRegion($region);
  
  if ($visibility && !empty($visibility_key)) {
    $block->setVisibilityConfig($visibility_key, $visibility);
  }
  
  $block->save();
}

Placer un block de contenu

/**
 * @param unique string $id
 *   The unique id of the block instance.
 * @param \Drupal\block_content\Entity\BlockContent $blockContent
 *   The BlockContent entity.
 * @param $region
 *   The region machine name.
 * @param integer $weight
 *   The block weight.
 * @param array $visibility
 *   An array containing visibility condition
 * @param string $visibility_key
 *   the visibility type configuration.
 * @param string $display
 *   Displaying the block title (string 'visible') or not (empty string)
 *
 * @return \Drupal\block\Entity\Block $block
 */
public function placeBlock($id, BlockContent $blockContent, $region, $weight = 0, $visibility = [], $visibility_key = 'request_path', $display = 'visible') {

  /** @var \Drupal\block\Entity\Block $block */
  $block = Block::create([
   'id' => $id,
   'plugin' => 'block_content:' . $blockContent->uuid(),
   'region' => $region,
   'provider' => 'block_content',
   'weight' => $weight,
   'theme' => \Drupal::config('system.theme')->get('default'),
   'visibility' => [],
   'settings' => [
     'label' => $blockContent->label(),
     'label_display' => $display,
     'info' => $blockContent->label(),
   ],
 ]);

  if ($visibility & !empty($visibility_key)) {
    $block->setVisibilityConfig($visibility_key, $visibility);
  }
  
  $block->save();
  return $block;
}

Créer un contenu

/**
 * @param string $type
 *   The content type.
 * @param string $title
 *   the content title.
 * @param string $langcode
 *   the content langcode.
 * @param string $uid
 *   The author's uid.
 * @param array $fields
 *   An array of field values keyed by field_name. 
 * @param bool $promote
 *   The content is promote to frontpage.
 * @param bool $status
 *   The content is published.
 * 
 * @return \Drupal\node\Entity\Node $node
 *   The node entity.
 */
public function createNode ($type, $title, $langcode, $path ='' , $uid = '1', $fields = [], $promote = FALSE, $status = TRUE){
  /** @var \Drupal\node\Entity\Node $node */
  $node = Node::create(array(
    'type' => $type,
    'title' => $title,
    'uid' => $uid,
    'status' => $status,
    'promote' => $promote,
    'langcode' => $langcode,
    'path' => $path,
  ));

  if (empty($fields)) {
    $node->save();
    return $node;
  }

  else {
    foreach ($fields as $field_name => $value) {
      if ($node->hasField($field_name)) {
        $node->set($field_name, $value);
      }
    }

    $node->save();
    return $node;
  }

}

Créer un block de contenu

/**
 * Creates a block content given type, info and fields.
 *
 * @param string $type
 *   The block content type.
 * @param string $info
 *   The block content info.
 * @param array $options
 *   array of options.
 * @param array $fields
 *   array of value keyed by fieldname.
 *
 * @return \Drupal\block_content\Entity\BlockContent
 *   The block content.
 */
public function createBlockContent($type, $info, $options = [], $fields = []) {
  $edit = [
    'type' => $type,
    'info' => $info,
  ];

  if (!empty($options)) {
    foreach ($options as $key => $value){
      $edit[$key] = $value;
    }
  }

  /** @var \Drupal\block_content\Entity\BlockContent $block_content */
  $block_content = BlockContent::create($edit);

  if (empty($fields)) {
    $block_content->save();
    return $block_content;
  }

  else {
    foreach ($fields as $field_name => $value) {
      if ($block_content->hasField($field_name)) {
        $block_content->set($field_name, $value);
      }
    }

    $block_content->save();
    return $block_content;
  }

}

Créer un lien de menu

/**
 * Creates a menu link given text and path.
 *
 * @param string $text
 *   The menu link text.
 * @param string $path
 *   The menu link path.
 *   Available path : 'route:contact.site_page' or 'internal:/contact' or 'entity:node/' . $node->id()
 * @param int $weight
 *   The menu link weight.
 * @param string $menu
 *   The menu to add the link to.
 * @param integer $expanded
 *   The menu link is expanded or not if it has children.
 * @param string $parent
 *   The parent menu item uuid to attach the link to.
 * @param string $langcode
 *   The menu item langcode.
 *
 * @return \Drupal\menu_link_content\Entity\MenuLinkContent
 *   The saved menu link.
 */
public function createMenuLink($text, $path, $weight = 0, $menu = 'main', $expanded = 1, $parent = NULL, $langcode = 'fr') {
  /** @var  \Drupal\menu_link_content\Entity\MenuLinkContent $menu_link */
  $menu_link = MenuLinkContent::create([
    'title' => $text,
    'link' => ['uri' => $path],
    'menu_name' => $menu,
    'weight' => $weight,
    'expanded' => $expanded,
    'langcode' => $langcode,
  ]);
  if ($parent !== NULL) {
    $menu_link->set('parent', 'menu_link_content:' . $parent);
  }
  $menu_link->save();
  return $menu_link;
}

Créer des termes de taxonomie

/**
 * @param string $vocabulary
 *   The vocabulary machine name.
 * @param string $term_names
 *   Term's names to create separated by comma.
 * @param string|Boolean $return
 *   Permit to return an array containing all term object created if return = 'term'.
 *   Otherwise return an array of term ids keyed by target_id.
 * 
 * @return array $terms->id() keyed by target_id or an array of terms entities.
 */
public function createTerms($vocabulary, $term_names, $return = FALSE) {
  $term_ids = array();
  foreach (explode(',', $term_names) as $term_name) {
    $term_name = trim($term_name);

    // The term may already exist in this vocabulary.
    $terms = entity_load_multiple_by_properties('taxonomy_term', array(
      'name' => $term_name,
      'vid' => $vocabulary
    ));
    if (empty($terms)) {
      // If not, create a new one.
      /** @var \Drupal\taxonomy\Entity\Term $term */
      $term = Term::create(
        array(
          'name' => $term_name,
          'vid' => $vocabulary,
        )
      );
      $term->save();
    }
    else {
      // If found, there should be only one.
      $term = array_shift($terms);
    }
    
    
    if ($return == 'term') {
      $term_ids[] = $term;
    }
    else {
      $term_ids[] = array('target_id' => $term->id());
    }

  }
  return $term_ids;
}

Créer des fichiers / images

/**
 * @param array $files
 *   array of files to import
 * @param string $destination
 *   The public destination where files are copied
 *   example : images/actualite
 * @return array $images
 *   an array on File object
 */
public function createFiles($sources = [], $destination = '' ) {
  $files = array();
  $year = date('Y');
  $month = date('m');
  $dirname = 'public://' . $destination . '/' . $year . '/' . $month;
  file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);

  foreach ($sources as $file_name) {

    $uri = file_unmanaged_copy($file_name, $dirname . '/' . basename($file_name), FILE_EXISTS_RENAME);
    $file = File::Create([
      'uri' => $uri,
    ]);
    $file->save();
    $files[] = $file;
  }

  return $files;
}

Créer un commentaire

/**
 * @param string $field_name
 *   The field name of the comment field.
 * @param \Drupal\node\Entity\Node $node
 *   The node entity the comment is related.
 * @param array $fields
 *   An array of fields values keyed by field_name.
 * @param string $type
 *   The comment type.
 * @param string $subject
 *   The comment's subject.
 * @param string $uid
 *   The comment's author uid.
 * @param string $entity_type
 *   The entity type the comment is related.
 * @param int $status
 *   The comment is published.
 * 
 * @return \Drupal\comment\Entity\Comment $comment
 *   The comment entity.
 */
public function createComment($field_name, Node $node, $subject = '', $fields = [], $type = 'comment', $uid ='1', $entity_type = 'node', $status = 1) {
  /** @var \Drupal\comment\Entity\Comment $comment */
  $comment = Comment::create(array(
    'comment_type' => $type,
    'subject' => $subject,
    'uid' => $uid,
    'entity_type' => $entity_type,
    'field_name' => $field_name,
    'entity_id' => $node->id(),
    'status' => $status,
  ));

  if (empty($fields)) {
    $comment->save();
    return $comment;
  }

  else {
    foreach ($fields as $field_name => $value) {
      if ($comment->hasField($field_name)) {
        $comment->set($field_name, $value);
      }
    }

    $comment->save();
    return $comment;
  }

}

Créer un paragraph

/**
 * @param string $type
 *   The paragraph type.
 * @param array $fields
 *   An array containing field values keyed by field_name.
 * @return \Drupal\paragraphs\Entity\Paragraph $paragraph
 *   The paragraph entity.
 */
public function createParagraph($type, $fields = []) {
  $paragraph = Paragraph::create([
    'type' => $type,
  ]);

  if (empty($fields)) {
    $paragraph->save();
    return $paragraph;
  }

  else {
    foreach ($fields as $field_name => $value) {
      if ($paragraph->hasField($field_name)) {
        $paragraph->set($field_name, $value);
      }
    }

    $paragraph->save();
    return $paragraph;
  }

}

N'hésitez pas à partager d'autres snippets bien utiles que vous pourriez avoir sous le coude dans les commentaires. Et si vous recherchez un développeur Drupal 8 pour des besoins plus avancées, vous pouvez me contacter.

 

Ajouter un commentaire