Drupal 8 Developer's Cookbook: Other Tips and Tricks

Allowing Data URLs in Block / Dynamic Page Output

Even though data URLs are not inherently dangerous and actually quite useful, they were not whitelisted in the XSS (Cross Site Scripting) filter system.  However, you can whitelist them yourself with the following three lines  - just add them somewhere before you return a render array that contains links with data URLs:

$allowedProtocols = \Drupal\Component\Utility\URLHelper::getAllowedProtocols();
$allowedProtocols[] = 'data';

Why would you use a data URL? They're perfect for displaying images contained in data that you've already pulled in from a remote data source.

Quick Way of Adding Taxonomy Based Node Access Control

The following is a quick and dirty way to enable term based access control.  It doesn't provide a pretty GUI for adding / removing / managing the term to user role mappings, but those probably won't need to be changed very frequently.  For managing access control on a node, you just use the built-in interface for adding one of your access control "terms" to the node, after which the rules you set up in the code below will take effect.


  1. Create a taxonomy for holding access control identifiers, add at least one term, and then add a taxonomy reference field to your node content type(s) that references this taxonomy.

  2. Create a user role for each access control group and add people who should have access.

  3. Finally, add the following to a module that you enable on the site, and any nodes that have the specified term mapped to them will only be accessible to people in the indicated user role.

use Drupal\Core\Access\AccessResult;
use Drupal\node\NodeInterface;

function mymodule_node_access(NodeInterface $node, $op, $account) {

  $map = array(  #--maps taxonomy ID to a user role ID

  /* The following limits the check to the content types indicated ('page' is
   * "Basic Page) */
  if ($node->bundle() == 'page') {

    /* "field_access_group" is the machine name of your taxonomy reference
     *field */
    $termList = $node->field_access_group->getValue();

    foreach ($termList as $term) {
      if (isset($map[$term['target_id']])) {
        $roles = array_flip($account->getRoles());
        return AccessResult::allowedIf(isset($roles[$map[$term['target_id']]]));
        /* The above grants full access if user is in the mapped role.  Use the
        /* following line if you want to forbid all access (even viewing) to anyone
        /* who is *not* in the mapped role.  NOTE: None of these rules apply to
        /* administrators with the 'administer content' permission

        /* return AccessResult::forbiddenIf(!isset($roles[$map[$term['target_id']]]); */
        /* The following will cache the result to speed things up in the future
         *  - turn on only after you've fully debugged your code
         * ->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); */


  return AccessResult::neutral();


Even More Tips and Tricks

Visit the Georgia Tech Drupal Users Group Drupal 8 Guide for even more tips and tricks.