Drupal

Drupal Composer scaffold file prepending and appending

The file-mapping configuration setting consists of a map from the destination path of the file to scaffold to a set of properties that control how the file should be scaffolded.

The available properties are as follows:

  • mode: One of “replace”, “append” or “skip”.
  • path: The path to the source file to write over the destination file.
  • prepend: The path to the source file to prepend to the destination file, which must always be a scaffold file provided by some other project.
  • append: Like prepend, but appends content rather than prepends.
  • overwrite: If false, prevents a replace from happening if the destination already exists.

The mode may be inferred from the other properties. If the mode is not specified, then the following defaults will be supplied:

  • replace: Selected if a path property is present, or if the entry’s value is a string rather than a property set.
  • append: Selected if a prepend or append property is present.
  • skip: Selected if the entry’s value is a boolean false.

Examples:

"file-mapping": {
  "[web-root]/sites/default/default.settings.php": {
    "mode": "replace",
    "path": "assets/sites/default/default.settings.php",
    "overwrite": true
  },
  "[web-root]/sites/default/settings.php": {
    "mode": "replace",
    "path": "assets/sites/default/settings.php",
    "overwrite": false
  },
  "[web-root]/robots.txt": {
    "mode": "append",
    "prepend": "assets/robots-prequel.txt",
    "append": "assets/robots-append.txt"
  },
  "[web-root]/.htaccess": {
    "mode": "skip",
  }
}

How to install a Drupal.org sandbox module using Composer

What do you do if you want to use a Drupal.org sandbox project with Composer? You can’t just add it in your "require" section, as it won’t be available as a package name. Turns out you just have to define the repository in your composer.json like so:

Code language: JavaScript

"repositories": {
  "drupal/image_field_caption": {
    "type": "package",
    "package": {
      "name": "drupal/image_field_caption",
      "type": "drupal-module",
      "version": "1.x-dev",
      "source": {
        "url": "https://git.drupalcode.org/sandbox/spoit-2806183.git",
        "type": "git",
        "reference": "8.x-1.x"
      }
    }
  }
},
"require": {
  // ...
  "drupal/image_field_caption": "1.x-dev",
  // ...
},
// ...

Drupal 8, behaviors, and jQuery Once

When porting some front-end code from Drupal 7 to Drupal 8, I ran into an unexpected change in the use of jQuery.once(). In Drupal 7, you’d do this in a behavior:

Code language: JavaScript

Drupal.behaviors.exampleBehavior = {
  attach: function(context, settings) {
    $('.example', context).once('example-behavior', function() {
      // Do stuff.
    });
  },
  detach: function(context, settings, trigger) {
    $('.example', context).removeOnce('example-behavior', function() {
      // Undo stuff.
    });
  }
};

In Drupal 8, however, you can’t pass in a function to jQuery.once(), as the API for that jQuery plugin has changed. It now acts like jQuery.filter(), in that it filters out any elements that have already been processed so they aren’t processed more than once, and returns a jQuery collection. So, in Drupal 8, the example would be:

Code language: JavaScript

Drupal.behaviors.exampleBehavior = {
  attach: function(context, settings) {
    $('.example', context).once('example-behavior').each(function() {
      // Do stuff.
    });
  },
  detach: function(context, settings, trigger) {
    $('.example', context).removeOnce('example-behavior').each(function() {
      // Undo stuff.
    });
  }
};

Drupal 8 contextual links are locally cached in sessionStorage

I ran into a seriously confusing issue with a project that I’m learning the internals of Drupal 8 for: custom contextual links were not reliably appearing or even disappearing after removing them from code, and the only thing that seemed to work was to fully uninstall and reinstall the custom module, which was far from ideal. Turns out that Drupal caches contextual link markup in sessionStorage, which is why clearing Drupal’s own cache had no effect like you would expect. The easiest way of handling this is running window.sessionStorage.clear(); in your browser’s developer console. Alternate solutions include opening the page in a new tab will cause a re-download of the contextual links (due to how sessionStorage works), or opening up your browser’s developer tools and deleting the sessionStorage entries for the entities or other identifiers - for a block it would be Drupal.contextual.block.*, while for a node it would be Drupal.contextual.node.*.