Snippets

How to get all field names of field type

Components

To get a list of all field names for the fields whose field type is for example image you can use the entity_field.manager service:

$field_map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('image');

The field_map array will contain a list of fields by entity type.

Drupal 9 - Field names by field type
Drupal 9 - Field names by field type

How to programmatically change order status

Components

Changing the order state in Drupal Commerce 2.x like this:

$order->set('state', 'canceled');
$order->save();

is not a good idea because you are not dispatching transition events. And some modules depend on those events. The proper way to change the order state is to apply state transition like this:

$order = \Drupal::entityTypeManager()
  ->getStorage('commerce_order')
  ->load(1);
$order->getState()->applyTransitionById('cancel');
$order->save();

You can find the list of transition IDs in the workflows file.

How to programmatically add a language

Components

Sometimes you have to add a new language in Drupal 8/9 programmatically. For example, maybe you need to write an update hook that will add a new language. This is how you can do it:

use Drupal\language\Entity\ConfigurableLanguage;

$language = ConfigurableLanguage::createFromLangcode('sr');
$language->save();

If you don't know the langcode, you can find it by inspecting the select box on the /admin/config/regional/language/add page. 

How to set price field value programmatically in Drupal Commerce

Components

Price in Drupal Commerce 2.x is not a number but a class. This class has a price number and currency code properties, and both are strings. So, to set the product price programmatically you have to first instantiate the Price class:

$price = new \Drupal\commerce_price\Price('9.99', 'EUR');

and then use created Price object to set the product price:

$product_variation = \Drupal\commerce_product\Entity\ProductVariation::load(1);
$product_variation->set('price', $price);
$product_variation->save();

To get the price number and currency code you can use appropriate getters methods:

$price_number = $price->getNumber();
$currency_code = $price->getCurrencyCode();

You can also create a Price object by using the static method:

$price = Price::fromArray(['number' => '9.99', 'currency_code' => 'EUR']);

How to customize the Drupal Commerce order receipt email subject

Components

At the moment you can't configure the order receipt email subject. The subject is hardcoded in the OrderReceiptMail service.

There is an issue to fix this, but until that happens the only way to alter the email subject is to use the hook_mail_alter().

/**
 * Implements hook_mail_alter().
 */
function MY_MODULE_mail_alter(&$message) {
  if ($message['key'] == 'order_receipt' && !empty($message['params']['order'])) {
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $message['params']['order'];

    $message['from'] = 'noreply@example.com';
    $message['subject'] = t('Receipt for Order ID: @number', [
      '@number' => $order->getOrderNumber(),
    ]);
  }
}

How to generate masquerade link programmatically

Components

The Masquerade module allows website admins to switch users and visit the website as that user. This is helpful for developers and site builders when trying to find out what a client might see when logged into the website. To create the unmasquerade programmatically use this:

if (
  \Drupal::moduleHandler()->moduleExists('masquerade') && 
  \Drupal::service('masquerade')->isMasquerading()
){
  $links['unmasquerade'] = [
    '#type' => 'link',
    '#title' => t('Unmasquerade'),
    '#url' => Url::fromRoute('masquerade.unmasquerade'),
    '#weight' => 1500,
  ];
}

Drupal 8/9 and Guzzle HTTP client library

Components

Making a simple HTTP Get request in Drupal 8 or 9 is super easy thanks to the Guzzle library. This library has been added to Drupal core a long time ago, and it replaced the much less powerful drupal_http_request() function. Let's see how to get some data from the Star Wars API:

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

$client = new Client();
$people = [];

try {
  $response = $client->get('https://swapi.dev/api/people');
  $result = json_decode($response->getBody(), TRUE);
  foreach($result['results'] as $item) {
    $people[] = $item['name']; 
  }
}
catch (RequestException $e) {
  // log exception
}

Guzzle can also be accessed through the http_client service and the helper method:

$client = \Drupal::httpClient();

Sending a POST request is also simple and easy.

public function sendOrder(OrderInterface $order) {
  try {
    $response = $this->httpClient->post($url, [
      'form_params' => $data,
    ]);
    $response_data = json_decode($response->getBody()->getContents(), TRUE);

    // do something with data
  }
  catch (RequestException $e) {
    // log exception
  }
}

If you want to log the exception don't use $e->getMessage() because the error message will be truncated. Instead, use this:

$e->getResponse()->getBody()->getContents();

You can also use Guzzle to send files. To send an image file you can do something like this:

try {
  $client = new Client(['headers' => ['X-Auth-Secret-Token' => 'my-secret-token']]);
  $options = [
    'multipart' => [
      [
        'Content-type' => 'multipart/form-data',
        'name' => 'image',
        'contents' => fopen($image->getFileUri(), 'r'),
        'filename' => basename($image->getFileUri()),
      ],
    ],
  ];
  $response = $client->post($api_base_url . 'api/v1/images', $options);
}
catch (\Exception $e) {
  // log exception
}

In this case, the $image variable is an instance of Drupal\file\Entity\File class.

Change status message text

Components

Let's say that a contrib module is showing a message like this: Your message has been created, and you want to change it to something like this: Message created. To do this you don't have to hack the contrib module, you can use the hook_preprocess_HOOK() to alter the message.

/**
 * Implements hook_preprocess_HOOK().
 */
function MY_MODULE_preprocess_status_messages(&$variables) {
  if (isset($variables['message_list']['status'])){
    $status_messages = $variables['message_list']['status'];
    foreach($status_messages as $delta => $message) {
      if (strpos((string) $message, 'Your message has been created.') !== FALSE) {
        $variables['message_list']['status'][$delta] = t('Message created.');
      }
    }
  }
}

How to alter the page title?

Components

One way to alter the page title is to use hook_preprocess_HOOK() and then set the new page title depending on the current route name.

function MY_MODULE_preprocess_page_title(&$variables) {
  $route_name = \Drupal::routeMatch()->getRouteName();
  if ($route_name === 'entity.user.edit_form') {
    $variables['title'] = 'Edit My Account';
  }
}

This will only change the title in the Page title block. To actually change the <title> HTML tag you can use the following code snippet:

function MY_MODULE_preprocess_html(&$variables) {
  $route_name = \Drupal::routeMatch()->getRouteName();
  if ($route_name === 'entity.user.edit_form') {
    $variables['head_title']['title'] = t('Edit My Account')
  }
}

Hide fields in Inline Entity Form

Components

If you want to hide a field inside the Inline Entity Form you have to use the hook_inline_entity_form_entity_form_alter() hook – standard form alter hook won’t work. For example, to hide the status field you can do something like this:

/**
 * Implements hook_inline_entity_form_entity_form_alter().
 */
function MY_MODULE_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) {
  if (in_array($entity_form['#entity_type'], ['YOUR_ENTITY_TYPE_1', 'YOUR_ENTITY_TYPE_2'])) {
    $entity_form['status']['#access'] = FALSE;
  }
}