PHP

Entity Reference Selection

Entity Reference Selection

To 'alter' what shows in an entity reference selection

Reference https://drupal.stackexchange.com/questions/298105/can-i-create-non-default-entityreferenceselection

In src/Plugin/EntityReferenceSelection

<?php

namespace Drupal\YOUR_MODULE\Plugin\EntityReferenceSelection;

use Drupal\node\Plugin\EntityReferenceSelection\NodeSelection;

/**
 * Provides a query for a node entity reference selection.
 *
 * @EntityReferenceSelection(
 *   id = "YOUR_MODULE_REFERENCE_SELECTION_ID",
 *   label = @Translation("Filter nodes with a specific field value."),
 *   entity_types = {"node"},
 *   group = "YOUR_MODULE_REFERENCE_SELECTION_GROUP",
 *   weight = 1
 * )
 */
class YourModuleEntityReferenceSelection extends NodeSelection {
  /**
   * {@inheritdoc}
   */
  protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
    $query = parent::buildEntityQuery($match, $match_operator);
    $query->condition('field_featured', 1', '=');
    return $query;
  }
}

Set Message with a link as an argument

Set Message with a link as an argument

Need to output a message with a link in the text?

$link = Link::createFromRoute('Link Title', 'my_module.my_route', [
          'argument' => 'argument value',
        ]);
        
        $m_args = ['%message_link' => $link->toString()];
        
        \Drupal::messenger()->addStatus(t('Here is a message, and here is a link. %message_link', $m_args));

Output Twig Values in console.log

Output Twig Values in console.log

Trying to debug twig? Not rendering? Try this from within your twig file...

<script>console.log({{ _context | json_encode | raw}});</script>

 

Create a simple service

Create a simple service

Also includes dependency injection

MY_MODULE.services.yml

services:
  my_module.cool_service:
    class: Drupal\my_module\Services\CoolService
    arguments: ['@logger.factory']

/src/Services/CoolService.php

<?php

namespace Drupal\my_module\Services;

use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * CoolService returns what you give it in an array.
 */
class CoolService {


  /**
   * Logger Factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $loggerFactory;


  /**
   * Constructs the Cool service.
   *
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory
   *   A Guzzle client object.
   */
  public function __construct(LoggerChannelFactoryInterface $loggerFactory) {
    $this->loggerFactory = $loggerFactory->get('my_module');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('logger.factory')
    );
  }

  public function doSomething($someData) {
    $output = [
      'my_data' => $someData;
    ];

    $this->loggerFactory->error('Lets log a message!');
    
    return $output;
  }


}

Calling the service

$coolService = \Drupal::service('my_module.cool_service');

$returnedData = $coolService->doSomething('My Data');

echo $returnedData;

 

Update field values in multiple paragraphs

Update field values in multiple paragraphs

Let's say you have a LOT of paragraphs on your site. (Meaning Drupal Paragraphs contributed module entities).

Now you want to update a field in all of them. Rather than trying to find each and every one within nodes, you can run a simple script to update a field value.

This will simply load all paragraphs of a specific bundle. Then for each one, you update a value then save.

If you have a lot of paragraphs, you may want to run a batch process.

// Load all the paragraph entities of type
$entityManager = \Drupal::entityTypeManager();
$entities = $entityManager
    ->getStorage('paragraph')
    ->loadByProperties(['type' => 'MY_PARAGRAPH_TYPE','status' => 1]);

// Looping through each one and changing a value
// This could/should be set up in a batch process for a lot of items
foreach($entities as $key => $entity) {
    $paragraphStorage = $entityManager->getStorage('paragraph');
    $paragraph = $paragraphStorage->load($key);
    $paragraph->set('field_my_field','MY_NEW_VALUE');
    $paragraph->save();
}

 

Correct Timezone Handling

Correct Timezone Handling

Sometimes when outputting a Drupal date field, it will display in UTC, not in your desired timezone.

You can run the date through a few lines of code to output as desired.

$dt = new \DateTime($date[0]['value'], new \DateTimeZone('UTC'));
$dt->setTimeZone(new \DateTimeZone('America/Los_Angeles'));
$correct_date =  $dt->format('Y-m-d H:i:s');

 

Sending E-Mail in Drupal 8

Sending E-Mail in Drupal 8

Need to send an email from your custom module?

First, let's make a template file so you can add some HTML markup if you want. This will go in your custom_module/templates directory.

<h1>Here is a header for your e-mail</h1>
{{ text|raw }}

Sincerely,
{{ sender_name|raw }}

Some pieces that will go into your custom module

Include the template in your hook_theme()

Be sure to clear your cache for this template to be used.

/**
 * Implements hook_theme().
 * To add the template definition.
 **/
function MY_MODULE_theme($existing, $type, $theme, $path) {
  return [
    'my-custom-email' => [
      'variables' => [
        'text' => NULL,
        'sender_name' => NULL,
      ],
    ], 
  ];  
}

Add hook_mail()

/**
* Implements hook_mail().
*/
function MY_MODULE_mail($key, &$message, $params) {
 $options = array(
   'langcode' => $message['langcode'],
 );
 switch ($key) {
   case 'my_custom_key':
      $message['headers'] = $params['headers'];
      $message['from'] = $params['from'];
      $message['subject'] = $params['subject'];
      $message['body'][] = $params['message'];
      $message['params']['files'] = $params['attachments'];
      break;
 }
}

Now, you can wrap the emailing into a function while using variables such as the recipient, sender, etc.

<?php
  
function _send_my_custom_email($data) {
  // Set a reply-to value
  $reply_to = $data['reply_to'];
  
  // Set a from value
  $from = $data['from'];
  
  // Set a subject
  $subject = $data['subject']
  
  // Set a sender name
  $sender_name = $data['sender_name'];
  
  // Set a recipient email
  $to = $data['to'];
  
  // Set your message body
  $body = $data['body'];
  
  // Use the theme to send the message
  $theme_body = array(
    '#theme' => 'my-custom-email',
    '#text' => $body,
    '#sender_name' => $sender_name,
  );
  
  // Set up the Drupal Mail manager
  $mailManager = \Drupal::service('plugin.manager.mail');
  
  // Tell the mail system what module you are sending this from
  $module = 'my_custom_module';
  
  // Set up the parameters for your email from the variables
  $params['message'] = drupal_render($theme_body);
  // Set some header information
  $params['headers'] = [
    'content-type' => 'text/html',
    'MIME-Version' => '1.0',
    'reply-to' => $data['from'],
    'from' => 'sender name <' . $from . '>',
    'Return-Path' => 'sender name <' . $from . '>',
  ];
  $params['from'] = $from;
  $params['subject'] = $subject;
  
  // Need to attach a file? Maybe uploaded through a form
  if(!empty($data['attach'])) {
    $file_info = array();
    $file_info['filepath'] = $data['attach']['uri']; // File path
    $file_info['filename'] = $data['attach']['filename']; //File name
    $file_info['filemime'] = $data['attach']['filemime']; //File mime type
    $params['attachments'][] = $file_info;
  }
  
  
  // Set a key so you can send different types of message
  $key = 'my_custom_key';
  
  // Get the language code from your site
  $langcode = \Drupal::currentUser()->getPreferredLangcode();
  
  // Set sending to true in case there is other logic that needs to happen before
  $send = true;
  
  // Send the E-Mail
  $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);

}

Now, you can call the function to email while passing along some parameters

// Within a function that you are using that requires an email to be sent, you call the function with some data

use Drupal\file\Entity\File;

function _something_should_be_happening() {
  if($something == 'happened') {
    $data['reply_to'] = 'reply_to@example.com';
    $data['from'] = 'from@example.com';
    $data['subject'] = 'Subject text here';
    $data['sender_name'] = 'John Doe'; 
    $data['to'] = 'receiver@example.com';
    $data['body'] = 'A long value that can also hold <div>HTML Markup</div>';
    
    if($add_a_file == TRUE) {
      // Need to send a file attachment?
      // Load a file
      $file = File::load('FILE_ID');
      // attach some file info
      $data['attach']['uri'] = $file->getFileUri();
      $data['attach']['filename'] = $file->getFileName();
      $data['attach']['filemime'] = $file->getMimeType();
    }
  
    _send_my_custom_email($data);
    return;
  } else {
    return;
  }
}

 

Creating select form using Taxonomy and Form API

Creating select form using Taxonomy and Form API

Often times when using the Drupal Form API creating custom forms, you'll need to get a select list of Taxonomy terms as options. These snippets will help you look up terms in a vocabulary and put them in your options array.

Drupal 8

// Create empty options array
$options = array();

// Taxonomy vocabulary machine name
$taxonomy = 'tax_machine_name';

// Get all the taxonomy terms from the vocabulary
$tax_items = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($taxonomy);

// Inject into the options array
foreach($tax_items as $tax_item) {
  $options[$tax_item->tid] = $tax_item->name;
}

// Create a select form element
$form['taxonomy_options'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#required' => TRUE,
);


Drupal 7

// Create empty options array
$options = array();

// Taxonomy vocabulary machine name
$taxonomy = 'tax_machine_name';

// Get all the taxonomy terms from the vocabulary
$vocab = taxonomy_vocabulary_machine_name_load('tax_machine_name')->vid;
$tax_items = taxonomy_get_tree($vocab);

// Inject into the options array
foreach($tax_items as $tax_item) {
  $options[$tax_item->tid] = $tax_item->name;
}

// Create a select form element
$form['taxonomy_options'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#required' => TRUE,
);