Skip to content

Programming Solution Packs

William Panting edited this page Sep 17, 2015 · 16 revisions

Solution Packs.

Islandora Solution Packs provide the framework for the ingestion, organization, and display of digital objects in a Fedora repository through a front end Drupal web interface.

We will be using a fictional module called islandora_example, and an equally fictional content model called islandora:exampleCModel for our samples. We are assuming the programmer already knows the function and composition of a Content Model and has basic PHP and Drupal programming skills for these examples.

Ingestion:

The ingestion of a digital object may be simple, or complex. In the simplest case a file is uploaded and stored as the primary datastream: at ingest time the user is given the opportunity to enter metadata about that digital asset, and assign that object to one or more collections.

Ingestion can be made more complex in one of two ways – More than one digital asset can be ingested to form a single Fedora object, or more commonly, the uploaded digital asset may be used to generate derivative datastreams.

A form must be associated with the content model being used to describe the behaviour of the object being created to allow the creation of metadata on ingestion. This is accomplished with hook_islandora_content_model_forms_form_associations()

function islandora_example_content_model_forms_form_associations() {
 return array(
   'islandora_example_mods_form' => array(
     'content_model' => 'islandora:exampleCModel',
     'form_name' => 'Example MODS form',
     'dsid' => 'MODS',
     'title_field' => array('titleInfo', 'title'),
     'transform' => 'mods_to_dc.xsl',
     'template' => FALSE,
   ),
 );
}

This hook will run on module installation and can be run again by selecting Solution Packs, under Islandora in the Drupal admin panel. This form will now display as the first step of the ingest process for an object being described by the the islandora:exampleCModel content model.

Most new Fedora objects will be built around an existing digital asset. The existing asset will be uploaded from a form supplied by the hook_islandora_ingest_steps() function. The following implementation displays the islandora_example_upload_form, which can be found in the includes/upload_form.inc file of the islandora_example module. In this case we are adding a single additional form, which could have the ability to add one or more uploaded file, but any number of additional forms can be shown to complete a custom ingest process.

 islandora_example_islandora_exampleCModel_islandora_ingest_steps() {
  return array(
    'islandora_example' => array(
      'weight' => 10,
      'type' => 'form',
      'form_id' => 'islandora_example_upload_form',
      'module' => 'islandora_example',
      'file' => 'includes/upload.form.inc',
    ),
  );
}

Once the supplied data has been entered, either as uploaded files or manually entered data, it may be necessary to create derived datastreams. Derivatives are datastreams created using the supplied datastreams as input. A common examples would be thumbnail images created from supplied image files.

Derivative creation is defined by hook_CMODEL_PID_islandora_object_ingested() The function below takes the partially complete fedora object being constructed and passes it to a function called islandora_example_create_all_derivatives(). We are in the process of adopting a new derivative framework. See the api.php.

islandora_example_islandora_exampleCModel_islandora_object_ingested($object){
  module_load_include('inc', 'islandora_example', 'includes/derivatives');
  islandora_example_create_all_derivatives($object);
}

It is the responsibility of the programmer to validate and persist the derived datastreams.

Display

In the absence of any custom code to cause Islandora to behave otherwise, objects are displayed by the islandora_view_object function. This gives us only very basic information about the object.

To cause objects of a given Content model to be displayed in anything other than the default mode one of two things must happen. Either an existing viewer from another module must be called, or code must be written to change Islandora’s default behaviour.

Properly configured existing viewers can be listed and configured within the admin section of your solution pack.

module_load_include('inc', 'islandora', 'includes/solution_packs');
$form += islandora_viewers_form('islandora_example_viewers', 'some_mimetype');

If a custom view is required the islandora_example.module page hook_CMODEL_PID_islandora_view_object must be implemented. The code which invokes this hook will supply an IslandoraFedoraObject representing the object being displayed.

Please note that great care should be taken when changing the behavior of existing implementations as backwards compatibility is critical.

One possible approach is to have a theme function registered with hook_theme telling Drupal the name of the theme function where it is located. The theme function will create an array of variable to passed to a .tpl file which will then expose the object. The Content Model hook function can then call a theme function in the file identified hook_theme(theme/theme.inc in this example) and attempts to find a function matching the pattern identified as a parameter of hook_theme. If theme.inc has a function called islandora_example_preprocess_mymodule, that function will allow you to extract and interpolate object data to pass on to the .tpl file for display. The preprocess hook is not an Islandora hook, it supplied by Drupal.

Example:

function my_example_theme($existing, $type, $theme, $path) {
  return array(
    'mymodule' => array(
      'file' => 'theme/theme.inc',
      'template' => 'theme/myexample-show',
      'pattern' => 'mymodule__',
      'variables' => array('islandora_object' => NULL),
    )
  );
}
islandora_example_islandora_exampleCModel_islandora_view_object($object, $page_number, $page_size) {
  $output = theme('mymodule', array('islandora_object' => $object));
  return array('' => $output);
}

We have learned over time through hard experience and example of core Drupal that it is much easier to work with Drupal’s renderable arrays rather than fully rendered markup created through the the themeing system at this level. So the preferred approach is now to return renderable arrays from islandora_view_object so that they are easily modified in islandora_view_object_alter. Many core solution packs still use the method above however as the cost to change their workings is very high.

Organization

Fedora objects do not reside within a conventional file structure, although they may appear to. Each Fedora object has a RELS-EXT datastream which expresses that object’s external relationships. The REL-EXT will define, amongst other things, the object’s Content Model and the collections of which it is a member.

Fedora Objects may be members of one or more collections. When an object is added to an additional collection the relationship with that collection is noted in the object’s RELS-EXT stream but the base object is not duplicated.

Relationships associated with an object’s datastreams are stored in RELS-INT. This allows an object’s internal datastreams to have their own URI’s and to have relationships between them clearly expressed.

Both REL-EXT and RELS-INT are expressed in RDF, and both are searchable using either SPARQL or ITQL through the resource index.

Multiple Content Models

In general multiple content models are not well supported in Islandora. Our CModel use was originally for traditional typification and while mixin style use is possible and exists in some places supporting it is not a priority. Some of the issues implementing this are with (display) and derivative collision.

⚠️ This wiki is an archive for past meeting notes. For current minutes as well as onboarding materials, click here.

Clone this wiki locally