I feel no shame in the sense of accomplishment that I got from learning how to make a solution pack module for Islandora!
Working at the DSU has given me the chance to explore the possibilities and push the boundaries of what I'm capable of. It was great because I came out of the process learning a lot more about the mechanics behind Islandora, Fedora and Drupal and how the existing processes faciliate the lifecycle of a digital object in the system.
To me, a solution pack module is like the blueprint used to set up a digital object factory in Islandora city™. The module specifies what objects to produce, how they should look and what data types and packages are associated with an object. This is all done the programming languages understood by Drupal and Islandora.
When it is installed, the Living Research Lab solution pack designed for the DSU creates 5 collections (Births, Mice, Protocols, Publications, Experiments) that is used to manage and add objects. The objects in each collection are ingested using specially designed forms in Darwin Core Standard (Mouse, Birth, Protocol, Experiment, Publication, and Data Session). What I've done is a really basic setup. You can and should add hooks and configure so much more to streamline the way your data is ingested, processed and accessed.
The github link for the Living Research Lab Solution Pack can be found here: https://github.com/digitalutsc/islandora_solution_pack_livingresearchlab
I should note that so far module works well in development mode, but it is in definite need of debugging and refining before it can actually be used in a production environment.
It began with XML
In one of our projects we needed to build custom XML forms to store metadata in Islandora. We soon realized that customization would be really important in order to automate some of the actions and to improve usability. Building a solution pack was the next logical step to explore customization.
Tips to get started
- Look at other solution packs! When you're starting with nothing, it helps to look at something. What I did was look at simple examples, going through and breaking down the code line by line, and trying to trace the lines in the code and when each step is called in Islandora.
- Draw. Creating diagrams made it easier for me to make connections between different the little parts that contribute to the module's functionality
What I used*
- Sandbox Virtual Machine Image (http://islandora.ca/downloads) - the testing environment
- Creating a shared folder from a local folder to the VM - that way I could modify module on my desktop
- Drupal's Devel module (https://www.drupal.org/project/devel) - Selected Display $page array, Display machine names of permissions and modules, Kromo backtrace). Used to debug and quickly re-install the module
- Islandora Documentation (https://github.com/Islandora/islandora/wiki/Working-With-Fedora-Objects-Programmatically-Via-Tuque)
- Sublime Text - the code editor
- Module Examples - a reference, comparing across multiple solution packs when you're trying to start your own helps
- Islandora Porcus (https://github.com/ajstanley/islandora_porcus) - basic and heavily commented
- Biological Entity (https://github.com/giancarlobi/islandora_solution_pack_biological_entity) - usage of Darwin Core and multiple content models
- Biodiversidad (https://github.com/DiegoPino/islandora_solution_pack_redbiodiversidad-7.x-dev) - lots of customization and uses Darwin Core
Update 2014-09-11 - other useful resources:
- PHP code checker: http://phpcodechecker.com/
- Documentation: https://github.com/Islandora/islandora/wiki/Programming-Solution-Packs
The start of something
The first step I took to understand module building was to create map to see where and how variables and files were being referenced. What I soon discovered is that most files, functions and variables are initially called from the .module file. The .module file is the main file that contains the configuration and hooks and variables. It's in there where you add hooks, and where you wield a lot of power in if you know what you're doing.
The map below is a neater version to my original sketch. It lists all of the hooks from the .module file and what files they refer to. It also shows what component it affects in the Islandora system architecture.
Here are my original notes that went with the map when I was going through the Islandora Porcus module. I wrote out the names of all of the files contained in the module and within those files I wrote out all of the function names and tried to figure out what they did:
- islandora_porcus.install > install and uninstall the module under Modules, module_load_include draws from islandora modules usually .inc
- islandora_porcus.module > everything comes together > SEE BELOW
- islandora_porcus.info > info under Modules
- ./css/slandora_porcus.css > for Object View Page called from .tpl.php
- ./images/piggie.png > for Object View Page, called from derivatives.inc
- ./includes/derivatives.inc > SEE BELOW
- islandora_porcus_upload.form.inc > upload form
- islandora_porcus.admin.inc > admin config page when you go to Islandora > Click on Module
- ./js/islandora_porcus.js > for Object View Page from .tpl.php
- ./theme/islandora-porcus.tpl.php > Object View Page, when you create a new object this is what appears
- ./xml/islandora_porcus_form_mods.xml > the form!
Questions: So content models customized for your own datastreams and way you want things to be what is a hook even - when you go to a page something (function, template) is activated?
function islandora_porcus_menu() > the admin menu item, getting things started and loading .admin.inc
function islandora_porcus_theme($existing, $type, $theme, $path) > the Theme is the Template - the Object View Page
function islandora_porcus_preprocess_islandora_porcus(array &$variables) > sets up variables to be placed within the template (.tpl.php) files. From Drupal 7 they apply to templates and functions
function islandora_porcus_islandora_porcusCModel_islandora_view_object($object, $page_number, $page_size) > first content model association, if object is a Cmodel that you specify here
function islandora_porcus_islandora_porcusCModel_islandora_ingest_steps(array $configuration) > hooks ingest steps
function islandora_porcus_islandora_porcusCModel_islandora_object_ingested($object) > calls derivatives.inc
function islandora_porcus_islandora_xml_form_builder_forms() > load form
function islandora_porcus_islandora_content_model_forms_form_associations() > form association, for the form
function islandora_porcus_islandora_required_objects(IslandoraTuque $connection) > construct content model object, ingests it
function islandora_porcus_create_all_derivatives(FedoraObject $object) > derivative spec for the .txt uploaded object, potential file conversion
function islandora_porcus_transform_text($input_text) > for the .txt uploaded object
function islandora_porcus_upload_form(array $form, array &$form_state) > http://localhost:8181/islandora/object/porcus%3Atest/manage/overview/ingest this page to upload the file
function islandora_porcus_upload_form_submit(array $form, array &$form_state) > submit into what datastream
islandora-porcus.tpl.php connects to things from preprocess theme
Even if you don't want to create a module from scratch, this should help you modify existing modules in little ways that could make using Islandora easier. Feel the power.
[*] My secret wish for tutorials is to list tools and strategies for troubleshooting. That would help immensely.