Drupal modules for browsing and managing Fedora-based digital repositories.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

467 lines
15 KiB

<?php
// $Id$
/**
* @file
* An example to define a simple field, widget, and formatter.
* A module could define only a field, only a widget, only a
* formatter, or any combination. Widgets and formatters must
* declare what kind of field they work with, which can be any
* existing field as well as any new field the module creates.
*/
//==========================================//
// DEFINING A FIELD
//==========================================//
/**
* Implementation of hook_field_info().
*/
function pidfield_field_info() {
return array(
// The machine name of the field,
// no more than 32 characters.
'pidfield' => array(
// The human-readable label of the field that will be
// seen in the Manage fields screen.
'label' => t('Fedora PID field'),
// A description of what type of data the field stores.
'description' => t('Store a reference to a PID in this site\'s Fedora repository.'),
// An icon to use in Panels.
'content_icon' => 'icon_content_text.png',
),
);
}
/**
* Implementation of hook_field_settings().
*/
function pidfield_field_settings($op, $field) {
switch ($op) {
// Create the form element to be used on the field
// settings form. Field settings will be the same for
// all shared instances of the same field and should
// define the way the value will be stored
// in the database.
case 'form':
$form = array();
$form['max_length'] = array(
'#type' => 'textfield',
'#title' => t('Maximum length'),
'#default_value' => is_numeric($field['max_length']) ? $field['max_length'] : 64,
'#required' => FALSE,
// Use #element_validate to validate the settings.
'#element_validate' => array('_pidfield_length_validate'),
'#description' => t('The maximum length of the field in characters. Must be a number between 1 and 255'),
);
return $form;
// Return an array of the names of the field settings
// defined by this module. These are the items that
// CCK will store in the field definition
// and they will be available in the $field array.
// This should match the items defined in 'form' above.
case 'save':
return array('max_length');
// Define the database storage for this field using
// the same construct used by schema API. Most fields
// have only one column, but there can be any number
// of different columns. After the schema API values,
// add two optional values to each column,
// 'views', to define a Views field
// 'sortable', to add a Views sort field
case 'database columns':
$columns['value'] = array(
'type' => 'varchar',
'length' => is_numeric($field['max_length']) ? $field['max_length'] : 64,
'not null' => FALSE,
'sortable' => TRUE,
'views' => TRUE,
);
return $columns;
// Optional: Make changes to the default $data array
// created for Views. Omit this if no changes are
// needed, use it to add a custom handler or make
// other changes.
case 'views data':
// Start with the $data created by CCK
// and alter it as needed. The following
// code illustrates how you would retrieve
// the necessary data.
$data = content_views_field_views_data($field);
$db_info = content_database_info($field);
$table_alias = content_views_tablename($field);
$field_data = $data[$table_alias][$field['field_name'] .'_value'];
// Make changes to $data as needed here.
return $data;
}
}
/**
* Custom validation of settings values.
*
* Create callbacks like this to do settings validation.
*/
function _pidfield_length_validate($element, &$form_state) {
$value = $form_state['values']['max_length'];
if ($value && !is_numeric($value)|| $value < 1 || $value > 255) {
form_set_error('max_length', t('"Max length" must be a number between 1 and 64.'));
}
}
/**
* Implementation of hook_field().
*/
function pidfield_field($op, &$node, $field, &$items, $teaser, $page) {
switch ($op) {
// Do validation on the field values here. The widget
// will do its own validation and you cannot make any
// assumptions about what kind of widget has been used,
// so don't validate widget values, only field values.
case 'validate':
if (is_array($items)) {
foreach ($items as $delta => $item) {
// The error_element is needed so that CCK can
// set an error on the right sub-element when
// fields are deeply nested in the form.
$error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
if (!empty($item['value'])) {
if (!empty($field['max_length']) && drupal_strlen($item['value']) > $field['max_length']) {
form_set_error($error_element, t('%name: the value may not be longer than %max characters.', array('%name' => $field['widget']['label'], '%max' => $field['max_length'])));
}
}
}
}
return $items;
// This is where you make sure that user-provided
// data is sanitized before being displayed.
case 'sanitize':
foreach ($items as $delta => $item) {
$pid_field_text = check_plain($item['value']);
$items[$delta]['safe'] = $pid_field_text;
}
}
}
/**
* Implementation of hook_content_is_empty().
*
* CCK has no way to know if something like a zero is
* an empty value or a valid value, so return
* TRUE or FALSE to a populated field $item array.
* CCK uses this to remove empty multi-value elements
* from forms.
*/
function pidfield_content_is_empty($item, $field) {
if (empty($item['value'])) {
return TRUE;
}
return FALSE;
}
/**
* Implementation of hook content_generate().
*
* Optional, provide dummy value for nodes created
* by the Devel Generate module.
*/
function pidfield_content_generate($node, $field) {
$node_field = array();
// Generate a value that respects max_length.
if (empty($field['max_length'])) {
$field['max_length'] = 12;
}
$node_field['value'] = user_password($field['max_length']);
return $node_field;
}
/**
* Implementation of hook_token_list()
* and hook_token_values().
*
* Optional, provide token values for this field.
*/
function pidfield_token_list($type = 'all') {
if ($type == 'field' || $type == 'all') {
$tokens = array();
$tokens['pidfield']['raw'] = t('Just the PID itself.');
$tokens['pidfield']['formatted'] = t('A PID with a hyperlink');
return $tokens;
}
}
function pidfield_token_values($type, $object = NULL) {
if ($type == 'field') {
$item = $object[0];
$tokens['raw'] = $item['value'];
$tokens['formatted'] = isset($item['view']) ? $item['view'] : '';
return $tokens;
}
}
//==========================================//
// DEFINING A FORMATTER
//==========================================//
/**
* Implementation of hook_theme().
*/
function pidfield_theme() {
return array(
// Themes for the formatters.
'pidfield_formatter_default' => array(
'arguments' => array('element' => NULL),
),
'pidfield_formatter_plain' => array(
'arguments' => array('element' => NULL),
),
);
}
/**
* Implementation of hook_field_formatter_info().
*
* All fields should have a 'default' formatter.
* Any number of other formatters can be defined as well.
* It's nice for there always to be a 'plain' option
* for the raw value, but that is not required.
*
*/
function pidfield_field_formatter_info() {
return array(
// The machine name of the formatter.
'default' => array(
// The human-readable label shown on the Display
// fields screen.
'label' => t('Default'),
// An array of the field types this formatter
// can be used on.
'field types' => array('pidfield'),
// CONTENT_HANDLE_CORE: CCK will pass the formatter
// a single value.
// CONTENT_HANDLE_MODULE: CCK will pass the formatter
// an array of all the values. None of CCK's core
// formatters use multiple values, that is an option
// available to other modules that want it.
'multiple values' => CONTENT_HANDLE_CORE,
),
'plain' => array(
'label' => t('Plain text'),
'field types' => array('pidfield'),
'multiple values' => CONTENT_HANDLE_CORE,
),
);
}
/**
* Theme function for 'default' example field formatter.
*
* $element['#item']: the sanitized $delta value for the item,
* $element['#field_name']: the field name,
* $element['#type_name']: the $node->type,
* $element['#formatter']: the $formatter_name,
* $element'#node']: the $node,
* $element['#delta']: the delta of this item, like '0',
*
*/
function theme_pidfield_formatter_default($element) {
//return $element['#item']['safe'];
$pid = $element['#item']['safe'];
if(!empty($pid)) {
module_load_include('inc', 'fedora_repository', 'api/fedora_item');
$item = new Fedora_Item($pid);
return fedora_repository_get_items($pid);
}
return null;
}
/**
* Theme function for 'plain' example field formatter.
*/
function theme_pidfield_formatter_plain($element) {
return strip_tags($element['#item']['safe']);
}
//==========================================//
// DEFINING A WIDGET
//==========================================//
/**
* Implementation of hook_widget_info().
*
* Here we indicate that the content module will handle
* the default value and multiple values for these widgets.
*
* Callbacks can be omitted if default handing is used.
* They're included here just so this module can be used
* as an example for custom modules that might do things
* differently.
*/
function pidfield_widget_info() {
return array(
// The machine name of the widget, no more than 32
// characters.
'pidfield_widget' => array(
// The human-readable label of the field that will be
// seen in the Manage fields screen.
'label' => t('PID Field widget'),
// An array of the field types this widget can be
// used with.
'field types' => array('pidfield'),
// Who will handle multiple values, default is core.
// 'CONTENT_HANDLE_MODULE' means the module does it.
// See optionwidgets for an example of a module that
// handles its own multiple values.
'multiple values' => CONTENT_HANDLE_CORE,
'callbacks' => array(
// Who will create the default value, default is core.
// 'CONTENT_CALLBACK_CUSTOM' means the module does it.
// 'CONTENT_CALLBACK_NONE' means this widget has
// no default value.
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
);
}
/**
* Implementation of hook_widget_settings().
*/
function pidfield_widget_settings($op, $widget) {
switch ($op) {
// Create the form element to be used on the widget
// settings form. Widget settings can be different
// for each shared instance of the same field and
// should define the way the value is displayed to
// the user in the edit form for that content type.
case 'form':
$form = array();
$size = (isset($widget['size']) && is_numeric($widget['size'])) ? $widget['size'] : 60;
$form['size'] = array(
'#type' => 'textfield',
'#title' => t('Size of textfield'),
'#default_value' => $size,
'#element_validate' => array('_element_validate_integer_positive'),
'#required' => TRUE,
);
return $form;
// Return an array of the names of the widget settings
// defined by this module. These are the items that
// CCK will store in the widget definition and they
// will be available in the $field['widget'] array.
// This should match the items defined in 'form' above.
case 'save':
return array('size');
}
}
/**
* Implementation of hook_widget().
*
* Attach a single form element to the form.
*
* CCK core fields only add a stub element and builds
* the complete item in #process so reusable elements
* created by hook_elements can be plugged into any
* module that provides valid $field information.
*
* Custom widgets that don't care about using hook_elements
* can be built out completely at this time.
*
* If there are multiple values for this field and CCK is
* handling multiple values, the content module will call
* this function as many times as needed.
*
* @param $form
* the entire form array,
* $form['#node'] holds node information
* @param $form_state
* the form_state,
* $form_state['values'][$field['field_name']]
* holds the field's form values.
* @param $field
* the field array
* @param $items
* array of default values for this field
* @param $delta
* the order of this item in the array of
* subelements (0, 1, 2, etc)
*
* @return
* the form item for a single element for this field
*/
function pidfield_widget(&$form, &$form_state, $field, $items, $delta = 0) {
$element['value'] = array(
'#type' => 'textfield',
'#title' => $field['widget']['label'],
'#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
'#autocomplete_path' => $element['#autocomplete_path'],
'#size' => !empty($field['widget']['size']) ? $field['widget']['size'] : 60,
'#attributes' => array('class' => 'pidfield'),
'#maxlength' => !empty($field['max_length']) ? $field['max_length'] : NULL,
);
// Used so that hook_field('validate') knows where to
// flag an error in deeply nested forms.
if (empty($form['#parents'])) {
$form['#parents'] = array();
}
$element['_error_element'] = array(
'#type' => 'value',
'#value' => implode('][', array_merge($form['#parents'], array('value'))),
);
return $element;
}
function get_node_references_for_fedora_item($item) {
$result = db_query("SELECT *
FROM {content_node_field} nf
INNER JOIN {content_node_field_instance} ni ON nf.field_name = ni.field_name
WHERE nf.type = 'pidfield'");
while ($field = db_fetch_array($result)) {
$db_info = content_database_info($field);
$ids = db_query("SELECT nid FROM {". $db_info['table'] ."} WHERE ". $field['field_name'] ."_value=\"". $item->pid."\"");
$results = array();
while ($data = db_fetch_object($ids)) {
//$additions[] = node_load($data->vid);
$results[] = $data->nid;
//$referred_node = node_load(array('nid'=>$data->nid) );
}
return $results;
}
}
function fedora_pidfield_redirect_to_node($item) {
$node_references = get_node_references_for_fedora_item($item);
if (!empty($node_references)) {
if (strstr( drupal_get_destination(), urlencode('fedora/repository'))) {
drupal_goto(drupal_get_path_alias("node/".$node_references[0]));
}
}
}