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) { $pid = $element['#item']['safe']; if(!empty($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])); } } }