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/ 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.

Drupal terminology vs old-fashioned DB words

Drupal’s entity model is pretty confusing if one is used to the strict world of ‘proper’ RDBMSs, but it does start to make sense after a while. It’s best to just forget about all the cruft that comes with the standard installation, and work with the base functionality (and some that’s currently provided by modules but seems will be in D8 core).

Taxonomy, for instance, provides a subset of the functionality that can be built with entity references (a.k.a. foreign keys in the relational model, except there’s no integrity!).

The commenting system (which is also in core) can be constructed with basic Drupal things like content types, views, blocks, and rules.

Same goes for Book pages. Everything, really.

(At least, this is my current thesis; an attempt to reduce the number of modules I have to get my head around to under a thousand…)

Basically one needs to just know of the following:

Database term Drupal equivalent (sort of)
Table Content (or Node) Type
Row Node
Column Field
Foreign key Entity reference field
View View
Enum field type list_text field type
Boolean field type list_boolean field type

A bug in the Workflow module confuses me

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

/var/www/$ drush fr featurename

Fatal error: __clone method called on non-object in /var/www/ on line 55
Drush command terminated abnormally due to an unrecoverable error.

Error: __clone method called on non-object in /var/www/, 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.

Features (my cheatsheet)

The Features module is great. I think. Sometimes it seems too good to be true… usually it just is good though.

One can build a site in one’s local Drupal installation, and then piece by piece export its definition to a feature module that can be put under version control and deployed to other sites in one fell swoop. Start with:

drush fe --version-set=7.x-0.1 --destination=sites/all/modules/custom/featurename featurename components

where featurename is the new module’s name and components is the first thing to export (usually a content type). From then, the destination can be left out, and the components definition is also pretty flexible at making it quicker to select which components to export (naming contentions, such as common prefixes, help with this). So, as the site progresses, export new components to the feature:

drush fe --version-increment featurename components

If a component that’s already been exported needs to be changed, just change it and then update the feature with:

drush fu --version-increment featurename

That’s about all there is to the construction phase. Stick the sites/all/modules/custom/featurename directory into a VCS. Then it’s deployment time…

Check the featurename module out to the staging site (in the custom directory still, just for clarity’s sake) and enable the module:

drush en featurename

That only needs to be done the first time; subsequent updates are just cycles of updating the code and reverting the feature (a note on the slightly-confusing terminology of Features: one reverts (fr) the site, or updates (fu) the code).

$ git pull origin master
$ drush fr featurename

‘Add node’ link in Drupal Views’ header

Very often one wants to add a link to a View’s header or footer that allows users with permission to quickly jump to the relevant content creation form.

It’s easy to create a Global: Text area with the link, but this would then be seen by all users, regardless of authorization.

A few people have had similar thoughts.

I don’t know if there’s a better way (i.e. probably one that doesn’t involve PHP, not because this is a particularly complicated way of doing things but just that I always figure that Drupal should be usable by non-coders), but here’s how I’ve got it working:—

Required modules: views, views_ui, and php.

Add a Global: Text area header to a view, and select the PHP code text format for it. The code is as follows:

Add new article

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.

What’s the point?

Oh weary thing! Oh listless drudgery! Oh the stupid work we make for ourselves!! Oh!…

Here I sit, on a cool spring morning, with nothing at all to worry about; I am happy. So why-oh-why-oh-why should I sit down to work at some sloppy, good-for-nothing code that purports to “record, display and analyze genealogical data”?! Why?! This world certainly does not need me to be spending my time in meaningless work that helps no-one. Programming feels at times as though we’re just making up work for ourselves, work that doesn’t — in the Great Scheme Of Things — actually need to be done. Growing food, building houses, having sex, talking to old people: these are fundamental to living. Building Drupal modules is not.

It must be said also, that blogging is not. So I’ll stop now. I do not really think that I was making much sense anyway; sorry.