modules/custom/eml/eml.module
<?php
/**
* @file
* EML generation.
*
* Major features
* - EML view mode and template for nodes.
* - API to generate a package ID for EML.
* - API to fetch the DOI of an EML.
* - Action that can be used in VBO to update data sets' DOI fields.
*
* @todo Sean check all the pasta api urls and calls.
* @todo Sean to trace the process for the API calls and test the logic.
*/
require_once dirname(__FILE__) . '/eml.field.inc';
/**
* Implements hook_help().
*/
function eml_help($path, $arg) {
// Show a warning on the 'EML' view mode sub-tab of 'Manage Display' pages
// that re-ordering fields has no affect on the actual EML templates used.
if (preg_match('/.*\/manage\/.*\/display\/eml/', $path)) {
drupal_set_message(t('The ordering of these elements is hard-coded in the template files of the EML module. Re-ordering here will not change any output in EML.'), 'warning');
}
}
/**
* Implements hook_entity_info_alter().
*/
function eml_entity_info_alter(array &$info) {
// Add an 'EML' view mode to all possible entity types.
foreach (array_keys($info) as $entity_type) {
if (!empty($info[$entity_type]['view modes'])) {
$info[$entity_type]['view modes']['eml'] = array(
'label' => t('EML'),
'custom settings' => FALSE,
);
}
}
}
/**
* Implements hook_menu().
*/
function eml_menu() {
$items = array();
$items['node/%node/eml'] = array(
'page callback' => 'eml_output_node',
'page arguments' => array(1),
'access callback' => 'node_access',
'access arguments' => array('view', 1),
'type' => MENU_CALLBACK,
'file' => 'eml.pages.inc',
);
$items['admin/config/services/eml'] = array(
'title' => 'EML',
'description' => 'Configure EML settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array('eml_settings_form'),
'access arguments' => array('administer site configuration'),
'file' => 'eml.admin.inc',
);
return $items;
}
/**
* Implements hook_entity_view().
*
* When an entity is being rendered with the 'eml' view mode, convert the theme
* and template being used to use our own EML theme/template.
*
* @see eml_preprocess_eml()
*/
function eml_entity_view($entity, $type, $view_mode, $langcode) {
if ($view_mode == 'eml') {
list(, , $bundle) = entity_extract_ids($type, $entity);
$entity->content += array(
'#entity' => $entity,
'#bundle' => $bundle,
'#theme' => "eml",
);
}
}
/**
* Implements hook_theme().
*/
function eml_theme($existing, $type, $theme, $path) {
$info['eml'] = array(
'render element' => 'elements',
'template' => 'eml',
'path' => $path . '/templates',
);
// Add support for our additional EML templates.
$info += drupal_find_theme_templates($info, '.tpl.php', drupal_get_path('module', 'eml') . '/templates');
$info['eml_tag'] = array(
'render element' => 'element',
);
$info['eml_tags'] = array(
'render element' => 'element',
);
// A theme wrapper for format_xml_elements().
$info['eml_elements'] = array(
'variables' => array('eml' => array()),
);
return $info;
}
function theme_eml_elements($variables) {
return format_xml_elements($variables['eml']);
}
function theme_eml_tag($variables) {
$element = &$variables['element'];
if (isset($element['#value'])) {
$element['#value'] = check_plain($element['#value']);
}
elseif ($children = element_children($element)) {
$element['#value'] = '';
foreach ($children as $key) {
$element[$key] += array('#theme' => 'eml_tag');
$element['#value'] .= drupal_render($element[$key]);
}
}
return theme_html_tag($variables);
}
function theme_eml_tags($variables) {
$output = '';
$element = &$variables['element'];
foreach (element_children($element) as $key) {
$sub_element = array('element' => array());
$sub_element['element']['#tag'] = $element['#tag'];
if (isset($element['#attributes'])) {
$sub_element['element']['#attributes'] = $element['#attributes'];
}
$sub_element['element']['#value'] = drupal_render($element[$key]);
$output .= theme_html_tag($sub_element);
}
return $output;
}
/**
* Implements hook_node_presave().
*/
function eml_node_presave($node) {
if ($node->type == 'data_set' && empty($node->nid)) {
// For new datasets, set the EML revision ID to 0. This will be incremented
// to 1 in eml_node_insert() if the data set is published, or whenever the
// data set is transitioned to a published state in
// eml_workbench_moderation_transition().
if (!field_get_items('node', $node, 'field_eml_revision_id')) {
$node->field_eml_revision_id[LANGUAGE_NONE][0] = array('value' => 0);
}
}
}
/**
* Implements hook_node_insert().
*/
function eml_node_insert($node) {
if ($node->type == 'data_set') {
$dataset = new EMLDataSet($node);
$dataset->detectEmlChanges();
}
}
/**
* Implements hook_workbench_moderation_transition().
*/
function eml_workbench_moderation_transition($node, $previous_state, $new_state) {
if ($node->type == 'data_set' && $new_state == workbench_moderation_state_published()) {
// If the node is updated to a published state, force EML generation, which
// checks if the EML has changed in any way.
$dataset = new EMLDataSet($node);
// If an unpublished node is being published from Moderation tab, it still
// has $node->status = 0. So the unpublished node checking must be disabled
// when run here.
$dataset->detectEmlChanges(FALSE);
}
}
/**
* Implements hook_node_view().
*/
function eml_node_view($node, $view_mode, $langcode) {
if ($view_mode != 'eml') {
return;
}
if ($node->type == 'data_set' || $node->type == 'data_source') {
$methods = array();
if ($items = field_get_items('node', $node, 'field_methods')) {
$method_instance = field_info_instance('node', 'field_methods', $node->type);
$instrumentation_instance = field_info_instance('node', 'field_instrumentation', $node->type);
$instrumentation_values = field_get_items('node', $node, 'field_instrumentation');
foreach ($items as $delta => $item) {
$method = array();
$method['description']['section']['para']['literalLayout'] = strip_tags(_text_sanitize($method_instance, $langcode, $item, 'value'));
if (!empty($instrumentation_values[$delta])) {
$method['instrumentation'] = strip_tags(_text_sanitize($instrumentation_instance, $langcode, $instrumentation_values[$delta], 'value'));
}
$methods[] = array('key' => 'methodStep', 'value' => $method);
}
}
if ($qa_items = field_get_items('node', $node, 'field_quality_assurance')) {
$qa_instance = field_info_instance('node', 'field_quality_assurance', $node->type);
$methods['qualityControl']['description']['para']['literalLayout'] = strip_tags(_text_sanitize($qa_instance, $langcode, $qa_items[0], 'value'));
}
if (!empty($methods)) {
$node->content['methods'] = array(
'#theme' => 'eml_elements',
'#eml' => $methods,
);
}
}
switch ($node->type) {
case 'data_set':
// Join all taxonomy fields into one content array to output in the
// template.
$node->content['keywordSets'] = array();
foreach (element_children($node->content) as $key) {
if (isset($node->content[$key]['#field_type'])
&& $node->content[$key]['#field_type'] == 'taxonomy_term_reference'
&& $node->content[$key]['#formatter'] == 'taxonomy_eml_keywordset') {
$node->content['keywordSets'][] = $node->content[$key];
}
}
$node->EmlDataSet = new EmlDataSet($node);
if ($metadata = $node->EmlDataSet->getCustomUnitMetadata()) {
$node->content['additionalMetadata'] = $metadata;
}
break;
}
}
/**
* Implements hook_date_format_types().
*/
function eml_date_format_types() {
return array(
'eml_yeardate' => t('EML yearDate'),
);
}
/**
* Implements hook_date_formats().
*/
function eml_date_formats() {
return array(
array(
'type' => 'eml_yeardate',
'format' => 'Y-m-d',
'locales' => array(),
),
);
}
/**
* Implements hook_preprocess_HOOK() for eml.tpl.php.
*/
function template_preprocess_eml(&$variables, $hook) {
$variables['entity'] = $variables['elements']['#entity'];
$entity = $variables['entity'];
$entity_type = $variables['elements']['#entity_type'];
$bundle = $variables['elements']['#bundle'];
$label = entity_label($entity_type, $entity);
$uri = entity_uri($entity_type, $entity);
$variables['url'] = url($uri['path'], array('absolute' => TRUE) + $uri['options']);
$variables['label'] = check_plain($label);
$variables['language'] = check_plain($GLOBALS[LANGUAGE_TYPE_CONTENT]->name);
$variables['pubPlace'] = check_plain(variable_get('site_name', 'Drupal'));
$variables['station'] = check_plain(variable_get('station_acronym', 'STATION'));
$variables['data_policies'] = check_plain(strip_tags(variable_get('eml_data_policies', '')));
list($pasta_user) = explode(':', token_replace(variable_get('eml_pasta_user', 'uid=[site:station-acronym],o=LTER,dc=ecoinformatics,dc=org')), 2);
$variables['pasta_user'] = $pasta_user;
$variables['namespaces_array'] = array(
'xmlns:eml' => "eml://ecoinformatics.org/eml-2.1.0",
'xmlns:stmml' => "http://www.xml-cml.org/schema/stmml-1.1",
'xmlns:ds' => "eml://ecoinformatics.org/dataset-2.1.0",
'xmlns:xs' => "http://www.w3.org/2001/XMLSchema",
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
'xsi:schemaLocation' => "eml://ecoinformatics.org/eml-2.1.0 http://nis.lternet.edu/schemas/EML/eml-2.1.0/eml.xsd",
);
if ($entity_type == 'node' && $variables['elements']['#bundle'] == 'data_set') {
$variables['attributes_array'] += array(
// The EmlDataSet property is loaded in eml_node_view().
'packageId' => $entity->EmlDataSet->getPackageID(),
'system' => "knb",
);
$variables['pubDate'] = format_date($entity->created, 'eml_yeardate');
}
// Helpful $content variable for templates.
$variables += array('content' => array());
foreach (element_children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
// Remove the field wrappers and classes so we just get native output.
if (isset($variables['content'][$key]['#theme']) && $variables['content'][$key]['#theme'] == 'field') {
unset($variables['content'][$key]['#theme']);
}
}
// Ensure that all the fields for this entity are available, even if empty.
foreach (field_info_instances($entity_type, $bundle) as $instance) {
if (!isset($variables['content'][$instance['field_name']])) {
$variables['content'][$instance['field_name']] = '';
}
}
// Add template suggestions to use, starting with the least preferred, and
// ending with the one to try first if it exists. The last one should be the
// most specific.
$variables['theme_hook_suggestions'][] = 'eml';
$variables['theme_hook_suggestions'][] = "eml__{$entity_type}__{$bundle}";
}
/**
* Implements hook_process_HOOK() for eml.tpl.php.
*/
function template_process_eml(array &$variables) {
$variables['namespaces'] = $variables['namespaces_array'] ? drupal_attributes($variables['namespaces_array']) : '';
}
function eml_debug($message, array $variables = array()) {
if (variable_get('eml_debugging')) {
drupal_set_message(format_string('EML DEBUG: ' . $message, $variables));
watchdog('eml', $message, $variables, WATCHDOG_DEBUG);
}
}
/**
* Calculate the package ID of a data set.
*
* @deprecated Use EmlDataSet::getPackageID().
*
* @param $node
* A data set node object.
*
* @return string
* The package ID of the data set in the format of scope.identifier.revision.
*/
function eml_dataset_get_package_id($node) {
$pattern = variable_get('eml_package_id_pattern', 'knb-lter-[site:station-acronym].[node:field_data_set_id].[node:field_eml_revision_id]');
return drupal_strtolower(token_replace($pattern, array('node' => $node), array('clear' => TRUE, 'callback' => 'eml_cleanup_package_id_tokens')));
}
function eml_dataset_is_valid_package_id($package_id) {
return preg_match('/^([\w-]+)\.(\d+)\.(\d+)$/', $package_id);
}
/**
* Token replacement callback to remove leading zeros from token values.
*
* This is necessary since it is very likely that [node:field_data_set_id]
* has leading zeros.
*/
function eml_cleanup_package_id_tokens(array &$replacements, array $data, array $options) {
foreach ($replacements as &$replacement) {
if (drupal_strlen($replacement) > 1) {
$replacement = ltrim($replacement, '0');
}
}
}