Moving a custom profile to its own repo

State can be weird in Drupal 8.

I recently experienced a situation where the project had a profile—let’s call it theprof—that got moved into its own repository, beefed up (various modules and themes moved to it, etc.), and included in the implementing project via `composer.json`.

We then ran into a weird problem: rebuilding the cache successfully found all of the enabled modules again, but the theme was no longer active. Not only was it inactive, but Drupal couldn’t even find it!

What in the world was going on?

It turns out that Drupal 8 discovers themes differently than modules. When discovering modules, it first actively discovers profiles and then passes a list of these to the class used for discovering “extensions” (a general term used to refer to both modules and themes).

However, when discovering themes, it simply delegates the job of finding profiles to Drupal itself. And Drupal, reasonably, retrieves the path to a profile it has seen before from the State subsystem (generally, the `key_value` table in the database).

Note: It retrieves the path to a profile “it has seen before” this way.

That means that when we moved theprof from profiles/theprof to profiles/contrib/theprof, Drupal still had its path set to the old path in the system.profile.files State key. The solution in the end was simple:

 * Clear profile path cache so that theme discovery works.
function mymodule_update_8004() {
  $state = Drupal::state();

  // Rebuild module and theme data.
  // @see drupal_flush_all_caches()
  $module_data = \Drupal::service('extension.list.module')->reset()->getList();
  /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
  $theme_handler = \Drupal::service('theme_handler');
  // In case the active theme gets requested later in the same request we need
  // to reset the theme manager.

Drupal 7: Watch for hyphens in CTools and Panels plugin names

I recently ran into an interesting problem with the way CTools plugin methods are discovered (namely, CTools content types, used by the Panels ecosystem) in Drupal 7.

The project I was working on had various content types named things like piwik-tracking-code (not the exact name, but good enough to illustrate the issue).

Panels looks for various methods, such as settings and render methods, by taking the machine name of the plugin (typically the filename) and adding suffixes to it—a lot like hooks, in fact.

You might be able to see where I’m going with this if you’re familiar with PHP. That’s right: piwik-tracking-code_render() is not a valid function name! Therefore, it fails.

There are a couple ways around this. With some of the plugin functions, you can specify the function names in the definition or in one of the functions. If you must hyphenate, you have to do this.

The other way, of course, is to simply use underscores. This is what I did and what I would recommend.

Workaround for ‘zR’ (expand all folds) not working in IdeaVim 0.58 in PhpStorm, IntelliJ IDEA, etc.

Just sharing my tweet on the blog as well:

The main point: put the following into your .ideavimrc, and reload with :source ~/.ideavimrc

map zR :action ExpandAllRegions<CR>:action ExpandAllRegions<CR>

It’s a wrap! Patreon pledges have been doubled and donated to the Drupal Association #DrupalCares (and FillPDF works with Drupal 9)

The total came out to $123.08 after Patreon fees. I doubled that to $246.16 and “topped it off” for a total of $623.08! That could become up to $1,869.24 matched.

Thanks, Patreon supporters!

  • Damien McKenna
  • Andreas Tasch
  • Michael Flipp
  • Jessica Cobb

I also ported FillPDF to Drupal 9 yesterday. I released 5.0.0-alpha1. There are many things to fix, and not all dependencies are ready yet, but it is a good start.

DONATION MADE. THANKS! Patreon pledge = 2x-6x donation to Drupal Association until April 29 #DrupalCares


As you might have seen me tweet, I’ve recently started Patreon and Ko-Fi pages. The goal of these is to let me spend more time working on open source (primarily, but not only, the FillPDF Drupal module and FillPDF LocalServer).

Not long after, Vanessa and Dries Buytaert, the founder of Drupal, announced his matching pledge, in which he would match up to $100,000 of individual memberships and donations.

Then Jeff Geerling pledged to donate $1 per like of his #DrupalCares video.

As if that wasn’t enough, a coalition of Drupal businesses also pledged to match the first $100,000 donated.


So, I’m joining the crowd:

If you become a member of my Patreon page (click here to go there), I will donate two times your April pledge to the Drupal Association. (For example, if you pledge $5, I will donate $10.)


If the #DrupalCares Match Challenge total is still under $100,000, Vanessa and Dries Buytaert and a coalition of Drupal businesses will each, in turn, match that, making it six times your pledge.


I will do this for the first $500 of supporters, for a total donation of $1,000 ($3,000 if fully matched).


I will also post and share a blog giving credit to all of the supporters.


There’s no obligation to remain a Patreon supporter, but if you use the FillPDF module or anything else I’ve contributed code to on Drupal.orgGitHub, or elsewhere, it will help me do more. I’m hoping some new supporters will remain supporters.



  • I’ll be making the donation on April 29.
  • My business, FillPDF Service, uses the FillPDF module, but it is not the only way to use the module, so the open source community still benefits from me working on it. It also makes use of open source itself. For example, I published the Commerce Recurring Metered Billing module as part of an upgrade I’m working on.

Fix for certbot-auto breaking on old systems

Some people might still be running servers with EOL (end-of-life) operating systems. certbot-auto recently broke Python compatibility with some of these in version 0.32.0.

The fix is straightforward: downgrade to 0.31.0.

This is how I did so:

# cd /opt/certbot
git fetch --tags
git checkout v0.31.0

I also edited my crontab. The certbot-auto entry now looks like this:

17 3 * * * PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games /opt/certbot/certbot-auto --no-self-upgrade renew --post-hook="service nginx reload" >> /var/log/le-renew.log

Notice the --no-self-upgrade option. This is important if you don’t want to run into the same issue in three months.

You may have to adapt these changes to your operating system, but it should resolve the issue and let you keep renewing your SSL certificates.

(I assume we all already know that we shouldn’t even be running such servers…but it happens. Some people also have commercial or enterprise support agreements.)


See for more.

PhpStorm how-to: Run PHP Code Beautifier on File Save (read the Twitter thread)

Hello from Drupal Mountain Camp 2019! I’m just pasting in a tweet here. Click to read the thread.

Call to undefined function cache_get() in Drupal 7? Check your settings.php.

Ran into this one today while setting up a local environment with DDEV:

PHP Fatal error:  Uncaught Error: Call to undefined function cache_get() in /var/www/html/includes/
 Stack trace:
 #0 /var/www/html/includes/ module_implements('system_theme_in...')
 #1 /var/www/html/modules/system/system.module(2511): module_invoke_all('system_theme_in...')
 #2 /var/www/html/includes/ _system_rebuild_theme_data()
 #3 /var/www/html/includes/ list_themes()
 #4 /var/www/html/includes/ _drupal_maintenance_theme()
 #5 /var/www/html/includes/ drupal_maintenance_theme()
 #6 /var/www/html/includes/ _drupal_log_error(Array, true)
 #7 [internal function]: _drupal_exception_handler(Object(Error))
 #8 {main}
 thrown in /var/www/html/includes/ on line 754
 Drush command terminated abnormally due to an unrecoverable error.

It’s not very obvious at all what’s going on here. Clearly, Drupal is somehow failing to load. I at first thought it was the database connection details not getting loaded properly and ensured that they were OK. But the error persisted.

“Strange,” I thought. “The DB connection info is definitely correct.” So I went back to, which had some up in search, again. Everyone hitting the error seemed to have syntax errors in their settings.php. I figured that, logically, I must too, and just not be seeing it.

Sure enough:


if ($file_exists($dir . '/settings.local.php')) {
  require_once($dir . '/settings.local.php');

❝I think you’re looking for the file_exists() function there, buddy.❞


So I removed the extraneous $ and, sure enough, the site started working.

This has been another episode of the ongoing worldwide series Is It Plugged In?

apt-add-repository failing in Ubuntu 14.04 because of

Ran into an interesting one today:

# sudo add-apt-repository ppa:ondrej/apache2


Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmpnv_gva8h/secring.gpg' created
gpg: keyring `/tmp/tmpnv_gva8h/pubring.gpg' created
gpg: requesting key E5267A6C from hkp server
gpg: /tmp/tmpnv_gva8h/trustdb.gpg: trustdb created
gpg: key E5267A6C: public key "Launchpad PPA for Ond\xc5\x99ej Sur�" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.4/", line 920, in _bootstrap_inner
File "/usr/lib/python3.4/", line 868, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3/dist-packages/softwareproperties/", line 687, in addkey_func
File "/usr/lib/python3/dist-packages/softwareproperties/", line 370, in add_key
return apsk.add_ppa_signing_key()
File "/usr/lib/python3/dist-packages/softwareproperties/", line 261, in add_ppa_signing_key
tmp_export_keyring, signing_key_fingerprint, tmp_keyring_dir):
File "/usr/lib/python3/dist-packages/softwareproperties/", line 210, in _verify_fingerprint
got_fingerprints = self._get_fingerprints(keyring, keyring_dir)
File "/usr/lib/python3/dist-packages/softwareproperties/", line 202, in _get_fingerprints
output = subprocess.check_output(cmd, universal_newlines=True)
File "/usr/lib/python3.4/", line 609, in check_output
output, unused_err = process.communicate(inputdata, timeout=timeout)
File "/usr/lib/python3.4/", line 947, in communicate
stdout = _eintr_retry_call(
File "/usr/lib/python3.4/", line 491, in _eintr_retry_call
return func(*args)
File "/usr/lib/python3.4/encodings/", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 92: ordinal not in range(128)

Long story short, turns out it was due to my locale settings not being configured properly.

I applied the first suggestion of regenerating locales, and then the second one of setting default locales in /etc/default/locale, closing the SSH session, and opening it again. That fixed things.