• Development

    Faster Debugging with Lando and xdebug

    I’ve been struggling with the speed (or lack thereof) of Lando for Drupal sites. I have suspected xdebug was part of the issue. Sure enough, disabling xdebug speeds up the lando instance considerably. Re-enabling it slows it right back down again. I use xdebug often, so having to lando rebuild  to turn xdebug on and off is not an option. I wondered if there’s a way to leave the extension enabled but only use it when needed.

    While researching config directives like xdebug.remote_enable  and xdebug.remote_autostart, I came across this issue thread on the github Lando project: Allow faster xdebug on/off toggling

    The title sounds promising, right?

  • Development

    Quickly Protecting a Few Nodes from Deletion in Drupal 8

    I’m working on a Drupal 8 site with some critical pages for which we do not want to allow deletion. The homepage, for example, is a basic page; we do not want to allow anyone (even UID #1) to delete this page. If there comes a time where UID #1 decides they need to, they’ll have to update this simple code to support that. We need not make it any more complicated than that for this particular project.

    Here’s a solution that:

    • shows nothing but an error on the “Delete” form for specific nodes (works for all users)
    • prevents deletion by any means (works for all users except UID #1)
      • why except UID #1? because hook_node_access doesn’t run for this user
  • Development

    Testing Tokens with Entity Ref Traversal via Drush

    I am working on a project that has some complicated depth. I needed a way to quickly test token replacement. It’s pretty simple when you understand a few things.

    Example Architecture

    Here’s the Drupal architecture for this example:

    • Discussion Group (content type)
      • Title
      • Intro
      • Body
      • “Associated Experts” paragraph field (allows one “Associated Experts” paragraph item)
    • Associated Experts (paragraph type, used by many content types like Discussion Group above)
      • Heading
      • Intro
      • Experts (allows unlimited number of “Expert” nodes)
    • Expert (content type)
      • Title
      • Photo
  • Development

    Rendering a Drupal 8 Link with Anchor and Destination

    I’m working on a site that contains several complicated views (many exposed filters). The views render entities using a couple different view modes. These view modes use Display Suite. Within these view modes I’ve leveraged DS custom fields for several needs.
    I needed to render a node “Edit” link within some of these view modes. The user would click the edit link, edit the node, then click “Save”. The system would then bring the user to the exact position of the page they were on before, filters and settings intact.
    This type of solution would work without Display Suite (leveraging other methods). You’re getting a DS-based example because that’s what the site called for.
    In my particular case I needed to separate the anchor from the edit link. If you’re okay having them in the same place you could skip Step 1 and just include the anchor within the markup for the edit link.
  • Development

    Getting a Field from an Entity in Drupal 8

     

  • Development

    Display-only Pseudo Fields in Drupal 8

    In the past I’ve been happy to rely on Display Suite to create what I call “Frontend Only” (DSField) fields (which I created via php). These fields appeared in the Manage Displays screens so that site admins can easily drag them around in the display as needed. As it turns out, you can achieve nearly the same result using a few built-in hooks in Drupal 8. The Display Suite DSField plugin has a few handy helpers like the ability to only show the field on specific display mode forms (e.g., show the field on Full content but not on Teaser). You can still control whether or not the display-only field renders if you use the core hooks, so we’ll be okay.

    [UPDATE January 30, 2020] After some discussions with a colleague I decided the world needs a Plugin-based approach to the solution below. We talked through how it’d work before going about our day. After writing the info file, .module file, and prepping the folder structure I realized I never checked to see if this already existed.

    I was pleasantly surprised to see that Sutharsan had already created a module that fits the bill! Extra Field is nearly identical in structure and implementation as what I’d planned to build. I just finished writing my first ExtraField\Display plugin and it works beautifully! I will leave my post below in tact, but I highly recommend stopping here and simply using Extra Field. Note that the README.txt file is worth reading, and there is an extra_field_example sub-module that explains things quite well.

  • Uncategorized

    Twig Caching Issues in Acquia Cloud Enterprise

    I’ve recently run into an issue where my site (on Acquia Cloud Enterprise) has node displays that were flip-flopping between an older version of a Twig template file, and the most recent version. I tried all combinations of drush cr, varnish cache clearing, and clearing the cache through the Drupal UI.

    After reading through No reliable method exists for clearing the Twig cache, I landed on this page at Acquia: https://support.acquia.com/hc/en-us/articles/360005167754-Drupal-8-Twig-cache

    I SSH’d into the production server I always SSH into, and I ran the command as shown. I did this repeatedly. I did a drush cr after. I did a drush cr before. Nothing was working. My pages were showing up with the old template, or the new template, and it seemed to be at random.

    Ultimately I re-read the documentation page, more thoroughly this time, and discovered this: “connect to each web server instance and run a command like this…

    Ahah! EACH web server.

    So, I logged into the Acquia Cloud interface, found the other production server’s connection string (myuser@someserver.prod.hosting.acquia.com), connected, and ran the same command. After another drush cr all of the pages were using the new template.

    That’ll teach me to jump straight to executing commands without reading the instructions carefully.

  • Development

    Migrating Into Existing Nodes in Drupal 8, Including Rollback Missing from Source

    Please read this entire post (including the disclaimer at the bottom) before you put any of it to use.

    The site I’m basing this off had an existing set of nodes and a new migration that had the same nodes (and many more) in the data source. I wanted to map the existing nodes to their migration-based counterparts and treat every node as if it originated from the migration.

    As of today, using a few patches makes it easy (thanks contributors!) to rollback items that no longer exist in a D8 migration’s source data. See Migrate support for deleting items no longer in the incoming data and Implement rollback of items no longer in source data

    With these patches you can import and rollback in two commands:

    What if the data that you’re migrating (and rolling back if removed) already existed in Drupal before you started using the migration? If you attempt to migrate content, then rollback removed items, you will find that the items that no longer exist in the source will not be deleted if they existed before the migration.

    First, I should describe how I’m pulling data into existing nodes.

    This is as simple as populating the node ID in the process section of your migration YML, like this:

  • Development

    Combining Steps in Behat for Drupal

    Lately I have found myself repeating several lines of behat steps over and over again. Here is a sample of the behat code I use to choose a specific checkbox from an entity browser popup:

    There are a few steps in here that are custom, but explaining them would be beyond the scope of this post; just assume they do what they describe (switching focus to an iframe, and clicking a checkbox).

    The issue I was having is that every time I wanted to do that one action (pick an image from an entity browser) I was repeating all 8 lines of code.

    I began looking for ways of making this set of steps repeatable. After some failed attempts at extending MinkContext and MinkAwareContext I came across scenario hooks via this StackOverflow post. I discovered the @BeforeScenario, which is executed before every scenario in each feature (where it’s used). Using this hook to access contexts from other contexts was documented on behat.org but required a few tweaks for the Drupal implementation. Here is what I ended up doing (based on the default FeatureContext.php you get when you install behat for the project:

  • Development

    Adding Level Number Class to Menu Items in Drupal 8

    This is a quick post showing how to add level classes to menu items in Drupal 8.

    Here’s the result, showing the additional menu--level-N  and menu-item--level-N  classes:

    Result

    Step 1: Create a New Twig template File

    Determine which Twig template you need to override. I recommend reading the official docs on this. In my case, for a menu called infofor, I copied docroot/core/themes/classy/templates/navigation/menu.html.twig to docroot/themes/custom/mytheme/templates/navigation/menu--infofor.html.twig .

    Step 2: Update the Twig Code