Drupal

Drupal and upgrading PHP from v5 -> v7

I finally bit the bullet to upgrade PHP from v5.x to v7.2.x (v7.3.x is not yet supported by this version of Drupal). So, of course, it was a disaster, and nothing worked. I had to do a few things to get things up and running again.

First, it would not execute my .php scripts, rather, it would return them as text ... I ended up adding this to my httpd.conf:

<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>

Alright, so that helps! Now, of course, it's failing with a DSO error like

 [client 127.0.0.1:32794] PDOException: SQLSTATE[HY000] [2002] No such file or directory...

Not particularly useful, but my friend Brian France helped me track this down. Turns out, for some reason my PHP is not finding the mySQL domain socket, even though it's in the default directory. I modifed my php.ini accordingly:

pdo_mysql.default_socket = /var/lib/mysql/mysql.sock
mysql.default_socket = /var/lib/mysql/mysql.sock
mysqli.default_socket = /var/lib/mysql/mysql.sock

Voila! Now the last thing I had to tweak with my installation was opcache, I still don't understand why this is not enabled and configured with sensible defaults in PHP by default. But, in my php.ini, I added

zend_extension=/opt/php7/lib/php/extensions/no-debug-non-zts-20170718/opcache.so
[opcache]
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000

 

Hacking: 

Drupal 8 upgrades

I did the latest security updates for Drupal 8 on this system, and ended up having new problems that I've not seen before. This showed up in my logs:

[Thu Jan 17 13:40:42.339572 2019] [:error] [pid 12676] [client 127.0.0.1:37080] PHP Fatal error:  Class 'TYPO3\\PharStreamWrapper\\Behavior' not found in drupal8/core/lib/Drupal/Core/DrupalKernel.php on line 484

The solution, of course, is to update the dependency modules, using

$ composer install --no-dev

 

Hacking: 

Optimizing Drupal7 CSS and JS

Even though Drupal (since long ago) supports merging CSS and JS into one file each, after I upgraded from v6 to v7, I still ended up getting more than one of each. It turns out, Drupal has some notion of groups, and it would only merge the CSS / JS elements within each group. I did some web searches, and came up with the following:

function pixture_reloaded_js_alter(&$js) {
  if (arg(0) === 'admin' || strpos($_GET['q'], 'search/google') === 0) {
    return;
  }

  uasort($js, 'drupal_sort_css_js');
  $weight = 0;

  foreach ($js as $name => $javascript) {
    $js[$name]['group'] = -100;
    $js[$name]['weight'] = ++$weight;
    $js[$name]['every_page'] = 1;
    $js[$name]['scope'] = 'footer';
  }
}


function pixture_reloaded_css_alter(&$css) {
  uasort($css, 'drupal_sort_css_js');

  $print = array();
  $weight = 0;
  foreach ($css as $name => $style) {
    $css[$name]['group'] = 0;
    $css[$name]['weight'] = ++$weight;
    $css[$name]['every_page'] = TRUE;

    if ($css[$name]['media'] == 'print') {
      $print[$name] = $css[$name];
      unset($css[$name]);
    }
  }

  $css = array_merge($css, $print);
}

This goes into the Theme's template.php file, in my case I use the Pixture Reloaded theme. I don't know much about Drupal nor PHP, so I don't know what this might break. But this accomplishes three things:

  1. Merge all CSS into one single CSS.
  2. Merge all JS into one single JS.
  3. Move the JS to the "footer" of the page (this is important for improved page rendering, but could potentially break some sites I'd imagine).

Hacking: 

Druapl 7 problems behind a proxy

I run Drupal behind an Apache Traffic Server caching proxy. In my setup, the proxy listens on port 80, and the real Apache HTTPD server listens on port 82 (which is firewall off). In my Traffic Server remap.config, I have a rule like

map http://www.boot.org  http://www.boot.org:82

Granted, in retrospect, this is not the best of setups, but it does however causes serious problems with Drupal 7, whereas it does not cause problems with Drupal 6. In D7, the favicon.ico and all JS and CSS URLs in the head are created to use absolute URLs. I don't set an explicit $base_url in my Drupal settings.php, more on that later, and this causes the URLs to get the wrong base! These URLs are all getting a form like

http://www.boot.org:82/misc/favicon.ico

Yikes! This obviously fails, since port 82 is not accesible from the outside. Browsing the forums, the "solution" seems to be to set the $base_url in the Drupal settings.php configuration file, e.g.

$base_url = 'http://www.boot.org';  // NO trailing slash!

This does indeed solve the problem, however, it now breaks when I want to use e.g. https://www.boot.org for admin access. Besides, why these URLs should be absolute, is a mystery to me, they certainly were not in D6.

The solution I'm ending up with is of course to change Apache Traffic Server to use what we call "pristine host headers", so that the Origin server (Apache HTTPD and Drupal) sees the original client Host: header. I could not get any help from the Drupal IRC, or forums, but if anyone has any insight on why D7 is doing this crazy stuff with absolute URLs, please post. In an ideal world, they really should change these to be relative, e.g. /misc/favicon.ico.

Hacking: 

Drupal, Traffic Server, HTTPS and CDNs

I use Drupal for most of my sites. It generally works well, despite all the weirdness it does (Drupal 7 is doing strange things behind a proxy, more later). One thing is, I've started using a CDN (NetDNA) for my site. With HTTPS, this generally doesn't work well, since I'm not enabling HTTPS for the CDN (at least not yet). The CDN module in Drupal generally works well, but I couldn't see an option to prevent it from using the CDN with HTTPS. This would generate those annoying warnings from Internet Explorer for example.

Since I'm also using an Apache Traffic Server proxy in front of Apache HTTPD, the protocol information was lost oncey it hit Apache, PHP and Drupal. Bummer. I browsed through the CDN code, and noticed they do indeed honor a header of X-Forwarded-Proto, which if set to "https" will prevent the CDN from being used. I added a plugin for my remap rules, with a config like

[SEND_REQUEST_HDR]
        X-Forwarded-Proto =https=

And I activated this for the https remap.config rules for Apache Traffic Server. With this, my Drupal site now stops using the CDN when Apache Traffic Server maps from https:// to the http://localhost URL.

Hacking: 

Filtering Drupal comment spam

I get a fair amount of comment spam on my blog, and even after I changed all comments to be moderated, the spammers still persist. I decided to do something about this, and working under the assumption that most spammers are from a few countries, I decided to implement a Geo-location filter for Apache Traffic Server. The code is currently available at http://svn.apache.org/repos/asf/trafficserver/plugins/geoip_acl/, and only works with MaxMind's APIs (but I'd be more than happy to add support for other Geo-location APIs). This plugin also requires PCRE, but that's already a requirement for building ATS, so shouldn't be a problem.

Once compiled and installed (see the README), setting this up is fairly straight forward. In my remap.config, I now have the following rule

map http://www.ogre.com http://localhost:69 @plugin=geoip_acl.so @pparam=country \
       @pparam=regex::/home/server/etc/deny_spam.conf


This says to apply a country based Geo-location filter on this rule, using the additional configurations from deny_spam.conf. This file contains one single line:

^comment/       deny    CN RU IN

This might look draconian, but for now I'm disabling all comment posts from China, Russia and India. For more details on the plugin configurations and features, again see the README from the source above.

Enjoy!

Hacking: 

Drupal and e-commerce

I recently helped a friend setting up his new E-commerce site (http://www.weinerwraps.com/) using Drupal. We were considering a few modules, and finally decided on using UberCart. Now, our site isn't flashy, or have fancy graphics, but getting it functional was really easy. What we currently have working is

  • Paypal payment option
  • USPS shipping (with shipping calculations)
  • Basic cart features, different products, checkout options etc.

We've had a few issues on the way, most notably (and very confusing) was that the shipping cost calculator stops working if you disable the country field from the user entry for the shipping address. This made absolutely no sense to me (since we only ship to the US), and there were no errors or indicators whatsoever. Clearly someone didn't think through a typical use case scenario here ... Other open issues include

  • We have an optional addition to each order, for embroidery, where we'd like the price to be adjusted based on the length of the entered text.
  • There's no way to make the product picture adjust to selected options. There are a few modules that claim to do this, but none that really works.

All in all, setting up an E-commerce site with Drupal and UberCart has been a pretty good experience.

Hacking: 

Must-have Drupal modules

This collection of pages is my own personal experience with various 3rd party Drupal modules. I'm not really saying you must have these modules, but I personally find them incredibly useful. I'm not ranking these modules in any particular order, instead I'm trying to organize them by functionality. If you have suggestions for modules that I ought to include here, please let me know, and I'll be happy to add them (after I try 'em of course).

Content related modules

The modules in this section either create new content types, or let you manipulate or create content types.

Hacking: 

Pages

Subscribe to RSS - Drupal