Wednesday, 25 January 2012

Wiki filter for Drupal


One of the known problems with Drupal is no Wiki module. It is possible to put together a Wiki using various resources but the biggest stumbling block is the text filter.


There have been attempts and some successes. The current perceived wisdom is to use FlexiFilter - sorry but it's just too cumbersome. In fact nightmarish.


And I needed a Wiki filter for a project so this evening I spent 5 hours writing a Wiki filter for Drupal 7.


Does pretty much everything you could want including nested OL/UL lists which can be mixed - I only mention that particularly because it was a bitch. Otherwise it's got italics, bold, underline, strikethrough, h2-h6, blockquotes, code (pre), superscript and subscript.


So to set up a Wiki Text format on Drupal 7 you use these in this order:

  • Limit allowed HTML tags - to none, to clear out any tags in the text.
  • Then my filter
  • Convert line breaks
  • Assign IDs to anchors (From the TOC module)
  • Table of contents filter module
  • Freelinking module to deal with URL links

Then have WikiTools hijack Freelinking (it's an option). And configure the rest as desired.


Voila! A Drupal Wiki.


I will be putting it onto drupal.org presently.

Saturday, 21 January 2012

Stable Field Value Extraction module released

Okay, after weeks of nobody complaining about any aspect of my field_extract module I have finally got around to issuing the code as the full stable version. Hurray.

Now because I'm lazy I use Eclipse for development purposes - I know, I know, how can I be a proper developer if I don't use Linux and Vim? Well, I don't. I was using command line before you were born (unless you were born before 1983). Been there, done that.

However Eclipse and Drupal Git are strange bedfellows, and it can take a bit of work learning how they can be made to work together.

Getting Drupal repos cloned locally isn't too much of an issue once you've got your SSH keys sorted out, and for cloning you can happily use http.

Pushing upstream is another matter entirely (and you will to need to use just Push... instead of Push upstream... until you get it sorted out and configured). If you try using http you may well hit a brick wall, just as I did. the trick is to use git+ssh for your protocol, and it'll work nicely. One thing, which is obvious unless you forget it, is to include Add all tags spec if you are uploading tags as well as branches. Ahem.

Hopefully it won't be so long before my next posting - I have a fun new website specifically for developers coming up. I think you're going to like it, it provides a service that all developers need from time to time, and there is only one website I've found that fulfils the need, and not as well as my version. It's written in D7 of course, leveraging it as a development framework rather than a CMS.

And with that enigma, I'll leave you.

Thursday, 15 December 2011

MD5s as IDs

While there is the chance of duplication it can be handy to use MD5s for creating a "unique" ID for strings. I had this in my current project but I've done it before and there is a potential problem which is more likely than duplicate IDs.

There is a chance that you'll get an MD5 that begins with a zero and, potentially even worse, one that begins with a zero and is all decimal numeric (does not contain a-e digits).

In this instance, with the loose typing of PHP, you might find your MD5 gets converted to a number and loses its leading zero (or zeroes). In which case it's useless as an ID and it will take you a very long time to track it down. I know the first time it happened to me it took me a couple of days.

But there is a very simple solution, when you create your MD5 do an immediate search and replace to change all zeroes into 'g'.

$id = str_replace('0', 'g', md5($source));

Now you can be sure you will never lose your leading zero, because there isn't one.

(By the way, after 12 weeks my field_extract module has received no complaints or bug reports so I shall be promoting it to a full version.)

Wednesday, 16 November 2011

Ssssh

I've not posted recently because my current job involves Drupal 6 so I've done virtually no D7 work for a while. However I do have a new set of modules for developers coming soon which will be in both D6 and D7 varieties.

Essentially it's a system that does a similar job to CTools plugins but is lightweight and standalone. It's very good for de-coupling dependent custom modules, essentially very simple but very versatile.

There's a core module that provides the API (a very small module indeed) and then some other modules that demonstrate how to use it and provide handy facilities at the same time.

Hopefully I'll have that out by Christmas. I'm also happy to say that my field_extract module is doing very nicely  in the module usage charts currently standing at 99 sites.

Monday, 26 September 2011

Automatic file download

I have a personal project I'm working on which requires an automatic download link. You know the sort of thing - like you get on SourceForge: "Your file will download in x seconds". And then the file download dialog pops up.

All the solutions for this are JavaScript - and if you want a countdown then JS is the way to go. But I didn't want JavaScript.

The basic part of the trick isn't limited to Drupal at all, you just HTML:

<meta http-equiv="Refresh" content="1; URL=http://www.yoursite.com/system/files/downloadfile.ext" />

So here, after one second, the page refreshes - except it's a file to be downloaded, so your browser does the right thing and gives you a download dialog box instead.

Easy.



Sunday, 11 September 2011

field_extract module in beta

EDIT: Now out of beta. Fully implemented.

EDIT: You can now get the module from http://drupal.org/project/field_extract and it works properly with Drush.

My incredibly useful field_extract module is now available on drupal.org. I am slightly embarrassed because something went wrong in the project creation process so the actual URL is:

http://drupal.org/project/1158878

And when you download it the module comes inside another folder "1158878". In fact this will work just as it comes, you'll just get the folder 1158878 in your modules folder with field_extract inside that.

If you're competent you can extract the inner "field_extract" module and get rid of the outer 1158878 folder but, as I say, it should work out of the box anyway. (I may get around to re-uploading it properly at some point but I can't wait any longer to get it out to you.)

So what does it do? For a start, this is only a developer's module. It does nothing by itself and should only be downloaded if requested by another module. But what it does do is provide a couple of functions that make it much easier to extract field data from entities.

The project page provides clear instructions on how to use it.

Enjoy.

Wednesday, 7 September 2011

Reducing the footprint

Sorry I haven't blogged in a while, I have been working very hard on commercial D7 sites in my day job but haven't really come across anything spectacularly D7 I wanted to talk about.

So here's something unspectacular but quite important, and applies almost as much to D6 as D7.

Every module eats memory. Every x.module file (for enabled modules) gets loaded for every access (well, let's ignore caching). So anything that can be done to reduce the files loaded (size in this case) can only be a good thing. (Back in the day I wrote code for machines with 128K of memory of which 20K might be used for the screen, and another 32K for the OS - in those days you really had to think about keeping code as compact as possible.)

Drupal uses hooks to gather information from modules, and then it stores this information in the database caches (or other tables), after which it no longer calls these hooks - unless the caches get cleared and it has to build the information again.

Hooks like hook_menu, hook_theme, hook_permission and so on. But these hooks need to be available in the x.module file - and yet they are only called infrequently.

Solution? Put a minimal hook in the x.module file which loads another file (say x.registry.inc) and then calls the actual hook code which is in there. Like this:

In x.module:

function x_menu() {
  module_load_include('registry.inc', 'x');
  return _x_menu();
}

And in x.registry.inc:

function _x_menu() {
  $items = array();


  $items['my/path'] = array(
    // my/path data  );


  return $items;
}

If a hook is called on pretty much every page there is no advantage in doing this. But if it's a hook that's called infrequently it's definitely worth it.

This is something I'd played with back in my D6 days but then stopped using. But then I saw another contributed module that was using it and thought "yep, I should be doing that". So I am and here it is.

hook_hook_info()

There is another solution using hook_hook_info() which allows you to define a file in which hooks can be found. This does not work for the majority of system modules because they use customised hook-calling methods. Only one system module - Tokens - has it defined so token code can be located in x.tokens.inc.

However the Block module only uses standard hook-calling functions and you could specify a file for block management using hook_hook_info_alter(); I wrote something about this here.