Jan 19, 2015

Setting up virtual hosts for multiple domains in Apache

On my local Linux Mint system running Apache, the server root is at /var/www/html. Because I have multiple sites, each site is installed in a subdirectory under that root.

To browse to a site, I would use a url such as localhost/opti for the Optimizely module, which happens to be an instance of Drupal 8.

Lately, I've had problems with some site roots being subdirectories under the server root rather than being at the server root itself. So I figured it was time to learn how to set up virtual hosts.

The following steps worked for Linux Mint 17 with Apache 2.4.7.

(0)  Enabled the Apache module vhost_alias.

#  a2enmod  vhost_alias

(1)  Created a virtual host.

# cd  /etc/apache2/sites-available
# cp  000-default.conf  opti.conf


Edited opti.conf so that within the <VirtualHost *:80> directive, two changes were made.

Inserted the line for ServerName, where opti.local will be the url to use for the local site.

  ServerName  opti.local

Edited DocumentRoot to set the site root to its path.

  DocumentRoot  /var/www/html/opti


(2)  Enabled the site.

#  a2ensite  opti

(3)  Directed the new url to the local system.

Edited /etc/hosts to add  the following line.

127.0.0.1  opti.local

(4)  Restarted Apache.

#  service  apache2  restart

(5)  Browsed to opti.local instead of localhost/opti.

Caveat: after I set up the virtual host, I had problems with code that does matching of paths when I absent-mindedly went back to using the url localhost/opti. Although I haven't really explored this, there appears to be confusion that results from two different notions of what the base url is. If you've got a virtual host, it's best to use its url consistently.

(Many thanks to Darren Lee for mentioning Apache's virtual hosts to me.)

Sources:

Setting Up Virtual Hosts for Apache on Ubuntu for Local Development
http://blog.code4hire.com/2011/03/setting-up-virtual-hosts-for-apache-on-ubuntu-for-local-development/

How To Set Up Apache Virtual Hosts on Ubuntu 12.04 LTS
https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-hosts-on-ubuntu-12-04-lts

Jan 16, 2015

DBUS_SESSION_BUS_ADDRESS is not properly set when switching user

On my Linux Mint system, I often su root in order to open a shell with elevated privileges. Running programs in that shell sometimes displays warning messages that I generally ignore as long as the program seems to work okay.

Recently, though, I have been running the nemo file manager and have not been able to save changes to its preferences. This was driving me nuts and I finally figured out what the problem was.

Here is a sampling of three commands and their warnings when I ran them after su root.



# nemo

Error creating proxy: The connection is closed (g-io-error-quark, 18)
(nemo:4365): dconf-WARNING **: failed to commit changes to dconf: The connection is closed




# gsettings set org.nemo.preferences show-hidden-files true

(process:4393): dconf-WARNING **: failed to commit changes to dconf: The connection is closed



# gedit

(gedit:4382): GConf-WARNING **: Client failed to connect to the D-BUS daemon:
Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
GConf Error: No D-BUS daemon running




Apparently, when you su root or to some other user, the value of the environment variable DBUS_SESSION_BUS_ADDRESS is supposed to change to that of the other user, but it doesn't.

I  found there are at least two ways to get around this. Either works.

(1)  Use sudo instead of opening a different shell. For example,

# sudo nemo

(2)  Add these two lines to the .bashrc file for root so that the environment variable is set to the correct value.

sessionfile=$(find "${HOME}/.dbus/session-bus/" -type f)
export $(grep "DBUS_SESSION_BUS_ADDRESS" "${sessionfile}" | sed '/^#/d')

A longer and more robust version of this code can be found in a comment in the source article.

Source:

GConf Error: No D-BUS daemon running?! How to reinstall or fix?
http://ubuntu.findincity.net/view/635400140124705175219724/gconf-error-no-d-bus-daemon-running-how-to-reinstall-or-fix

Jan 11, 2015

Installing Drush for Drupal 8

Having converted the Optimizely module to run under D8 beta 4, I thought I'd get drush working under D8 as well.

Here's what I got when I downloaded the archive, installed drush as I had done previously for D7, and typed in drush status for a D8 site:

PHP Fatal error:  Class 'Drupal' not found in /var/www/html/opti/core/includes/bootstrap.inc on line 171

Oops, outdated archive, dated July 2013. Do not use the archive at

  drush 8.x-6.0-rc1
  https://www.drupal.org/node/2041157



Drush is now maintained on GitHub at  https://github.com/drush-ops/drush

According to the docs there, Drush 7 is the version that works with Drupal 8. Unfortunately, at the time I visited the repo, the build was flagged as "failing".

Masochist that I am, I decided to push on anyway to see how much mileage I might get. (The logs show that Drush is in very active development.)

There are a lot of different ways to install Drush — see Install - Drush docs.

Sometimes I just like to install in a slower but more transparent way.

So on my Linux Mint system, I downloaded the zip archive from the GitHub repo, extracted it, and created a symbolic link in /usr/local/bin to the drush executable so that this version of drush would be globally available.

From the Drush root, I ran composer install to fetch the dependencies. If you don't already have composer installed, that will need to be done first.

At that point I had a working copy of Drush.

At the root of a D8 site,

  # drush status

worked as expected.

  # drush cc all

gave the error message 

  `cache-clear all` is deprecated for Drupal 8 and later. Please use the `cache-rebuild` command instead.

The replacement commands for D8 are

  # drush cache-rebuild
  # drush cr

For the examples module, these worked fine to download and to enable.

  # drush dl examples
  # drush en examples

But

  # drush dis examples

gave this expected error message

  Drupal 8 does not support disabling modules. Use pm-uninstall instead

  # drush pm-uninstall examples
  # drush pmu examples

And at the root of a D7 site, all of the above commands worked except that you still use

  # drush cc all


Sources:

Drush
https://www.drupal.org/project/drush

drush-ops / drush
https://github.com/drush-ops/drush

Install - Drush docs
http://docs.drush.org/en/master/install/

Upgrading Drush to work with Drupal 8
https://drupalize.me/blog/201408/upgrading-drush-work-drupal-8

Jan 8, 2015

Beta 4: drupal_match_path() and drupalSettings.path.basePath() replaced

Moving from Drupal 8 Beta 3 to Beta 4 turned out to be a significant chunk of work.

Much of that was due to functionality that was previously deprecated but still available that has been removed altogether. We continue to be nudged into doing things the D8 way.

Here are a couple of more changes I made for this release. This wraps up my findings for Beta 4.



  Fatal error: Call to undefined function Drupal\optimizely\drupal_match_path() in /var/www/html/opti/modules/contrib/optimizely/src/PathChecker.php on line 193

Function drupal_match_path() has been removed and replaced. For example, instead of the call

  drupal_match_path($target_path, $project_paths)

use this.

  \Drupal::service('path.matcher')->matchPath($target_path, $project_paths)



In javscript code, drupalSettings.path.basePath has been replaced with drupalSettings.path.baseUrl .



Sources:

New PathMatcher service
https://www.drupal.org/node/2274675

current_path() is replaced by the <current> route
https://www.drupal.org/node/2382211

Jan 1, 2015

Beta 4: hook_page_build() has been removed, as well as function current_path()

hook_page_build() has been removed and replaced with several other hooks. In our case, we used the new hook_page_attachments() since a dynamically generated piece of javascript is being attached to selected pages.

So instead of

  function optimizely_page_build(&$page) { .... }

in the D8 version it is

  function optimizely_page_attachments(array &$page) { .... }

The body of the hook function remained largely the same, but there were some changes as described below.



Function current_path() has been removed in favor of using the built-in route <current>. For example, in place of

  $curr_path = current_path();

I did this,

  $url = \Drupal\Core\Url::fromRoute('<current>');
  $curr_path = $url->toString();



N.B. The value of $curr_path in this example code contains a leading slash character. Although I'm not certain, from the reading I've done so far, it seems this is considered the standard for internal paths within D8.

Unfortunately, this is at odds with how paths are specified by users of the D7 version of the module and causes path matching to fail.

I decided to fix this in our code by stripping off such a leading slash. This preserves compatibility with D7 data, but possibly violates D8 conventions.



In D7, pulling in javascript from an external source can be done with something like this.

  $page['#attached']['js'][] = array(
    'type' => 'external',
    'data' => $js_snippet,
  );

Attaching javascript directly in this way is no longer allowed.

For static js and css, you can use libraries as described in the posting
http://optimizely-to-drupal-8.blogspot.com/2014/12/beta-3-beta-4-use-libraries-not.html

For the dynamically generated javscript needed for the module, here's what I did.

  $page['#attached']['html_head'][] = array(
    array(
      '#tag' => 'script',
      '#attributes' => array(
        'type' => 'text/javascript',
        'src' => $js_snippet,
      ),
      '#value' => '',
    ),
    'optimizely-snippet',
  );

That last array element 'optimizely-snippet' is not actually used in this module. I include it as example of "a key, to make it possible to recognize this HTML <HEAD> element when altering".

Happy 2015!



Sources:

Added hook_page_attachments(_alter)() and removed hook_page_build/alter()
https://www.drupal.org/node/2357755

function hook_page_attachments
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/function/hook_page_attachments/8.0.x

current_path() is replaced by the <current> route
https://www.drupal.org/node/2382211

Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module
https://www.drupal.org/node/2274843