Useful Drupal modules

Click on the module name for notes, comments, patches.
Recommendations (for and against) are my personal opinion only and may be out of date. Feel free to email with corrections/suggestions.

Why doesn't the table mention Drupal 9 or 10?

1. Nowadays, I try and use Drupal as little as possible. Specifically I do not recommend it for a new website. I'd also strongly caution you against choosing Drupal if you're at the beginning of your career and trying to learn web development (front / back / full stack) or just want to manage/maintain a website. More details why by email on request.

2. By February 2022 I'd updated all the sites I look after to Drupal 9 (experience: mixed). As of March 2023, a year later, none of them were fully ready for Drupal 10 (waiting on support for various modules). By 13 Nov 2023 (a week or two after D9 lost support) I had updated a couple of them.

Q: What's the Drupal 9 to 10 upgrade experience like? A: it's what I'd describe as "just bearable", slightly better than D8 to D9, though with plenty of things to still trip you up. There is still deprecated code that needs fixing in D10 modules, and policy changes mean odd things will break (be prepared to turn off Aggregate CSS/JS files if your themes stop working, and note that Drush launcher doesn't work with Drush 12...)

Admittedly the upgrade_status module is the best solution they could have come up with for tracking compatibility. Also watch out for a nasty session headers bug with redirect_after_login.

What about sites still running Drupal 7? In short I still recommend leaving them on Drupal 7 or moving to another platform entirely. My prediction was that Drupal will extend D7 support year after year (note that drupal.org itself is still running D7). It's now been confirmed as 5 Jan 2025. There will have to be some sort of third-party long term support, because of the sheer volume of sites that are not being upgraded.

Your decision is really what specifically you think you will gain from Drupal 8/9/10 - often the answer will be not enough, and one of the main hassles - apart from converting each content type one at a time, and setting up a new theme, will be recreating all your views by hand, as views can't be automatically upgraded.

(134 modules in list)
Module name or machine name
Any text in the notes
Name D8 Sort ascending Personally Tested Last Updated
Content access (content_access)

d.o. page

"Essential"

Set permissions by content type (with the option of overriding node by node)

Rules (rules)

d.o. page

Patch needed (the pages and roles tabs are missing on block editing form otherwise):

https://www.drupal.org/project/rules/issues/3160347

HMS Field (hms_field)

d.o. page

Hours/minutes/seconds field type (formats: h:mm, h:mm:ss, m:ss, h, m or s). Drupal 8 in beta.

Two Factor Authentication (tfa)

d.o. page

"Essential"

install tfa and ga_login (TFA is just a framework, it doesn't come with it's own login plugins.)

Use this patch I wrote - it adds display of validation skip times and an admin reset button for users who are got locked out.

My installation instructions:

Next you need to generate an encryption profile.
First you need to generate a key - key type needs to be Encryption (not Authentication).
A 128bit key = 128/8 bytes = 16 characters - so generate a random 16 character string.

Set key provider to File rather than Configuration, this means the key won't end up in your version control.

Tick the 'strip trailing line breaks' box to avoid the "The selected key size does not match the actual size of the key." error

Key path should be relative to Drupal so the config will work on multiple sites
e.g. if you have created a file called /app/tfa.key on a lando container, set the key path to ../tfa.key
I'm actually creating mine in a keys directory.

Remember to save the key somewhere in your password manager, or your ansible variables, in case you lose the files later.
Remember to add /keys to your .gitignore file, so it won't get stored in version control.
Remember to copy it manually onto your production server.

In the TFA settings (/admin/config/people/tfa) you probably want to increase the number of times a user can skip validation.

Note that TFA has a separate 'Tfa user login' block (replacing the ordinary 'User login') 

AJAX Comments (ajax_comments)

d.o. page

Not recommended

Not very actively maintained and it can be quite buggy.

Needs this patch:

Reply button can be pressed multiple times, resulting in multiple comment forms

I abandoned it for a project because the admin XHR response when you submit comments sends back comments you've already filtered out (I had written code to restrict visibility of certain comments).   Also had a problem where the initial comment form was left in place rather than being replaced, so you ended up with duplicates.

Automatic User Names (auto_username)

d.o. page

"Essential"

Removes the 'Username' field from registration form.  Use in conjunction with a module that allows users to login with their email address.
Generates a username in the background (Drupal still requires one) - adds 'Patterns' tab to Account settings for configuring the name.

Patches:

 

Feeds (feeds)

d.o. page

"Essential"

As of Sep 2018, up to alpha3 in D8 (but not personally tested).

Lets you import CSV/RSS etc.  files and various other formats and map them to nodes/user/taxonomy terms, either one-off or periodically.

Layout builder (layout_builder)

d.o. page

Benefits:

  • Build layouts using GUI - arrange fields in columns/blocks (or add a block, or menu, or tag cloud, user info etc.) 
  • Easily override layout of individual nodes without needing to clone/design/apply a template (and reset to default easily afterwards)


Status:

Nov 2018: core, experimental in 8.6.x
May 1 2019: due for stable release in 8.7.0

Issue queue

Installation:

  • Enable the layout_builder module (which also enables layout_discovery)
  • Clear cache.
  • Activation:  Content type -> Manage Display -> scroll down to Layout Options - tick Use Layout builder

By turning on Layout Builder, you switch from the standard Manage Display view (field, label, format/widget settings) and the layout builder GUI.

Resources:

Compatibility:

  • A migration path is being built for Panels / Panelizer.
  • Undecided (Nov 2018) how Layout builder will work in conjunction with Paragraphs

 

Login email or username (login_emailusername)

d.o. page

"Essential"

Self-explanatory.

Alexa (alexa)

d.o. page

Integrates with Amazon Echo. Allows Drupal to respond to Alexa skills requests.  See Dries' blog with video demo.

Field collection (field_collection)

d.o. page

Allows you to group a set of fields together.  In active development for D8 but still a lot of open bugs at time of writing - project page says it will likely be replaced by Paragraphs.

Configuration Read-only (config_readonly)

d.o. page

Lock all configuration changes via the admin UI - e.g. if you need to lockdown a production environment.

config_readonly now has a whitelist, added via an array in settings.php.

Password policy (password_policy)

d.o. page

Not recommended

There are still quite a few bugs open. I dropped this for a project, partly because it adds a load of clutter with the 'resets' and reset dates.
The minimum password policy in Drupal is already 12 characters anyway (and one issue is changing the minimum length doesn't change the help text.) 
You need to enable the submodules to use the various constraints:
drush pm:list | grep 'password_policy_'
Admin users see password policy stuff on the user profile page.
You need to set password reset days to 0 if you don't want to enforce a reset policy.
Policies can be applied by role.  
You get a generic warning about the password 'not matching the password policy'. Suggest using string overrides to change the "To change the current user password, enter the new password in both fields." message users see.
Instructions: add/edit the policy, click next, choose constraint then click 'Configure constraint settings' otherwise you won't be able to change anything.
It also lets you do a forced reset by role.

Automatic Entity Label (auto_entitylabel)

d.o. page

"Essential"

Hide entity labels (i.e. titles) or auto-generate them. (Works for anything - nodes, comments, taxonomies).

Field Formatter Condition (fico)

d.o. page

(based on ffc which hasn't been ported to D8).  

Allows you to configure field display based on value.  Adds a 'Conditions' pane to the cog in Manager Display of all entities (so content types but also comment types, e.g. if you have comments with multiple fields)

Requires Display Suite (ds)

Note: if you wanted to hide say a checkbox when it's value is false - you can do in it core with Manage Display - turn the label off then set (via cog wheel) the output format to Custom, and you can enter a value for true and leave false blank - exactly the same widget for boolean values you use when setting the output of a field in a view.

Webform Views Integration (webform_views)

d.o. page

"Essential"

This module lets you add fields from submissions to view, and sort/filter the view on them, in the same way you would standard fields from the Field API.

It's still alpha and not as polished/robust as the webform module itself - but it's certainly OK to use in production provided you test things first - check every combination of exposed filters works, and double check you aren't seeing duplicate rows (right now I've locked it to a recent commit on the dev-5.x branch, which doesn't need any patches).

Menu position (menu_position)

d.o. page

"Essential"

Assign various pages (by content type, URL, role etc.) to certain menu entries - so the 'active' status of the menu is set correctly (i.e. they appear within the sections you want).

- patch: Add enabled checkbox to edit form + enable new rules by default

As of alpha2 - views with contextual filters (e.g. myview/somefilter) will work correctly when a rule is added with pages / pages with wildcards specified.

 

Conditional Fields (conditional_fields)

d.o. page

Adds a 'Manage dependencies' tab to the admin page for content types.

This lets you set a 'target field' whose visibility is set according to a 'control field' and whether the latter is full/empty/checked/unchecked/has a specific value.

Another useful feature is you can prefill/pre-tick etc. the target field (including with a custom text value, for example).

To detect quickly if it's in use anywhere (I needed to do this before being sure I could uninstall the module on a site), export your site config and grep the /config/sync directory for 'conditional_fields' - it's stored in the 'third_party_settings' key in core.entity_form_display.node.[content type].default.yml

Pathologic (pathologic)

d.o. page

There's a D8 version but I've only tested D7.

It's a filter that fixes incorrect paths in your content - e.g. if you have content with an old domain or IP address specified, you can redirect it.

Node access user reference (nodeaccess_userreference)

d.o. page

"Essential"

Allows you to use an entity reference field on a node to allow (or deny) access to that node to the users you have selected.  Extremely useful for giving selected people access.

This isn't available in D8 or above (though it ought to be) - there's a note in the issue queue about it.  #2655426

Node Export (node_export)

d.o. page

Tto actually export node content. An 8.x version has begun development:

composer require 'drupal/node_export:1.x-dev'

Mydropwizard (mydropwizard)

d.o. page

"Essential"

If you have a Drupal 6 site, this modifies your Available Updates page (/admin/reports/updates) with direct download and release note links to all the D6 LTS (Drupal 6 Long Term Support) releases. 

Restrict Login or Role Access by IP Address (restrict_by_ip)

d.o. page

Can specify single IP address or ranges. Two modes: restrict login, so they can only login from certain IPs, and restrict role, so they can login from anywhere but only access a role's permissions from the defined IPs. There's a D8 dev branch, last updated June 2016.

Views PHP (views_php)

d.o. page

Allows you to insert a Global PHP field in a view in D7, so you can have conditionals etc.

Note there's a bug in 7.x-1.1 (Jan 2022) - you need this patch.

(Not available in D8, you should use Twig instead).

Node Page Disable (node_page_disable)

d.o. page

"Essential"

Adds an checkbox labelled 'Retain /node as an active url?' to /admin/config/system/site-information

This lets you disable the /node page which would otherwise list all published content.

Note it doesn't let you individual disable /node/xxx access by content type - see restrict_node_page_view or rabbit_hole for that.

This is for D7 only - in D8 you go to /admin/structure/views and disable /node there.

Resave nodes (resave_nodes)

d.o. page

"Essential"

If you want to manually refresh a series of nodes.
Mainly useful if you have a rule or a hook that relies on a node being saved, to update a computed field etc.

You can choose the node type.

Autofocus (focus)

d.o. page

Autofocuses the first field of form (forms can be specified).  No sign of a D8 port.

Table trash (table_trash)

d.o. page

Add extra tables JS support for views (and many other pages) - e.g. search box, dynamic column sorting, rearranging columns, exporting to clipboard etc.

If you get "TypeError: tables.DataTable is not a function" when using datatables module, first, try going to /admin/config/content/table_trash/global_settings and saving the existing settings.

Administration Views (admin_views)

d.o. page

"Essential"

D7 only (as this is in D8 core as standard).

Converts /admin/people into a fully-fledged configurable view (i.e. fields, filters, exposed filters, header/footer, pagination settings etc.) 

(Dependency: views_bulk_operations)

Autosave (autosave)

d.o. page

Saves snapshot of content type form using AJAX.  Content types and save frequency can be configured.  No sign of a D8 port yet.

Automatic Nodetitles (auto_nodetitle)

d.o. page

You can hide a node's title field (for reference, every node has to have a title) and generate it automatically, similar to pathauto.  No-one's porting this to D8 yet.

View Migration (view_migration)

d.o. page

Not recommended

Migrate views from D7 to D8.
Once installed on D7 - you need to go to /admin/config/view-migration 
It outputs multiple YML files and you're specifying a directory to put them in, which you need to create first.

My experience of the YAML output has been:

- incomplete (e.g. multiple missing displays in a complex view, views without a machine name)
- invalid UTF8 due to the next and previous arrows in pager.options.tags being encoded wrong
- the dependencies section at the top of the file not being set out correctly

It doesn't look like there's much current development activity (likewise migrate_views, which is the other plugin people usually mention).

Flood Control (flood_control)

d.o. page

Protect against brute-force login attacks. Unclear what's happening with porting of this.

Views Aggregator Plus (views_aggregator)

d.o. page

Provides extra options for aggregating data in tables - e.g. grouping sets of rows together and summing the values of particular fields.

Has a hook - hook_views_aggregation_functions_info() - which lets you add your own options to the table aggregation settings - e.g.  supposing you have a limit for something (number of tickets, nights of accommodation) and want to decrement it - you can write a method to sum the matching rows and then do a calculation on the total.

Also supports 'add column function' - adds a grand total (or other summary field) at the very bottom of the table.

Caution - this module breaks hook_views_pre_render() - you can write your own pre_render method to remove or shuffle entire rows, but any chances to values will be overwritten (discovered this by looking through the source and looking for the use of that hook).  The workaround is to try and do what you need to by using hook_views_aggregation_functions_info() instead.