Skip to main content

Linking to revisionable files in Drupal 7

Our client had some very specific requirements for their project. They needed to be able to insert links to files and they needed to keep the same URL for those files even if the file changed. Those familiar with Drupal will know that by default, Drupal will suffix the newer version of the filename with _0, _1 etc which obviously breaks the URL. Here's how we worked around the issue...

by tim.eisenhuth /

The challenge

Some of our clients deal with an enormous number of files. In particular PDF’s and Word docs. Alone, this is not a great challenge for Drupal. Using the Media, File entity and bulk upload modules we had most of the functionality we needed. However, there were some key requirements that complicated the issue.

1) Files must be revisionable - The client would quite often make updates to files and so needed to keep a history of the changes in the form of revisions. Further, the client would from time to time want to revert ( temporarily or completely) to a previous version of the file. Drupal node’s are no stranger to revisions but we found that at the time, File entities were not revisionable ( It seems that this has since been addressed ) . It looked like file entity was not the solution we needed.

 2) Links to a file must remain the same - For example, say the client has created a page and wants to link to a company policy. Let’s say it is at http://www.example.com/policy.pdf. The client uploads a newer version of this file with the same file name. Drupal by default will handle this by suffixing the filename with an underscore and a number. So policy.pdf becomes policy_0.pdf and so on. Basically the issue is that the filename itself has to be unique. This seemed to be the underlying issue we faced. File entity assumes a one to one relationship between “File” on disk, and the logical file element. Note: there is also a contrib module called Upload file replace which changes this default behavior and reverses the order of the file suffixing. So, for example, the latest file is always policy.pdf and the older versions are policy_0.pdf, policy_1.pdf etc

 3) Must be able to arrange files like in a file system - The client wanted to be able to create “folders” and to move files in and out of folders in order to organise their large variety of files. Because of the way Drupal manages files, it would be too complex to gives them acess directly to the file system. For example: If they moved a file, we would need to find some way to update Drupal’s file_managed table to reflect the change. Not impossible, but definitely complex and time consuming.

A possible solution...

Because the Media module’s Media Browser is powered by Views, I figured it would be simple enough to create my own View. As it turns out Media is quite welcoming in allowing you to add your own custom Views to the Media browser. However, the problem that we had was the interface for selecting a file to be inserted. Media handles this with some custom JS that does some Media-specific things, whereas we needed it to just return a link to the selected file.

After some playing around I decided that it was going to be too time consuming to get this running and was not even sure it was possible without hacking Views.

The solution

One thing I noticed is that if you have a file field on a node, and enable revisions on the node, Drupal will create a copy of the file field every time you create a new revision. This was basically the exact behaviour that we required. It made me think that a special node content type with a file field could be the way to go. Of course, there was still the issue that the new copy of the file will be suffixed with _0, _1 etc. To work around that I issue I used the contrib module Attachment links. This module provides permanent links to files attached to a node. It provides a URL such as http://www.example.com/node/123/attachment/newest where it will return the “newest” copy of the attached file (you configure which field on the node contains the file). It also provides some other URLs like /attachment/preferred, where you can specify a preferred version.

So I started work on building a custom module (http://github.com/timeisenhuth/file_manager) which provided a content type called “file_manager_file”. The content type has a title, body and a single file field which serve as a place for file metadata which also came in handy. Once I had enabled revisions the content type was ready to go.

There was still the problem of organising files. I looked at some file management solutions like Scald as well as IMCE’s file browser but again the problem I ran into was the assumption that every filename was unique. This simply wasn’t going to work. We needed to be able to move files around independent of the filename. Given that a file system is a simple hierarchy I decided that Taxonomy could be the solution. The module creates a “File manager” vocabulary and set's up permission for the client to be able to add, edit and manage terms within the hierarchy. It also adds a field to the file_manager_file node that referenced this vocabulary. The module also contains a WYSIWYG plugin (At the moment this plugin is specific to TinyMCE). The plugin provides a toolbar button that when clicked loads a popup window ( similar to Linkit ) with a View that shows a list of “file_manager_file” nodes, and has an exposed filter on the taxonomy field which shows the hierarch of the vocabulary. Each file is presented as a link and when the user clicks the link it insert’s the Attachment Link’s link into the field.

Conclusion

The module is not a perfect solution, it could definitely be improved with a better/smoother user experience. Being able to create new “Folders” (Terms) on the fly would be one example. Also I beleve I can remove the dependency on the Attachment links module and possibly expand the plugin to work with other WYSIWYG editors.

My experience working on this has lead me to start contributing to the Drupal 8 Media initiative as I believe that Drupal’s handling of media is an area that could have a positive impact for expanding Drupal. I am currently getting up to speed with the lates development and have started to contribute to the new Media entity module. Since Drupal 8 core and the Media module have already greatly improved file handling, I believe there is still potential for a WYSIWYG plugin that handles displaying and inserting links to files within a field.

Senior Developer