Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Feb 01 2021
Feb 01

Sending an email works with defining an email template (subject, text and possibly email headers) and the replacement values to use in the appropriate places in the template. Processed email templates are requested from hook_mail() from the module sending the email. Any module can modify the composed email message array using hook_mail_alter(). Finally \Drupal::service('plugin.manager.mail')->mail() sends the email, which can be reused if the exact same composed email is to be sent to multiple recipients.

Below function's triggerMail code, can be written in any submit handlers or post actions in Drupal.

function triggerMail() {
  $module = "x_module";
  $key = "x_mail";
  $to = "[email protected]";
  $langcode = 'en';
  \Drupal::service('plugin.manager.mail')->mail($module, $key, $to, $langcode);
}

Below is the hook_mail() usage, written in x_module.module file.

function x_module_mail($key, &$message, $params) {
  switch($key) {
    // To Trigger email on x_mail key.
    case 'x_mail':
      $message['headers'] = [
        'content-type' => 'text/html'
      ];
      $message['subject'] = t('X Mail subject');
      $message['body'][] = (string) getXMailMessageBody();
  }
}

Below is the helper function getXMailMessageBody() which can pull the dynamic data from the system and pass it through.

function getXMailMessageBody() {
  // Get Dynamic values.. then pass to twig file..
  return twig_render_template(
    drupal_get_path('module', 'x_module') . '/templates/x-mail.html.twig',
    [
      'theme_hook_original' => 'not-applicable',
      'dynamic_key1' => "{value1}",
      'dynamic_key2' => "{value2}
    ]
  );
}

Create a twig template file x-mail.html.twig in the module folder within templates folder.

Email Body and with dynamic values here {{ dynamic_key1 }} & {{ dynamic_key2 }}.

So, with these Drupal Mail service & custom template, you can send emails with customized message mails from your Drupal application.

Thank you :)

Original Article: https://peoplesblog.co.in/blogs/Sci-Tech/Drupal/2021-01-20-Send-Mail-with-Custom-Email-Template-and-with-Dynamic-values-via-Drupal-Mail-Service.html

Nov 14 2019
Nov 14

Submitted by karthikkumardk on Thursday, 14 November 2019 - 11:14:32 IST

The SimpleTest module has been deprecated in Drupal 8, and will be removed in Drupal 9.

Production sites should never have SimpleTest module installed since it is a tool for development only.

contributed module is now available for those who wish to continue using SimpleTest during the transition from Drupal 8 to 9.

However, developers are encouraged to write tests with PHPUnit, and to use the phpunit command line test runner: https://www.drupal.org/docs/8/phpunit/running-phpunit-tests

Note that the final decision to deprecate SimpleTest still has some dependencies on the in-progress Drupal 9 issue so exact details of the deprecation may be revised (#3075490: Move simpletest module to contrib).

Thanks :)

Nov 08 2019
Nov 08

The API that the JSON:API module makes available is centered on Drupal's entity types and bundles. Every bundle receives its own, unique URL path, which all follow a shared pattern

HTTP Methods

JSON:API specifies what HTTP Methods to accept. Those are: GET, POST, PATCH, and DELETE. Notably, PUT is not included.

  • GET - Retrieve data, can be a collection of resources or an individual resource
  • POST - Create a new resource
  • PATCH - Update an existing resource
  • DELETE - Remove an existing resource

Authentication

Typically some form of authentication is used for POST requests. The examples below all use Basic Authentication. Enable the HTTP Basic Authentication module, set the permission for the API user (and role) and set the encoded username and password to the 'Authorization' request header.

Headers

Make sure to use 'Content type' and 'Accept' headers when appropriate

Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

Response codes

The JSON:API Specification also dictates acceptable responses. The Drupal implementation uses a subset of those. The module can respond with the following codes:

  • 200 OK - All successful GET and PATCH requests
  • 201 Created - All successful POST requests (response includes the newly created resource)
  • 204 No Content - All successful DELETE requests

And here's the detailed documentation - https://www.drupal.org/docs/8/modules/jsonapi/get-post-patch-and-delete

And here's the sample postman collection - https://gitlab.com/heykarthikwithu/drupal-jsonapi---sample-api-calls

Thanks :)

Jul 25 2019
Jul 25

Submitted by karthikkumardk on Thursday, 25 July 2019 - 15:29:44 IST

file_scan_directory is deprecated and has been moved to the file_system service.

Before:

$files = file_scan_directory($directory);

After

if (is_dir($directory)) {
  $files = \Drupal::service('file_system')->scanDirectory($directory);
}

When possible, you should inject the FileSystemInterface into your constructor.

Original source - https://www.drupal.org/node/3038437

Jul 19 2019
Jul 19

Redis is an open-source, networked, in-memory, key-value data store that can be used as a drop-in caching backend for your Drupal

Add the Redis module from Drupal.org. You can install and enable the module from the command line.

Edit sites/default/settings.php to add the Redis cache configuration. These are the mandatory, required Redis configurations for every site.

// Use Redis for caching.
$conf['redis_client_interface'] = 'PhpRedis';
// Point Drupal to the location of the Redis plugin.
$conf['cache_backends'][] = 'sites/all/modules/redis/redis.autoload.inc';
$conf['cache_default_class'] = 'Redis_CacheCompressed';
$conf['cache_prefix'] = array('default' => 'pantheon-redis');
// Do not use Redis for cache_form (no performance difference).
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
// Use Redis for Drupal locks (semaphore).
$conf['lock_inc'] = 'sites/all/modules/redis/redis.lock.inc';

Enable the module via from /admin/modules

Verify Redis is enabled by going to the Dashboard and clicking "Connection Info". If you see the Redis cache connection string, Redis is enabled

Visit /admin/config/development/performance/redis and open Connection Information to verify the connection.

And once the Redis server is connected, one could use the PhpRedis functions to set the key & value pairs on Redis as seen below

function _get_value_redis_cache($key) {
    try {
        $redis = Redis_Client::getClient();
        return $redis->get($key);
    }
    catch (Exception $exception) {
        watchdog('redis_cache', t('Error, while getting the value from redis cache.'), custom_log(array($key, $redis)), WATCHDOG_ERROR);
    }
}

function _set_value_redis_cache($key, $value) {
    try {
        $redis = Redis_Client::getClient();
        $redis->set($key, $value);
        $now = time();
        $redis->expireAt($key, $now + 900);
        $redis->save();
    }
    catch (Exception $exception) {
        watchdog('redis_cache', t('Error, while setting the value from redis cache.'), custom_log(array($key, $value, $redis)), WATCHDOG_ERROR);
    }
}

Once these generic functions are ready, one could utlize this functions for setting and getting the values based on the keys as seen below

$key = "_get_tmp_value_from_redis";
$tmp = _get_value_redis_cache($key);
if (empty($tmp)) {
    $tmp = get_actual_value_from_db();
    _set_value_redis_cache($key, $tmp);
    return $tmp;
}
else {
    return $tmp;
}

cheers :)

Jul 17 2019
Jul 17

The Migrate Drupal UI module provides a web browser user interface for upgrading from Drupal 6 / 7 to Drupal 8. There is a pre-upgrade analysis which displays a list of legacy modules that will be upgraded and will not be upgraded. Included in those that will be upgraded are modules that do not need an upgrade, such as the Help module. In order for this analysis to be correct, some Drupal 8 modules must provide information in a MODULE_NAME.migrate_drupal.yml file in the module's migrations/state directory.

This applies to Drupal 8 modules that:

  • Provide migrations from a Drupal 6 or Drupal 7 module, or
  • Intend to provide those migrations in the future, or
  • Are a successor to a Drupal 6 or Drupal 7 module and want to communicate that no migration is needed.

This does not apply to modules that are brand new in Drupal 8 and have nothing to communicate about any Drupal 6 or Drupal 7 modules.

Syntax

finished:
  6:
    source_module: destination_module
    source_module_2: destination_module
    source_module_3:
    - destination_module
    - destination_module_2

  7:
    source_module: destination_module
    source_module_3:
    - destination_module
    - destination_module_2

not_finished:
  7:
    source_module_2: destination_module

As can be seen above, the data in migrations/state/MODULE_NAME.migrate_drupal.yml consists of migration sets where each set is a source module for a legacy Drupal version (6 or 7), and one or more destination modules for the current Drupal version (8). The source module and destination modules correspond to the source_module and destination_module definitions in the migrations. And each set can be declared either 'finished' or 'not_finished'. For a set to be "finished", all of the migrations for the set must exist. If a module maintainer knows that they have not yet provided all of the migrations that are needed from a given source module to one or more destination modules, then they should declare that set as "not_finished".

Merging state across provider modules, source modules, and destination modules

Each module's migrations/state/MODULE_NAME.migrate_drupal.yml file defines the state of the migrations that are provided (or intended to be provided in the future) by that module. In most cases, destination modules are the sole providers of migrations to themselves. For example, the dblog module is the sole module that provides migrations from earlier versions of itself to itself. In some cases, modules provide migrations for other destination modules. For example, the Content Translation module provides migrations from earlier versions of the Statistics module to the current version of the Statistics module. This is in addition to the migrations provided by the Statistics module itself.

The Migrate Drupal module considers a source module / destination module pair as not finished if there is any provider that declares it as not finished. For example, in the above example, if the Content Translation module in its .migrate_drupal.yml were to declare that statistics: statistics were "not_finished", then Migrate Drupal considers that pair to be not finished, even if the Statistics module itself is finished with the migrations that it intends to provide.

Similarly, a given source module is considered not finished overall, if there exists at least one destination module for which it is declared as not finished. For example, there are migrations from the Drupal 6/7 Menu module to several Drupal 8 destination modules (System, Menu UI, and Custom Menu Links). If any one of those pairs (e.g., menu: system, menu: menu_ui, or menu: menu_link_content) were declared as not finished (by any provider module), then on the Migrate Drupal UI pre-upgrade review screen, the Menu module would be listed as "will not be upgraded".

Usage

If the Drupal 8 module is not providing migrations, now or in the future, for its legacy version then create a migrate_drupal.yml. Declare a finished migration for each legacy Drupal version. See scenario 1 below.

If the Drupal 8 module is or will be providing migrations for a legacy module then create a migrate_drupal.yml file. For each source_module:destination_module pair used by the migrations in your module do the following for Drupal 6 and Drupal 7.

  • If the migrations for the pair are complete add a line in the "finished" array for the relevant Drupal version.
  • If at least one migration for a pair exists but the pair is not finished add an entry to "not_finished" for the relevant Drupal version.
  • If the migrations needed for the pair do not exist then add a line in the "not_finished" array for the relevant Drupal versions.

Examples

Scenario 1. A successor to a legacy module that for any reason will not be providing a migration. Let's use Pirate as the example. Currently, if Pirate is enabled on the legacy site it will be displayed as will not be upgraded when it should be listed as will be upgraded. To make that happen simply declare a migration set with pirate as the source module and destination module as finished.

finished:
  6:
     pirate: pirate
  7:
     pirate: pirate

Scenario 2. The legacy version of your module has content and configuration that needs to be upgraded. Your module provides two migrations with the same source_module:destination_module pair for both Drupal 6 and Drupal 7 and all migrations are finished.

finished:
   6:
     google_analytics: google_analytics
   7:
     google_analytics: google_analytics

Scenario 3. Your module provides migrations. The Drupal 6 version is complete but the Drupal 7 is not. Note there may be zero or more migrations for Drupal 7 in your module but more are needed for it to be complete.

 finished:
    6:
      google_analytics: google_analytics
  not_finished:
    7:
      google_analytics: google_analytics

Scenario 4. Your module provides migrations for other modules with many pairs, such as Commerce Migrate Module.

finished:
    6:
      node: commerce_product
      system: commerce_store
    7:
      node: commerce_product
      commerce_product: commerce_product
      system: commerce_store
  not_finished:
    6:
      uc_orders: commerce_order
    7:
      uc_orders: commerce_order
      commerce_order: commerce_order

Scenario 5. Your module provides a migrate field plugin for a legacy field, such as Address Module.

  finished:
    6:
      adressfield: address
    7:
      adressfield: address

Scenario 6. Menu, JQuery UI, Blog, Color and many other modules moved directly into Core. These are denoted as 'core' for the destination and are treated specially. They are marked as finished since these do not have an upgrade path and site upgraders do not need to look for an equivalent project to install in Drupal 8.

finished:
  6:
    blog: core
    blogapi: core
    calendarsignup: core
    color: color
  7:
    blog: core
    bulk_export: core
    contextual: core
    ctools: core

Cheers :)

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web