Monday, December 2, 2013

National Library of the Netherlands - Migrating multilingual xHTML from a shoe-box to Drupal 7

In fact I am a very lazy person. That's why I studied theoretical physics. In school I simply compared the number and thickness of the books for the different studies, and concluded that physics must be the one where this laziness would prosper most.
Feynman diagrams
The thing is, as soon as you understand a part of physics, you can stop reading. Not so with history, not so with all other subjects. They require hard mental labour.
(I have to find some apology for studying philosopy lateron, so any suggestions are welcome....)

Hail Laziness
Laziness is one of the least respected human inclinations.  If there where no lazy people, no one would have invented the car, the combine, the phone et cetera. We would all be working our asses off all day in the fields, pushing little grains out of their stalks one by one. Books would have no indexes. Skyscrapers no elevators. Chairs no legs.

Royal Library of the Netherlands
One fine day (early 2012) we got like the following request from the Royal Library.

On the left we've got twenty shoeboxes of HTML, and on the right we have a brand new core structure for the website in Drupal 7: Contenttypes, Display Suite, Views and all.
Could you please import the information from the shoeboxes into the Drupal 7 system. Thankyouverymuch and Yesterday would be fine.


Being Lazy we simply said: Yes, of course we can. There is nothing we can't do.
And then imagine the soundtrack of Jaws on the background........

Delusions of simplicity
We said so because the concept in itself is very simple.

      Here we have content A, B and C. In booklet X.
      There, on the other side, is a new booklet Y.
      Now copy A, B and C to booklet Y.

      X( A B C )         -->        Y( A B C )


What the hell were you thinking!
The source being ante-diluvian xHTML, more or less templated,  from which we had to sift images, downloads and all other digital objects, parse all content from all these different structured pages, and then load and upload everything in the totally different structured Drupal 7 system.

Book of Hours of Simon de Varie. Paris, 1455;  Tours, c. 1455.
Vellum, 99 leaves, 116 x 85 mm. - 74 G 37a, fol. 1v-2r
We're talking repeatable fieldcollections in repeatable fieldcollections,  migrating source images to different caching formats, programmatically generating en configuring viewmodes, and showing them via the Display Suite and the Media module, which at the time was still in the development phase. And apart from that, there was still development going on the the target Drupal site.
Oh Yeah, and did I mention the multilingual part? English and Dutch.

So it's a project with a big red rubber stamped warning on the cover:

      Send project manager to 
      high altitude trainingcamp 
      before start!

Or, stated differently, in common ICT jargon: Blood, Sweat and Tears ahead.

Analysis: Dance like a butterfly...
The approach we used was the equivalent of dance like a butterfly and sting like a bee in webdevelopment. There is no way to oversee all problems in this kind of large projects concerning conversions between two totally different systems. In the quotation we made, which needed to be fixed price, we tried to include some bleeding control, but we knew beforehand that we were entering the Swamp part of our Portfolio. 
It proved for instance especially difficult to emulate the maintenance features in the old system, which was an xml based editor. There was no way we could migrate these features to the new D7 setup.  We were down to analysing every feature and  approach it from a totally different angle in D7.
Another unexpected tricky part was recalculating all internal links in the site. We had to iterate all pages aproximately twenty times before we had all link types covered. Some linkit, some entityreferences, some link fields, et cetera.
Don't get me started...
For the sake of your mental health I will not elaborate on the technical details, anyone interested can contact me directly, but it's a lot like this
    $filename2=createfilenameforimage($filenamearr);
    $file2 = file_save_data($image2, 'public://'.$filename2,FILE_EXISTS_RENAME);
    $field_collection_item->field_afbeelding=array(LANGUAGE_NONE => array('1' => (array)$file2));

    $field_collection_item->field_alttekst[LANGUAGE_NONE][0]['value'] = $animageobject->alt;
    $field_collection_item->field_titletekst[LANGUAGE_NONE][0]['value'] = $animageobject->title;


and than for days on end....
(And as for the bleeding part: Whoever thought up the idea of littering PHP code with all these dollar signs?)

5% inspiration, 99% iteration
I think we did about ten migrations. And after every migration the Royal Library checked the new site and discovered some new features or parts that weren't specified but certainly needed to be migrated as well. The Math was never right!

Never again!
And when you are finaly finished, and the site is migrated and the Royal Library is happy, the first three days you say to yourself: Never again. Behind every mountain there was another mountain, behind every tree there was a madman with an axe, behind every solution there appeared a brand new grinning unexpected problem produced by the very same solution, with five other problems stacked up his sleeve.
But on the fourth day you realise how much fun we had, how much we learnt about the internal workings of Drupal.

Geek sucks
I sometimes mind the Geeky part of my work, days of trying to get a certain piece of code right, minimal pixel adjustment feuds with the designers, that stuff. But when the subject matter itself is something like the Royal Library content, or digital heritage projects in general, I might just possibly be able to live with that.


http://www.kb.nl/en

Saturday, November 30, 2013

Drupal 7 - Moving the messages text from a zone to a region in an Omega subtheme

The messages always mess up my page layout, so I usually simply want them on the top of my page content.

1. remove message from its default postion
1.a  Copy  zone--content.tpl.php to your subtheme's template directory (if you have not done that already)
1.b Remove these lines
  <?php  if ($messages): ?>
      <div id="messages" class="grid-<?php print $columns; ?>"><?php print $messages; ?></div>
    <?php endif; ?>


2. transfer the messages variable to the region template
2.a Open template.php
2.b add a preprocess functio, or modify if you alreay have one

 function THEMENAME_preprocess_region(&$vars) {
      $theme = alpha_get_theme();
     if ($vars['elements']['#region'] == 'content') {
       $vars['messages'] = $theme->page['messages'];
    }

 }


3. add the messages to the region template
Just write anywhere you want in the template
    <?php if ($messages): ?>
      <div id="messages" class="grid-<?php print $columns; ?>"><?php print $messages; ?></div>
    <?php endif; ?>

Drupal 7 - Adding multiple javascript files to an Omega subtheme

Adding a javascript to an Omega subtheme is a bit complex.
I'd rather use  scripts[] = js/chr.js in the info file, which works by the way, but for some reason you first need to add the js file as a library, and then enable it in the settings.
(see https://drupal.org/node/1416128 and https://drupal.org/node/1205984)
I this example I add one library containing two javascript files.

0. Add your javascript files in the js folder of your theme
(in this example I use files chr.js and chr2.js)

1. Add some code like this to your theme's info file

libraries[chromega][name] = CHR KHR main javascript
libraries[chromega][description] = Quirqks and Jeeeequery fun for th CHR website
libraries[chromega][js][0][file] = chr.js
libraries[chromega][js][0][options][weight] = 1
libraries[chromega][js][1][file] = chr2.js
libraries[chromega][js][1][options][weight] = 2

(you can use any name where I use chromega)

2. Go to your theme's settings page

3. Select tab toggle libraries and add your custom library











4. Clear you cache  

5. and then GO javascripting
(I always forget the structure for the D7 javascript files so thats why I add this wonderfull example)


// JavaScript Document
// http://drupal.org/node/756722
(function ($) {
 //////////////////////////////////////////////////////////////////////////////////////// All code here
   $(document).ready(function() {
     // maak op d ehomepage beide blokken even lang
     dotherightthing();   
  });
  function dotherightthing(){
      alert('Do the right thing!');
  }
 ////////////////////////////////////////////////////////////////////////////////////////  end of all code
}(jQuery));



        ---

Nota bene

For some reason this (lazy) way of adding the javascript in the template file does not work

function themename_preprocess_page(&$variables) {
  drupal_add_js(path_to_theme() . '/js/chr.js');
}

Friday, November 29, 2013

Drupal 7 - Adding captcha to a webform

Another thing I always have to lookup while it is so simple....
1. install the captcha and image captcha module
https://drupal.org/project/captcha

2. go to configuration > people > captcha

3. Add form id
Add the form id of the forms to which you want to add a captcha challenge on the bottom of this page and select the captcha type







You can find the id by opening the form an looking in the HTML. There you find an id like: webform-client-form-75

<form accept-charset="UTF-8" id="webform-client-form-75" method="post" action="/en/order" enctype="multipart/form-data" class="webform-client-form">


NB! Replace all hyphens by underscores!

webform-client-form-75    ->    webform_client_form_75

4. Translation
If you have a multilingual site and want to translate the description, you have to do this partly on the capcha configuration page, partly via the normal Drupa interface translation.
(which is rather stupid)

captcha config
For instance, as I am Dutch (although also half Frysian) I always translate
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
To a bit archaic
Deze vraag wordt gebruikt om te testen indien u een menselijke bezoeker bent teneinde spam-inzendingen te vermijden.

Interface translation
What code is in the image? *To
Welke code ziet u in de afbeelding?: *
Enter the characters shown in the image.
Which is more or less a useless repetition of the previous sentence I think, to
Vul bovenstaande code in.

5. State of Bliss
And then, your webform will contain a captcha. Rejoice!















For Drupal 8: see this post



Thursday, November 28, 2013

Drupal 7 - Changing the default file type icons without hacking core

A lot of time the designers want the icons just a little bit different than they are in drupal core. So, being lazy, I always just replaced the icons in core with the designer icons ad made a remark in my upgrade doc for that particular site.

A better way to achieve this is to just change the file icon path in your theme and put the modified icons somewehere outside the drupal core, so as being ably to upgrade your site and modules without any extra configuration steps.


function THEMENAME_file_icon($vars) {
  $file = $vars['file'];
  $icon_directory = drupal_get_path('theme', 'THEMENAME') . '/images/file_icons';
  $mime = check_plain($file->filemime);
  $icon_url = file_icon_url($file, $icon_directory);
  return '<img alt="" class="file-icon" src="' . $icon_url . '" title="' . $mime . '" />';
}


Copy the map modules/file/icons to a the images directory in your theme.
Rename the map file_icons
Change any image in this map to your (or your beloved designers) liking and you're set.


Monday, November 25, 2013

Drupal 7 - Presave a node (or doing custom validation and/or manipulation on field values)

I now have the simple specification that I have a text field in a Node which always needs to be uppercase, whatever the editor enters in the field. As a second specification I also want all spaces removed from the field values.
I could not find an example snippet to start up from, so I thought better publish this, maybe someone else will have  an easier live than me....

Specification
Field x: user may enter any character, but on saving the field all characters will be uppercased.
Field x: Also, alle whitespaces will be removed from the string


1. Create a module, in this example called customchr.
1. a Create info file  customchr.info

name = Custom CHR
description = Custum manipulations for the CHR site
package = Overboord
core = 7.x



2. Create module file customchr.module

function customchr_node_presave($node) {
  if ($node->type == 'publication') {
    // convert to uppercase
    $tempstring=strtoupper($node->field_publication_code[und][0][value]);
    // strip all whitespaces
    $node->field_publication_code[und][0][value]= preg_replace('/\s+/', '', $tempstring);
  }
}










Drupal 7 - Theming file field for documents

What seems to be a really simple task for any Drupalist got me really walking the ceiling this evening.
I just want to display my filefields, for the document, as a download limk with an icon denoting the file type and with the filesize mentioned. It seems to me that that should be the default way to show a download, but it is not.
After playing with the custom field formatters for a while, I used an easier approach.


1. Go to view modes and add a viewmode
2. give it a understandablen namen (vm_file_icon_download_size)
3. Check file
4. save
5. go to structure > file types (or older Drupal version you can find that under configuration)
6. click 'manage display' in the document row
7. click on tab 'custom display settings'
8. check the new view mode you just added
it appears as a tab in the top of your page
7. click on this tab and then click on manage file display
8. Choose table of files
Drupal will then show a rather ugly table with all element I want, the icon, the filename, the size.
I can rewrite the css to make it all a bit less ugly


.file.file-document table thead {
       display:none;
 }

.file.file-document table, .file.file-document table tr  {
      border:none;
      background-color: #FFFFFF;  
}
.file.file-document table td  {
      display:inline;
}


The link in the display will then look like



BUG: Description bug
But when you enable a description this still won't show.
This is caused by a bug in the file entity module.
https://drupal.org/node/1784762
Using the patch resolves this issue

https://drupal.org/files/file-entity-load-description.patch