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

Update: https://wizone.solutions/2020/04/29/its-a-wrap-patreon-pledges-have-been-doubled-and-donated-to-the-drupal-association-drupalcares-and-fillpdf-works-with-drupal-9/

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.

 

Notes:

  • 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 https://community.letsencrypt.org/t/python-error-when-running-certbot-auto/88399 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/module.inc:754
 Stack trace:
 #0 /var/www/html/includes/module.inc(954): 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/theme.inc(798): _system_rebuild_theme_data()
 #3 /var/www/html/includes/theme.maintenance.inc(57): list_themes()
 #4 /var/www/html/includes/bootstrap.inc(2922): _drupal_maintenance_theme()
 #5 /var/www/html/includes/errors.inc(179): drupal_maintenance_theme()
 #6 /var/www/html/includes/bootstrap.inc(2634): _drupal_log_error(Array, true)
 #7 [internal function]: _drupal_exception_handler(Object(Error))
 #8 {main}
 thrown in /var/www/html/includes/module.inc 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 https://www.drupal.org/forum/support/post-installation/2016-06-23/fatal-error-call-to-undefined-function-cache_get, 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 threading.py

Ran into an interesting one today:

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

[omitted]

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 keyserver.ubuntu.com
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/threading.py", line 920, in _bootstrap_inner
self.run()
File "/usr/lib/python3.4/threading.py", line 868, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py", line 687, in addkey_func
func(**kwargs)
File "/usr/lib/python3/dist-packages/softwareproperties/ppa.py", line 370, in add_key
return apsk.add_ppa_signing_key()
File "/usr/lib/python3/dist-packages/softwareproperties/ppa.py", line 261, in add_ppa_signing_key
tmp_export_keyring, signing_key_fingerprint, tmp_keyring_dir):
File "/usr/lib/python3/dist-packages/softwareproperties/ppa.py", line 210, in _verify_fingerprint
got_fingerprints = self._get_fingerprints(keyring, keyring_dir)
File "/usr/lib/python3/dist-packages/softwareproperties/ppa.py", line 202, in _get_fingerprints
output = subprocess.check_output(cmd, universal_newlines=True)
File "/usr/lib/python3.4/subprocess.py", line 609, in check_output
output, unused_err = process.communicate(inputdata, timeout=timeout)
File "/usr/lib/python3.4/subprocess.py", line 947, in communicate
stdout = _eintr_retry_call(self.stdout.read)
File "/usr/lib/python3.4/subprocess.py", line 491, in _eintr_retry_call
return func(*args)
File "/usr/lib/python3.4/encodings/ascii.py", 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.

Sign up for the FillPDF API private beta

I wanted to echo the blog post from FillPDF Service here. I’m working on a brand new version that is going to be way easier to use, and won’t be de-facto limited to use via the Drupal module. I’m starting a private beta test soon and opening up an early version to testers.

Sign up for the private beta.

It’s going to (finally) be a real REST API! Use vanilla PHP, Python, Elixir, whatever, and fill in PDFs without having to upload them to a server first. Most similar services either require that you upload your PDF template in advance or are hard to use. FillPDF Service doesn’t need that, and it won’t begin to. I may add similar features later on, but it will be on top of what’s already there.

I’m very excited about what’s to come. It will be a big change for FillPDF Service.

Anyway, beta testers will get free usage up to a certain point (most likely equivalent to the Clipboard plan, 600 merges) and can pay for more after that. The existing flexible billing features, like flexible overages, will come later. The beta is basically the API without the billing system set up. I’ll be setting that up while people beta test.

Sign up for the private beta.

Hello from WordCamp Vienna, and ddev in fish

I’m…kind of late mentioning that I’m at WordCamp Vienna. The day of sessions was fun and the people were great.

I’m at the Contributor Day now setting up my site in ddev.  I use the Fish Shell, so sometimes I have to run commands a bit differently.

After I imported my database, ddev reminded me to properly search-replace the WordPress URL, as one does. It told me:

WordPress sites require a search/replace of the database when the URL is changed. You can run “ddev exec ‘wp search-replace [http://www.myproductionsite.example] http://wizonesolutions.com.ddev.local'” to update the URLs across your database. For more information, see http://wp-cli.org/commands/search-replace/

However, I got errors when trying to do that:

Failed to execute command [wp search-replace http://local.wizonesolutions.com http://wizonesolutions.com.ddev.local]: Failed to run docker-compose [-f /Users/kevin/vhosts/ws/wizonesolutions.com/.ddev/docker-compose.yaml exec -T web wp search-replace http://local.wizonesolutions.com http://wizonesolutions.com.ddev.local], err='exit status 126', stdout='OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"wp search-replace http://local.wizonesolutions.com http://wizonesolutions.com.ddev.local\": stat wp search-replace http://local.wizonesolutions.com http://wizonesolutions.com.ddev.local: no such file or directory": unknown
', stderr=''

This was weird. I could see that it was misinterpreting my command and trying to use it as a working directory or something. That made sense.

I started to think: is Fish processing my command inside the single quotes before it sends to ddev, maybe? I’m not sure if that was the exact cause, but it lead me to running the command this way:

ddev exec ''wp search-replace http://local.wizonesolutions.com http://wizonesolutions.com.ddev.local''

It worked after that!

How to fix nokogiri errors caused by Vagrant 2.0.3 plugins

The short version: vagrant plugin expunge --reinstall

The long version:

Vagrant 2.0.3 seems to have changed something from 2.0.2 in terms of its embedded version of nokogiri. This causes errors when running commands such as vagrant status.

Here’s an example of the kind of error you may see:

/opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': incompatible library version - /Users/kevin/.vagrant.d/gems/2.4.3/gems/nokogiri-1.8.2/lib/nokogiri/nokogiri.bundle (LoadError)
from /opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/nokogiri-1.8.2/lib/nokogiri.rb:32:in `rescue in <top (required)>'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/nokogiri-1.8.2/lib/nokogiri.rb:28:in `<top (required)>'
from /opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-parallels-1.7.8/lib/vagrant-parallels/driver/base.rb:2:in `<top (required)>'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-parallels-1.7.8/lib/vagrant-parallels/driver/meta.rb:4:in `require_relative'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-parallels-1.7.8/lib/vagrant-parallels/driver/meta.rb:4:in `<top (required)>'
from /opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-parallels-1.7.8/lib/vagrant-parallels/provider.rb:16:in `usable?'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/vagrantfile.rb:138:in `machine_config'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/vagrantfile.rb:45:in `machine'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/environment.rb:694:in `machine'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-auto_network-1.0.2/lib/auto_network/action/filter_networks.rb:38:in `block in machines_for_env'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-auto_network-1.0.2/lib/auto_network/action/filter_networks.rb:36:in `map'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-auto_network-1.0.2/lib/auto_network/action/filter_networks.rb:36:in `machines_for_env'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-auto_network-1.0.2/lib/auto_network/action/filter_networks.rb:30:in `filter'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-auto_network-1.0.2/lib/auto_network/action/filter_networks.rb:18:in `call'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/warden.rb:34:in `call'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-auto_network-1.0.2/lib/auto_network/action/load_pool.rb:19:in `call'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/warden.rb:34:in `call'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-triggers-0.5.3/lib/vagrant-triggers/action/trigger.rb:17:in `call'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/warden.rb:34:in `call'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-triggers-0.5.3/lib/vagrant-triggers/action/trigger.rb:17:in `call'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/warden.rb:34:in `call'
from /Users/kevin/.vagrant.d/gems/2.4.3/gems/vagrant-triggers-0.5.3/lib/vagrant-triggers/action/trigger.rb:17:in `call'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/builder.rb:116:in `call'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/runner.rb:66:in `block in run'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/util/busy.rb:19:in `busy'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/action/runner.rb:66:in `run'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/environment.rb:504:in `hook'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/lib/vagrant/environment.rb:165:in `initialize'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/bin/vagrant:131:in `new'
from /opt/vagrant/embedded/gems/2.0.3/gems/vagrant-2.0.3/bin/vagrant:131:in `<main>'

 

The most likely reason this happens is that plugins using Nokogiri have to build what are called native extensions each time. That means that the end result of that building is specific to your computer and various things on it. If those things change (e.g. Vagrant changes its version of Nokogiri), then the build becomes invalid and has to be redone.

In this case, it has to be redone across the board, and the easiest way is just to reinstall all plugins.

For that, you can use the vagrant plugin expunge --reinstall command.

You can then get back to developing!

 

(It’s worth noting that the command didn’t work on my older macOS computer, but it did work on my newer one. I’m not really sure why, since they have the same version of Vagrant. I just left the old computer as-was since I didn’t really need to fix it at the time.)

 

Source: https://github.com/hashicorp/vagrant/issues/9599

WizOne Solutions will be at Drupaldelphia and Drupal Dev Days Lisbon (so far)

I wasn’t planning on Drupaldelphia OR Drupal Dev Days this year, but I’ll be going to both. If you are too, and want to meet up or talk, get in touch via my contact form above or on Twitter.

 

P.S. I’m strongly considering going to DrupalCamp Nordics in Stockholm early September and Drupal Iron Camp in/near Belgrade mid-to-late October. Playing with the idea of WordCamp Vienna, too, but that’s much less likely 🙂