Skip to content

Creating and Working With XML Forms

Daniel Aitken edited this page May 30, 2019 · 8 revisions

The Islandora XML Forms module marries the functionality of the Drupal Form API with a custom-built XML Form Builder to generate Drupal forms that can be used to save XML metadata as a datastream appended to an object. While XML forms can be fully created using the XML Form Builder UI, most of its functionality is also available through APIs, hooks, and a defined XML structure that allows XML forms to be generated and integrated into Islandora solution packs programmatically. This guide is intended to cover both methods.


Table of Contents

Using XML Form Builder

Creating a new form

The form properties

The form element tree

Common form controls

Drupal form elements

Drupal form element reference chart

A few other notable options

Taxonomy Autocomplete

The CRUD system

Element CRUD settings

Common scenarios

Working Programmatically with XML Forms

Structure of an XML Form Definition

Basic XML form definition structure

The form definition properties element

Form element actions

The form properties element

Form children

Drupal Form API element types supported by XML forms

Making form elements repeatable

The interpreted Drupal form array

XML Form Hooks

Adding a form to the list of forms

Adding a form association to a form

Adding an XSLT transformation to the list of available transformations

Using Form Alter Hooks On XML Forms

Altering an initial ingest form with ingest steps

Altering a datastream 'edit' form

Narrowing the scope of the form alteration

Making the actual alteration


Using XML Form Builder


XML Form builder is quite possibly the most intimidating part of Islandora. It is an advanced tool intended to provide the most unlimited level of flexibility possible in creating forms Islandora can use to create, store, and edit metadata; as such, it contains a wealth of controls whose function may be difficult to interpret at first, second, or even fifth glance. The purpose of this section is to hopefully impart enough information to the reader to get started with building forms using the XML Form Builder, and deal with any unusual situations they may encounter.

It is extremely important to note that XML Form Builder does almost no validation at all. Form Builder will let you do almost anything, including configurations that are impossible to render or would otherwise produce Drupal and PHP warnings and errors. Handling every possible invalid situation in an XML form is about as monumental and pointless a task as they come; some validation may be added in the future but do not expect XML Form Builder to hold your hand.

Conventions used in this section

  • Bolded words or word pairs generally reference a configuration option or setting that can be manipulated.
  • Lower-case italicized words generally reference a Drupal form element type.
  • When the words "Create", "Read", "Update" and "Delete" are capitalized, the words refer specifically to their context within CRUD, and will likely contain language specifying settings to be applied to that CRUD action for the element in question.

Creating a new form

New forms can be created by navigating to admin/islandora/xmlform/forms/create on your site, entering in a form name, and clicking 'Create'.

A new form contains one element - "Root (form)". This is the top-level element of the resultant XML. By default it contains no properties aside from its type (form), and will need to be modified.

The main viewing pane of a new form displays the form in preview mode. Because it contains no elements, only the 'Submit' button is rendered.

Clicking on an element in the left-hand tree pane will change the main viewing pane to that element's properties editor.


The form properties

Before we add any elements to our resultant XML, we need to make sure our root element contains an expected set of properties. These properties can be set by clicking on 'Form Properties' on the upper left hand corner.

The properties form contains the following elements:

  • Root Element Name: the name of the root element (e.g. 'mods', 'eaccpf', etc.)
  • Namespace URI: The namespace to use for the root element, if necessary
  • Schema Name: An optional schema to validate against
  • Namespaces: A list of namespace prefixes and corresponding URIs to be used by the form (e.g. 'xsi', 'xlink', etc.)

At the very least, the root element should be changed from the default ChangeMe to a valid root element name defined by your form's schema. The namespace URI should likely be set as well.


The form element tree

The left-hand pane of the form builder contains a tree representing the tree of Drupal form elements that will be rendered. They take the form:

Identifier (type)

Where 'Identifier' represents the unique identifier given to this element, and 'type' represents the kind of Drupal form element this is, such as a textfield or a select box.

It is important to note that the tree represents a Drupal form structure and not an XML form structure. The tree is used to sort elements in a Drupal manner, as opposed to the elements' CRUD settings, which are used to sort the elements in an XML manner. This means, for example, that children within the tree may only be appended to elements Drupal considers to be valid as parents, most notably form, markup, tabs/tabpanel, fieldset, and tags/tag. You cannot, for example, create a textfield as a child to another textfield, as this doesn't make good HTML form sense.

Above the tree are four controls, allowing you to:

  • Add an element as a child of the currently-selected element,
  • Copy the currently-selected element,
  • Paste the currently-copied element as a child of the currently-selected element, and
  • Delete the currently-selected element.

Elements can be dragged around the tree, either to make them siblings or children of existing elements.


Common form controls

All form elements allow the following settings:

  • Type (required): the type of Drupal form element to render for this node.
  • Title: The label to appear for this element. Not required for Drupal form elements that don't take labels, like markup and tabpanel.
  • Description: The description to be set for this element. Again, not required for Drupal form elements that do not render descriptions.
  • Default Value: The value to place in the Drupal form element if the corresponding Read action doesn't return an element.
  • Required: Whether or not Drupal should make a fuss if the user tries to submit the form without filling out this element.

Drupal form elements

When creating XML forms, it is extremely important to have a good understanding of the Drupal Form API. Before you even begin, it's a very good idea to take a look at this chart, and some of the concepts described in the sections below it:

Drupal Form API Reference Guide

Along the columns of the table you'll see names of form element types, some of which may already be familiar to you. Each row represents an attribute that applies to it. In Drupal, attributes that are meaningful to the Form API are preceded by hashes (#) to differentiate them from attributes that might be meaningful to other modules in other ways - which, of course, XML Forms uses many of.

Not all of these elements are useable by XML Form Builder, so here's a handy reference chart.

Drupal form element reference chart

Note that in the "Typical CRUD" section below, X's are used to represent CRUD options that should be turned off; e.g., CRXD for "Create, Read and Delete on, and Update off", or CXXD for "Create and Delete on, and Read and Update off".

Name Description Renders As Typical CRUD Notes
fieldset A frame that can surround form elements and be collapsed to clean up the display of the form A titled frame surrounding elements XXXX if the fieldset is purely cosmetic (XML created from children of the fieldset will use the next available XML parent), or CRXX to have the fieldset create an XML element with potential children Use Collapsible and Collapsed in "Advanced form controls" to allow the fieldset to be collapsible and to default to collapsed, respectively.
form The root element of the form A Drupal form XRXX - the root will be created by virtue of the form's properties, and only Read actions are generally required The only element with the form type should be the root element
markup An element that exists as part of the form definition only, and is otherwise not rendered Nothing - children of markup elements appear to be rendered in Drupal as siblings of the markup element CRXX to have the markup element create an XML element with potential children, or CRUX to have the markup element create an element automatically populated with content using the "xml" Create action's Type markup elements are typically given child elements, and are used to help structure your element tree in a more XML-friendly way without changing the form's look inside Drupal. They can also be used to Create elements to which both value and attribute content can be appended via Updates
select An element containing predefined options A drop-down menu of options to select from CRUX Options must be set in the element's "More advanced controls" section. At least one option MUST be included in the Options array; otherwise your form will not function
tabs/tabpanel Repeatable series of multiple form elements A framed tab containing one or more elements, and a button allowing the user to add more tabs XXXX for the tabs element, as it is the Drupal-rendered part of the tabs/tabpanel combo, and CRXD for its child tabpanel element, so that when tabs are deleted the XML element and children tied to the tab goes with it tabpanel should always be the immediate child of tabs; elements that you would like to be repeatable can then be added as children of the tabpanel. Set a the Title of the tabs element to have it rendered in Drupal
tags/tag Repeatable series of single text fields A text field with a green plus beside it to allow multiple values to be added; values are appended using AHAH and can be removed via a red button that appears beside them XXXX for the tags element, as it is the Drupal-rendered part of the tags/tag combo, and CRXD for its child tag, so that when tags are deleted the element tied to the tag goes with it tag should always be the immediate child of tags and should contain no children. Set a the Title of the tag element to have it rendered in Drupal
textarea An area for entering large chunks of text A multi-column box for user text input CRUX Rows and Cols in "Advanced form controls" can be used to define the default size of the rendered textarea; be careful when playing with this
textfield A single line for entering a moderate amount of text A single line box for user text input CRUX The textfield is the meat and potatoes of your form; nothing particularly important to note here.

A few other notable options

You can see what types of elements each of these options apply to either by checking the Drupal Form API chart or by hovering the mouse over the option in Form Builder.

Under "Advanced form controls":

  • Disabled: Greys out the element and makes it inaccessible through regular browser input. This is generally done in situations where a more advanced form designer could toggle this option using Drupal form states.
  • Prefix and Suffix: Text or markup to add before or after an element when it is rendered in Drupal. This is often used to encapsulate a Drupal form element within <div> or other types of tags with specific attributes holding some kind of meaning to the current theme or other enabled modules.
  • Max Length: Allows you to limit the number of characters in a textfield.
  • Size: Sets the width of select and textfield Drupal form elements.

Under "More advanced controls":

  • Attributes: A set of attributes to add to the form element when it is rendered in Drupal.
  • Element Validate: A list of function names of validators to use for this element and/or its children. Drupal includes element_validate_integer and element_validate_integer_positive to confirm that an element contains an integer and a positive integer, respectively.
  • User Data: Used by some Drupal modules to add additional information to the element.

Taxonomy Autocomplete

The 'Autocomplete Path' field in "Advanced Controls" can be used to point to URLs providing autocomplete information. This includes the creation of Drupal taxonomy vocabularies whose terms are provided to the autocomplete.

A taxonomy that can be used for autocompletion requires two parts:

  • A taxonomy vocabulary (visit admin/structure/taxonomy/add to create one) that implements the standard "Name" field at the top level
  • A field inside that taxomony implementing the "Term Reference" field type

The term reference field can either point to a different taxonomy, or it can be self-referential. The simplest way to do this is to navigate to "Manage Fields" in the taxonomy vocabulary you're creating and add a new field, giving it a decently unique name, selecting "Term reference" as the field type, and "Autocomplete term widget (tagging)" as the field widget.

Note the Machine Name that's auto-generated as you fill in the label; this will be important later.

Upon saving this form, you will be asked what vocabulary this term reference should refer to. It's fine for this to be self-referential to the vocabulary it's in.

You will be asked to configure the field; the default settings are fine.

To add the autocomplete to a form:

  • Select either a textfield or tag type field
  • Under "Advanced controls", in the "Autocomplete path", type in "taxonomy/autocomplete/machine_name", where machine_name is the term reference field machine name you noted earlier.

To force validation for the autocomplete field:

  • Under "More advanced controls", in the "Element Validate" section, add taxonomy_autocomplete_validate.

The CRUD system

The CRUD (Create, Read, Update and Delete) system allows XML form builder to define actions to take whenever any possible task is performed with an XML form.

The individual letters in the CRUD acronym can be, unfortunately, a bit misleading; specific definitions are as follows, in an order that makes more logical sense:

Read actions

These are taken when XML Forms wishes to query for the value of an element or attribute. This happens when editing existing XML (so that the Drupal form can be populated with the element values) or before writing XML from a filled-out form (so that it can be determined whether or not a new element needs to be created).

Update actions

These are taken when XML Forms performs a Read action, and querying the path configured for the Read action returns an existing element or attribute. The value from the existing element or attribute (including empty values) is replaced with the value defined by the update action, which it pulls from whatever is in the corresponding Drupal form element if possible, or that element's #value attribute.

If the Drupal form element does not define a value (e.g. fieldsets and markup don't have values because they don't take user input, whereas a textfield very clearly allows a value to be entered by the user), no Update action should be defined for the element.

Create actions

These are taken when XML Forms performs a Read action, and querying the path configured for the Read action does not return an existing element. An element, attribute, or hard-coded chunk of XML (depending on the Create Type) is created at the Path point using the Value configured for the Create action.

In form logic, Create actions occur before Update actions; i.e., the Create action generates an element, and the Update action populates it with a value.

Delete actions

These are taken when XML Forms performs an update action where the value being updated is empty (i.e. an element once contained text, but the user edited the form and removed it).

These are also taken in two specific, very important cases:

  • when the 'delete' button beside a tag is clicked, and
  • when the 'x' button on a tab inside a tabpanel is clicked.

Because of this, it is important to create Delete actions for tag and tabpanel elements; otherwise, removing them will not actually remove the corresponding entry from the resultant XML.

In all three of these cases, the corresponding entry is removed from the resultant XML.

Element CRUD settings

XPath settings

All elements contain the following two settings to ensure that Form Builder narrows down the exact element being worked:

Path Context: The context XPath should start searching from when using the Path setting. This can be:

document: the document's root element.

parent: the parent of the current element.

self (Update and Delete only): the element or attribute found via the associated Read action. Only available in contexts where a Read action has been taken and a value has been found.

Path: an XPath representation of the path to the node the action should be taken on. The Xpath query will begin at the Path Context defined above. The path self::node() is often used to represent the element found using the Path Context itself.

Schema settings

The Create and Update actions define a Schema field, allowing you to define the schema used to validate the element or attribute itself (in the case of a Create action), or the value that element will contain (in the case of an Update action).

Create-action-specific settings

The Create action requires a couple of additional settings in order for Form Builder to understand what it should be adding to the resultant XML:

Type: The type of content we are creating in the XML from this part of the form. This can be either:

element: an actual XML element.

attribute: an attribute on the element found by querying the Create action's Path Context/Path.

xml: actual XML content to append to the resultant XML at the position found by querying the Create action's Path Context/Path.

Value: The value of the type that should be created. For each Type, the contents of this field should look like:

elementName for element types; this would create an<elementName/> element at the path found by querying the Create action's Path Context/Path, which can then be given content using an Update action.

attributeName for attribute types; this would create an attribute on the element found by querying the Create action's Path Context/Path, in the form of <foundElement attributeName=""/>.

<hardCodedXML hardCodedAttribute="hard_coded_value">%value%</hardCodedXML> for xml types; this would append the exact XML written there to the resultant XML on the element found by querying the Create action's Path Context/Path element. Place the exact text "%value%" at the point in the XML where you would like the corresponding Update action to place its value. Importantly, this can be used to nest XML elements without the need for multiple Drupal form elements, e.g. <parent><child>%value%</child></parent>.

Common scenarios

Adding an attribute to an element

  1. Create an element
  2. Give the element Create, Read and Update actions
  3. Set the Create Type to 'attribute'
  4. Set the Read Path Context to the 'parent' and the Read Path to @attributeName

Adding both a value and an attribute to an element via user input

For example, you may want to have the user populate the value of an element, but also set its authority attribute. To accomplish this:

  1. Create a markup, tabs/tabpanel, or fieldset element using only a Create action
  2. Give that element two children, one for the element value and one for the element attribute
  3. Let the value element child Read and Update from and to the parent. Do not give it a Create or Delete context
  4. Let the attribute element be created as a standard attribute element

Applying a user-defined attribute to a sibling element

For example, a <parent> element may have a <child> with a value, as well as a user-defined attribute on the <child>.

  1. Create an element that can contain children, like a fieldset or markup
  2. Set the element's Create and Read actions to Create and Read from <parent>
  3. Create a child of <parent>. Let it Create and Read from <child> and Update it with a value
  4. Create a second child of <parent>. Let it Create, Read from and Update an 'attribute' Type, from the Path Context of 'parent', with a path of 'child/@attributeName'

Creating a hidden element with static content

For example, you may want to append non-configurable rights information to all XML created using your form.

  1. Create an element and give it the markup type so that it will be invisible to the user
  2. Give the element a Create action, and give it Read and Update actions as well so that additional elements are not generated when the form is edited
  3. Set the Create action's Type to 'xml'
  4. Set the Create action's Value to the exact XML you wish to add, e.g. <accessCondition>Here is some rights information</accessCondition>

Adding a markup element with display text

In almost all cases, it's preferred to add descriptive text to form elements using the Description property of elements. However, there may be situations where you wish to add descriptive text to the form where the Description would not suffice - for example, describing the contents of a fieldset that has Collapsed and Collapsible checked, or explaining the content your markup element will append to the form. In this case:

  1. Create an element and set its Type to defaultable_markup
  2. Set the Default Value to the markup text you would like to display
  3. If the element is only for display purposes, ensure the CRUD options are all left unchecked. Otherwise, Create and Read should be set.

Working Programmatically with XML Forms


Structure Of An XML Form Definition

XML form definitions are a modified XML versions of Drupal forms that contain additional elements recognized by the XML Forms module as being pertinent to XML metadata generation and modification. These XML forms are translated into Drupal form arrays when a user attempts to ingest or edit a datastream with an appropriate form association.

This guide skips over large chunks of required and otherwise valid XML form elements and properties in the name of simplicity and organization. If you'd like to follow along with this guide using an actual complete form definition, navigate to 'admin/islandora/xmlform' on an Islandora installation and export one of the forms there.


Basic XML form definition structure

<?xml version="1.0"?>
<definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3">
  <properties/>
  <form>
      <properties/>
      <children/>
  </form>
</definition>

The form definition properties element

The form definition properties element defines global properties of the form, and generally contains the following elements:

<properties>
    <root_name>The root element of the XML metadata you wish to generate.</root_name>
    <schema_uri>An optional schema URI to use for this form.</schema_uri>
    <namespaces default="default namespace URI">
        <namespace prefix="namespace_prefix">URI to use for this namespace</namespace>
        <!-- There can be multiple of these -->
    </namespaces>
</properties>

Form element actions

Form elements that represent XML elements that will ultimately go into your XML metadata have four #actions properties - create, read, update and delete, that can be manipulated to change what happens when one of those four actions are taken on the form:

<element name="elementName">
    <actions>
        <create>
            <context>The context from which to create this element (generally parent).</context>
            <path>The xpath to the node when it is being created (generally self::node()).</path>
            <type>The type of node to create (element, attribute or xml).</type>
            <value>The value of the node (an XML snippet if the type is xml, or the element name if it is an element).</value>
        </create>
        <read>
            <path>The xpath to the node when reading it from the form (generally a namespaced version of the node, e.g. mods:title).</path>
            <context>The context from which to read the element (generally from the parent).</context>
        </read>
        <update>
            <path>The xpath to the node when updating it on the form (generally self::node()).</path>
            <context>The context from which to update the node (generally self).</context>
        </update>
        <delete>
            <!-- This field is generally left with the value NULL, as no output is required from a deleted node. -->
        </delete>
    </actions>
</element>

The form properties element

The form properties element represents the properties of the top-level element of your form, and should include an <action><read><read/></action> entry, as well as <type>form</type>.


Form children

Form children are structured similarly to a Drupal form array, minus the hashes at the beginning of properties:

<children>
    <element name="elementName">
        <properties>
            <type>The Drupal Form API element type</type>
            <!-- Additional Form API properties can go here. -->
            <actions>
                <!-- Actions, as described above, can be placed here. -->
            </actions>
        </properties>
        <children>
            <!-- Additional child elements underneath this element can go here. -->
        </children>
    </element>
</children>

Drupal Form API element types supported by XML forms

Not all Drupal Form API element types work correctly on forms. Generally, XML forms are limited to the following types, although other types have been known to work:

Type Description
form This should be reserved for the form itself.
textfield A single line of text.
textarea A scrolling, manipulateable text box.
select A drop-down select box. Requires #options to be set.
hidden Used to set hidden properties or nodes.
markup Generally used in XML forms to designate an invisible form node that has no value but has children, e.g. the titleInfo node in MODS titleInfo/title.
fieldset Used in the same way as markup, but in a way that allows the section to be visible on the form.
tabs and tabpanel Used together to create repeatable sections of elements (see "Making form elements repeatable" below).
tags and tag Used together to create single repeatable elements (see "Making form elements repeatable" below).
creative_commons A custom Islandora XML Forms type that allows for the creation of Creative Commons form elements.

Making form elements repeatable

Single elements:

Use a parent tags element representing the node title, with a child tag element containing all the XML form actions, e.g.:

<element name="repeatableElement">
    <properties>
        <type>tags</type>
        <description>Repeatable element description.</description>
        <title>Repeatable element title.</title>
        <access>TRUE</access>
    </properties>
    <children>
        <element name="0">
            <!-- The element is given the name of '0' here as a placeholder; it doesn't actually need a specific name. -->
            <properties>
                <type>tag</type>
                <actions>
                  <!-- Relevant actions go here. -->
                </actions>
                <!-- The rest of the standard repeatable elements go down here. -->
            </properties>
        </element>
    </children>
</element>

Multiple elements grouped together by a parent node:

Use a parent tabs element representing the repeatable elements' parent, with a child tabpanel element containing all the child elements, e.g.:

<element name="repeatableSection">
    <properties>
        <type>tabs</type>
        <description>Description of what goes in this section of form elelements.</description>
        <title>A set of tabs</title>
        <access>TRUE</access>
    </properties>
    <children>
        <element name="0">
            <!-- The element is given the name of '0' here as a placeholder; it doesn't actually need a specific name. -->
            <properties>
                <type>tabpanel</type>
                <access>TRUE</access>
                <actions>
                    <!-- Relevant actions for this parent node go here. -->
                </actions>
            </properties>
            <children>
                <!-- The child elements being grouped together go here. -->
            </children>
        </element>
    </children>
</element>

Grouped together elements can be further nested underneath grouped together elements using the same method.


The interpreted Drupal form array

Note that this does NOT represent a complete Drupal form array, but simply serves to show where the above XML form elements fall into the Drupal $form array.

array(
  '#type' => 'form',
  // Other global form properties can be found up here.
  '#actions' => array(
    'create' => NULL,
    'read' => 'Top-level xpath',
    'write' => NULL,
    'delete' => NULL,
  ),
  'child_1' => array(
    '#type' => 'textfield',
    '#description' => 'Description',
    '#default_value' => 'value',
    // Other Drupal FAPI elements go here.
    '#actions' => array(), // Actions for this element go here.
  ),
  'child_2' => array(
    '#type' => 'fieldset',
    // Other Drupal FAPI elements go here.
    '#actions' => array(), // Actions for this element go here.
    'subchild' => array(
      '#type' => 'select',
      '#options' => array(
        'associative array' => 'of options',
      ),
      '#actions' => array(), // Actions for this element go here.
      // Other Drupal FAPI elements go here.
    ),
  ),
  // The rest of the form elements are down here.
  // Additional form properties can be found here.
);

XML Form Hooks

As of writing, Islandora XML Forms supports the use of three hooks for programmatically adding forms, form associations, and XSLT transformations to the XML Forms module.

Hooks in this section and throughout assume they are being created in a module called 'my_module'.

Note that in all cases asking for a path below, it is highly recommended to store XML and XSLT files in your module's 'xml' and 'xslt' folders, and use drupal_get_path() to find the path to the module containing the file in question, e.g.:

$path = drupal_get_path('module', 'my_module');
$path_to_xml = "{$path}/xml/xml.xml";
$path_to_xslt = "{$path}/xslt/xslt.xslt";

Adding a form to the list of forms

Hook: hook_islandora_xml_form_builder_forms()

Usage:

function my_module_islandora_xml_form_builder_forms() {
  $forms = array();
  return array(
    'Form Name' => array( // This unique form name will show up as the form title in admin/islandora/xmlform.
      'form_file' => 'path/to/form/definition/file.xml', // This should be the full path to the form definition.,
    ),
  );
}

Adding a form association to a form

Hook: hook_islandora_xml_form_builder_form_associations()

Note that hook_islandora_content_model_forms_form_associations() accomplishes the same thing, but is deprecated and should not be used.

Usage:

function my_module_islandora_xml_form_builder_form_associations() {
  return array(
    // By convention, the unique name should start with your module's name.
    'my_module_unique_association_name' => array(
      'content_model' => 'content_model:pid',
      'form_name' => 'Form Name', // This is defined above using the islandora_xml_form_builder_forms hook.
      'dsid' => 'DSID',
      'title_field' => array('titleInfo', 'title'), // An array of the elements required to go through in order to get to your desired title.
      'transform' => 'transform.xslt', // This is defined below from the xml_form_builder_get_transforms hook. Use 'No Transform' to pass on this option.
      'template' => 'path/to/template.xml', // Use FALSE for no template.
    ),
  );
}

Adding an XSLT transformation to the list of available transformations

Hook: hook_xml_form_builder_get_transformations()

Usage:

function hook_xml_form_builder_get_transforms() {
  return array(
    'transform.xslt' => 'path/to/transform.xslt', // This transform name is used by the form association hook.
  );
}

Using Form Alter Hooks On XML Forms

Because Islandora XML Forms are rendered using Drupal's Form API, they are able to be manipulated using Drupal form alteration hooks. The simplest way to do this is using hook_form_FORM_ID_form_alter().


Altering an initial ingest form with ingest steps

function my_module_form_xml_form_builder_datastream_form_alter(&$form, &$form_state, $form_id) {
  /**
   * Form alterations go here.
   */
}

Altering a datastream 'edit' form

function my_module_form_xml_form_builder_ingest_form_alter(&$form, &$form_state, $form_id) {
  /**
   * Form alterations go here.
   */
}

Narrowing the scope of the form alteration

A module that implements hook_form_xml_form_builder_edit_datastream_form_alter() or hook_form_xml_form_builder_ingest_form_alter() will make alterations to any ingest or edit form. To narrow down the selection, several array elements stored in the $form_state can be used to filter the form alteration hook, e.g.:

When altering an initial ingest form with ingest steps:

Form State Element Description
$form_state['islandora']['step_storage']['xml_form_builder_metadata_step']['association']['id'] The key of a form association hook implementation in the database, such as 1 in the example above.
$form_state['islandora']['step_storage']['xml_form_builder_metadata_step']['association']['VALUE'] One of the values from an association hook implementation, such as form_name, content_model or dsid.
$form_state['islandora']['shared_storage']['parent'] The PID of the parent collection.

When altering a datastream 'edit' form:

Form State Element Description
$form_state['association']['id'] The key of a form association hook implementation in the database, such as 1 in the example above.
$form_state['association']['VALUE'] One of the VALUEs from an association hook implementation, such as form_name, content_model or dsid.
$form_state['association']['datastream'] The IslandoraFedoraDatastream object currently being manipulated.

Using these and other $form_state values, you can narrow down your form alteration like so:

/**
 * Makes form alterations to any datastream 'edit' form using the association with the ID '1' in the database.
 */
function my_module_form_xml_form_builder_edit_datastream_form_alter(&$form, &$form_state, $form_id) {
  if (isset($form_state['association']['id'])) {
    if ($form_state['association']['id'] == 1) {
      /**
       * Form alterations go here.
       */
    }
  }
}

Making the actual alteration

Because of the broad level of crossover between XML forms and Drupal forms, nearly any alteration supported by the Drupal Form API is also supported by XML forms. Some examples:

function my_module_form_xml_form_builder_datastream_form_alter(&$form, &$form_state, $form_id) {
  /**
   * Removing an element from the form.
   */
  unset($form['language']);
  /**
   * Adding the '#collapsible' property to a fieldset.
   */
  $form['physicalDescription']['#collapsible'] = TRUE;
  /**
   * Adding #options to a select field.
   */
  $form['typeOfResource']['#options']['new option'] = 'new option';
  /**
   * Rendering an element invisible and giving it a value.
   */
  $form['accessCondition']['#type'] = 'value';
  $form['accessCondition']['#value'] = 'Copyright Information';
  /**
   * Using a form state to hide an element based on another element's value.
   * In this case, we're removing the 'country' element if the selected continent is Antarctica.
   */
  $form['subject']['hierarchicalGeographic']['country']['#states'] = array(
    'invisible' => array(':input[name="subject[hierarchicalGeographic][continent]"]' => array('value' => 'Antarctica')),
  );
}

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

Clone this wiki locally