Uninstalling WordPress plugins in PHPunit

There’s a problem with uninstalling Tabulate.

Fatal error: Class 'WordPress\Tabulate\DB\Grants' not found
in C:\work\public_html\wp\stage\wp-content\plugins\tabulate\uninstall.php on line 8

The uninstall.php file shouldn’t know anything about the actual plugin. It shouldn’t use any classes or functions from the plugin itself.

This problem should have been caught before now, though, because the tests all run uninstall.php in their tearDown() function. The reason they don’t is that the Tabulate classes are still available at that point.

Perhaps it’s a matter of removing the autoloader? In the tearDown() function:

$autoloader = require __DIR__.'/../vendor/autoload.php';

But no, then the autoloader isn’t loaded for the next test. So can we re-enable it in setUp()? Yes, but that still doesn’t make it fail on the classes used in uninstall.php… I’m not sure why not.

Is there anything wrong with just including autoload.php in uninstall.php? No, I thought not.

That was easy.

Loading spatial data into MySQL with LOAD DATA INFILE

Just a note for my future reference: importing an Excel CSV into MySQL. The WKT column has been constructed by hand to be POINT(lng lat) and the CSV contains headers.

LOAD DATA INFILE '/full_path/to/file-on-server.csv'
INTO TABLE the_table
SET geographic_location = GeomFromText(@geographic_location)

Including views in Drupal modules

Views are included in modules by implementing hook_views_api() and hook_views_default_views() and returning an array of view objects from the latter.

The easiest way to construct the view object is to create the desired view via the UI and then export it, saving each exported view into its own function in sites/all/modules/custom/modulename/modulename.views_default.inc and then returning them all in modulename_views_default_views() in the same file (named e.g. _modulename_views_view_name()). For example:

 * Implements hook_views_default_views().
function worksmanagement_views_default_views() {
  return array(
    'work_orders' => _worksmanagement_views_work_orders(),
    'job_reports' => _worksmanagement_views_job_reports(),

All of which is good, and works well. (Why not use Features for this, which more or less does exactly the same thing? Not sure; probably stubbornness. That doesn’t matter for now though.) The confusion comes with updating the exported views.

When a view is created, its definition lives in the views_view and views_display database tables. Once the view has been exported and saved into the module, its definition is stored in two places! This can be seen in the Views admin screen, where (once the caches have been cleared) the view is shown as “Database overriding code” rather than “In database”. There will also no longer be an option of deleting it; rather, it can be reverted. Reverting a view will delete its metadata from the two DB tables, and it will be defined exclusively from the module’s code. This is good.

The next step is to edit the view, make some changes, and re-export it. Do not save it! There is no need to save the changes you make (as this would then stick it back into the database and you’d just have to revert it again), but rather just use the export function available from the view editing UI under the edit view name/description menu (see screenshot below). This will export the view as it stands (i.e. in its unsaved, editing state).

Screenshot of View export menu item

After exporting and overwriting the code in _modulename_views_view_name(), clearing the cache is all that’s required to make the view active and update to date with what’s in the module’s code.

Note that the view will be locked for editing; hit ‘cancel’ to unlock it, or break the lock when prompted when next editing the view.

(This is why I don’t want to use Features for this: it feels better to have everything living in the module, rather than having to copy (or ‘revert’ as Features calls it) view definitions from the module into the database.)

Taxonomy is good after all

I was perhaps too hasty to dismiss Drupal’s taxonomy system. It is perhaps good to make this distiction between ‘content’ nodes and ‘metdata’ nodes; why create ‘content types’ for data that isn’t content?

So I need a new rule… perhaps it’s to do with frequency of updates and inserts? So that any entity whose records are not regularly updated or created should be thought of as non-content, and use the Taxonomy constructs.

A Book content type, for instance, might have a field for Binding Type which ten years ago we set to Hardcover, Paperback, and Magazine (or whatever… those are not great examples, but for a home library perhaps representative). Now we add Ebook also, but really that’s the limit of the modifications. Under the bare-bones Drupal paradigm with no taxonomy, one would create a Binding Type content type, and create only three nodes in it. Such foolishness! Better to create a new vocabulary.

A bug in the Workflow module confuses me

I’m getting and annoying error when running reverting a Feature (drush fr featurename):

/var/www/stage.example.org$ drush fr featurename

Fatal error: __clone method called on non-object in /var/www/stage.example.org/sites/all/modules/workflow/workflow.features.inc on line 55
Drush command terminated abnormally due to an unrecoverable error.

Error: __clone method called on non-object in /var/www/stage.example.org/sites/all/modules/workflow/workflow.features.inc, line 55

It looks like this bug was fixed 2 September 2014 and is tagged as being fixed in 7.x-2.4 … but that version was released on 15 July.

[Update:] Ah. A coffee later, and I realise my stupidity this morning — the bug is tagged as being in 7.x-2.4, not fixed in that version. Gosh, one shouldn’t post before coffee!

I apply the patch manually.

Video in Drupal

tl;dr: Drupal is good with the Video and Flowplayer modules. Install them with drush -y en video flowplayer and just make sure you’re testing with a video file that isn’t broken!

I’m trying to create a very simple video library in Drupal. Just a single Content Type with a bunch of fields, one of which should be for uploading a video.

The Video module looks to be the first choice. It creates a field type, and sets up a system for re-encoding. Sensible.

So I install it: drush -y en video

Then set up a transcoder by installing FFmpeg and telling Drupal where to find it. Also a Preset, which groups together output details like file extension, codec, sizes, and a bunch of other details—most of which I left as given.

Probably silly, as when I try to upload an MP4 (one of these) I get: “The video conversion process has failed. You might want to submit a simpler video format like mpeg or divx avi.” So why can’t I just upload a simple mpeg and have it displayed without being re-encoded?

The video field settings have an option, “Enable auto video conversion”, which I turn off. This works: I can upload the MP4 and it’s thumbnail is displayed at a nice size and things sort of start to look like a video player… but sadly emblazoned with “No video with supported format and MIME type found.” Oh well, maybe a different player is needed (I was relying on the standard HTML5 player).

Installing the Flowplayer module helps a bit: now there’s a video player with controls and a spinning loader—but the same MIME type error as before. Switching the MP4 player to ‘FLV Flash Players’ (from ‘HTML5 Player’) is a bit great: now there is a player, and it plays the file… audio only though, no video.

I tried another video though, and all works correctly! So that’s nice.