Skip to content

Instantly share code, notes, and snippets.

@l3th2nh
Forked from bdlangton/Blocks.md
Created March 17, 2020 16:24
Show Gist options
  • Select an option

  • Save l3th2nh/2f7cc835ed6f0e9a31cb32feb8cd709f to your computer and use it in GitHub Desktop.

Select an option

Save l3th2nh/2f7cc835ed6f0e9a31cb32feb8cd709f to your computer and use it in GitHub Desktop.
Drupal 8 programmatic solutions

Config

Get a config.

\Drupal::service('config.factory')->getEditable('system.performance');

Update a config value.

\Drupal::service('config.factory')->getEditable('system.performance')->set('cache.page.enabled', 1)->save();

State

Update a state value.

\Drupal::service('state')->set('du_admission_steps.importer.last_run', NULL);

DB Stuff

Simple database query.

$results = \Drupal::database()->query('select * from purge_queue')->fetchAll();

Debugging an entity query, enable the devel module and add tag before execute.

$entity_query->addTag('debug')->execute();

IS NULL (and IS NOT NULL) checks on entityQuery.

$result = \Drupal::entityQuery('node')
  ->condition('field_banner_code', NULL, 'IS NULL')
  ->execute();

Delete all 'event' nodes.

$result = \Drupal::entityQuery('node')
  ->condition('type', 'event')
  ->execute();
entity_delete_multiple('node', $result);
// Add ->range(0, 10) to delete a range

Insert statement.

$query = \Drupal::database()->insert('purge_queue');
$query->fields(['data', 'created']);
$query->values(['a:4:{i:0;s:3:"url";i:1;a:4:{s:10:"66849f6f11";i:3;s:10:"c990b129a0";i:3;s:10:"c618828456";i:3;s:10:"453d844ea2";i:3;}i:2;s:66:"http://www.example.com";i:3;a:0:{}}', time()]);
$query->execute();

Update statement.

$query = \Drupal::database()->update('mcpl_events_feeds_item');
$query->fields(['hash' => 'update']);
$query->condition('nid', 1);
$query->execute();

Delete statement.

$query = \Drupal::database()->delete('purge_queue');
$query->condition('data', '%url%', 'LIKE');
$query->execute();

Debugging

Debug backtrace any error.

// This function exists in core/includes/bootstrap.inc.
// Just need to add lines 6-8 to it.
function _drupal_error_handler($error_level, $message, $filename, $line, $context) {
  require_once DRUPAL_ROOT . '/includes/errors.inc';
  require_once DRUPAL_ROOT . '/modules/contrib/devel/kint/kint.module';
  $d = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
  ksm($message, $d);
  _drupal_error_handler_real($error_level, $message, $filename, $line, $context);
}

Debugging search API solr queries:

// You can output the Request object using kint/kpm, but it can be hard
// to figure out where to set the debugging code. The best place is in
// the executeRequest function in the following file:
// search_api_solr/src/SolrConnector/SolrConnectorPluginBase.php

Starting point for debugging ElasticSearch stuff, in the file

// src/ElasticSearch/Parameters/Builder/SearchBuilder.php:
// Add ksm at the end of build() and getSearchQueryOptions()

Service

services.yml:

services:
  du_user_management:
    class: Drupal\du_user_management\UserManagementService
    arguments: ['@cache.default', '@logger.channel.du_user_management']
  logger.channel.du_user_management:
    class: Drupal\Core\Logger\LoggerChannel
    factory: logger.factory:get
    arguments: ['du_user_management']

Service file

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache.
   * @param \Drupal\Core\Logger\LoggerChannelInterface $logger
   *   The logger channel.
   */
  public function __construct(CacheBackendInterface $cache, LoggerChannelInterface $logger) {
    $this->cache = $cache;
    $this->logger = $logger;
  }

Controller or Form

Controller/Form File

  /**
   * {@inheritdoc}
   */
  public function __construct(UserManagementService $user_management) {
    $this->userManagement = $user_management;
  }

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

Plugin

Plugin File

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, UserManagementService $client, ConfigFactoryInterface $config_factory) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->client = $client;
    $this->configFactory = $config_factory;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('du_user_management'),
      $container->get('config.factory')
    );
  }

Entities

Load an entity. Can be a config entity also.

$node = \Drupal::entityTypeManager()->getStorage('node')->load(23);
$search_api_index = \Drupal::entityTypeManager()->getStorage('search_api')->load('title_records');

Load multiple entities (if no param is passed, all entities are loaded).

$node = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($entity_ids);

Delete multiple entities.

$result = \Drupal::entityQuery('taxonomy_term')
      ->condition('vid', 'libraries')
      ->execute();
entity_delete_multiple('taxonomy_term', $result);

Adding a new field to a custom entity.

$new_field = BaseFieldDefinition::create('string')
  ->setLabel(new TranslatableMarkup('New Field'))
  ->setDescription(new TranslatableMarkup('New field description.'));
\Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition('<field_name>', '<entity_type_id>', '<provider>', $new_field);

Apply all updates to entities.

\Drupal::entityDefinitionUpdateManager()->applyUpdates();

Load a file

$file = \Drupal\file\Entity\File::load(1007);
OR
$file = \Drupal::entityTypeManager()->getStorage('file')->load(1007);

Working with file entities

// Get the URI (including wrapper, such as public://).
$uri = $file->getFileUri();

// Get the full URL path.
$url = file_create_url($file->getFileUri());

// Get relative path of the URL (w/o domain).
$path = file_url_transform_relative($url);

Images

Render array for an image style.

$render = [
  '#theme' => 'image_style',
  '#style_name' => 'thumbnail',
  '#uri' => 'public://my-image.png',
];

Image style, get URL (full URL including http://).

$style = \Drupal::entityTypeManager()->getStorage('image_style')->load('thumbnail');
$image_url = $style->buildUrl('public://du_content_gallery-article.jpg');

Image style, get URI (public://path-to-image-style).

$style = ImageStyle::load('thumbnail');
$image_url = $style->buildUri('public://du_content_gallery-article.jpg');

Adding Libraries

In preprocess function or controller function.

$variables['#attached']['library'][] = 'lotus/lotus-js';

In twig template file.

{{ attach_library('hcpl_zen/title-record') }}

Miscellaneous

Overriding libraries

// Libraries is an array of the library data.
// Extension is 'core' or the module/theme that defined the libraries.
function hook_library_info_alter(&$libraries, $extension)

Migrations

Run an update migration.

// Remove the prepareUpdate() section if you just want a normal import.
// To rollback just change 'import' to 'rollback'.
$migration = \Drupal::service('plugin.manager.migration')->createInstance('machine_name');
$migration->getIdMap()->prepareUpdate();
$executable = new \Drupal\migrate_tools\MigrateExecutable($migration, new \Drupal\migrate\MigrateMessage());
$executable->import();

// MigrateExecutable takes an optional third argument where you can provide options including
// limit to limit the number of migrations to perform, and idlist to only migrate certain source
// IDs.
// Example: ['limit' => 10, 'idlist' => '1,2,3']

Interrupt a migration (stop it).

$migration = \Drupal::service('plugin.manager.migration')->createInstance('machine_name');
$migration->interruptMigration(\Drupal\migrate\Plugin\MigrationInterface::RESULT_STOPPED);

Set a migration status to Idle.

$migration = \Drupal::service('plugin.manager.migration')->createInstance('machine_name');
$migration->setStatus(\Drupal\migrate\Plugin\MigrationInterface::STATUS_IDLE);

Run a migration on page load (w/?start-migration appended) for xdebug walkthrough.

use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessage;

/**
 * Implements hook_preprocess_page().
 */
function example_module_preprocess_page(&$vars) {
  if ($qs = \Drupal::requestStack()->getCurrentRequest()->getQueryString()) {
   if (strpos($qs, 'start-migration') !== FALSE) {
      $migration_id = 'your_migration_id';
      $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);
      $executable = new MigrateExecutable($migration, new MigrateMessage());
      $executable->import();
    }
  }
}

Miscellaneous

Get the node from the current path.

$node = \Drupal::routeMatch()->getParameter('node');

Get current path.

$path = \Drupal::service('path.current')->getPath();

Get path arguments (from path above).

$path_args = explode('/', $path);

Get the current route.

$route_name = \Drupal::service('current_route_match')->getRouteName();

Get the query parameter from a GET request.

$name = \Drupal::request()->query->get('name');

Get the parameter from a POST request.

$name = \Drupal::request()->request->get('name');

Get the host (ex: www.google.com).

$host = \Drupal::request()->getHost();

Redirect.

use Symfony\Component\HttpFoundation\RedirectResponse;
new RedirectResponse(\Drupal::url($route_name));

Add t() to classes (services, controllers, etc)

use Drupal\Core\StringTranslation\StringTranslationTrait;
class MyClass {
  use StringTranslationTrait;
}

Modules

Installing and uninstalling modules.

\Drupal::service('module_installer')->install(['media']);
\Drupal::service('module_installer')->uninstall(['media']);

Rendering

Render an entity.

$nid = 1;
$entity_type = 'node';
$view_mode = 'teaser';
$view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity_type);
$storage = \Drupal::entityTypeManager()->getStorage($entity_type);
$node = $storage->load($nid);
$build = $view_builder->view($node, $view_mode);
$output = render($build);

Render a field.

$view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$storage = \Drupal::entityTypeManager()->getStorage('node');
$nid = 1;
$node = $storage->load($nid);
$view = $view_builder->viewField($node->get('body'), [
  'type' => 'string', // string, entity_reference_label
  'label' => 'hidden',
  'settings' => ['link' => FALSE],
]);
$output = render($view);

Search

Trigger select entities to be re-indexed through the Search API.

// This is for Title Record entities, but any entity will do.
use Drupal\search_api\Plugin\search_api\datasource\ContentEntity;
use Drupal\omega_hub\Entity\TitleRecord;
$entity_ids = [507863, 509240, 513703, 515100, 536124, 537058, 541569];
$combine_id = function ($entity_id) {
  return $entity_id . ':und';
};
$update_ids = array_map($combine_id, $entity_ids);
$entity = TitleRecord::load(507863);
$indexes = ContentEntity::getIndexesForEntity($entity);
foreach ($indexes as $index) {
  $index->trackItemsUpdated('entity:title_record', $update_ids);
}

Users

Load a user.

$node = \Drupal::entityTypeManager()->getStorage('user')->load(23);

Get current user.

$account = \Drupal::currentUser();

Get current user ID.

$account = \Drupal::currentUser()->id();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment