diff --git a/config/install/core.entity_view_display.media.fits_technical_metadata.default.yml b/config/install/core.entity_view_display.media.fits_technical_metadata.default.yml new file mode 100644 index 00000000..4d7891e0 --- /dev/null +++ b/config/install/core.entity_view_display.media.fits_technical_metadata.default.yml @@ -0,0 +1,55 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.fits_technical_metadata.field_file_size + - field.field.media.fits_technical_metadata.field_media_file + - field.field.media.fits_technical_metadata.field_media_of + - field.field.media.fits_technical_metadata.field_media_use + - field.field.media.fits_technical_metadata.field_mime_type + - media.type.fits_technical_metadata + module: + - islandora_fits +id: media.fits_technical_metadata.default +targetEntityType: media +bundle: fits_technical_metadata +mode: default +content: + field_media_file: + weight: 0 + label: hidden + settings: { } + third_party_settings: { } + type: fits_formatter + region: content + field_media_of: + weight: 1 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + field_media_use: + weight: 3 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + field_mime_type: + weight: 2 + label: above + settings: + link_to_entity: false + third_party_settings: { } + type: string + region: content +hidden: + created: true + field_file_size: true + langcode: true + name: true + thumbnail: true + uid: true diff --git a/config/install/core.entity_view_display.media.fits_technical_metadata.fits_technical_metadata.yml b/config/install/core.entity_view_display.media.fits_technical_metadata.fits_technical_metadata.yml new file mode 100644 index 00000000..3bf6e5c3 --- /dev/null +++ b/config/install/core.entity_view_display.media.fits_technical_metadata.fits_technical_metadata.yml @@ -0,0 +1,53 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.fits_technical_metadata + - field.field.media.fits_technical_metadata.field_media_file + - image.style.thumbnail + - media.type.fits_technical_metadata + module: + - image + - islandora_fits + - user +id: media.fits_technical_metadata.fits_technical_metadata +targetEntityType: media +bundle: fits_technical_metadata +mode: fits_technical_metadata +content: + created: + label: hidden + type: timestamp + weight: 0 + region: content + settings: + date_format: medium + custom_date_format: '' + timezone: '' + third_party_settings: { } + field_media_file: + weight: 6 + label: above + settings: { } + third_party_settings: { } + type: fits_formatter + region: content + thumbnail: + type: image + weight: 5 + label: hidden + settings: + image_style: thumbnail + image_link: '' + region: content + third_party_settings: { } + uid: + label: hidden + type: author + weight: 0 + region: content + settings: { } + third_party_settings: { } +hidden: + langcode: true + name: true diff --git a/config/install/media.type.fits_technical_metadata.yml b/config/install/media.type.fits_technical_metadata.yml new file mode 100644 index 00000000..dd18514f --- /dev/null +++ b/config/install/media.type.fits_technical_metadata.yml @@ -0,0 +1,15 @@ +langcode: en +status: true +dependencies: { } +id: fits_technical_metadata +label: 'FITS Technical metadata' +description: "Display of transformed FITS xml" +source: file +queue_thumbnail_downloads: false +new_revision: false +source_configuration: + source_field: field_media_file +field_map: + name: name + mimetype: field_mime_type + filesize: field_file_size diff --git a/src/Plugin/Field/FieldFormatter/FitsFormatter.php b/src/Plugin/Field/FieldFormatter/FitsFormatter.php new file mode 100644 index 00000000..4f0259e2 --- /dev/null +++ b/src/Plugin/Field/FieldFormatter/FitsFormatter.php @@ -0,0 +1,262 @@ + $item) { + $elements[$delta] = ['#markup' => $this->viewValue($item)]; + } + + return $elements; + } + + /** + * Generate the output appropriate for one field item. + * + * @param \Drupal\Core\Field\FieldItemInterface $item + * One field item. + * + * @return string + * The textual output generated. + */ + protected function viewValue(FieldItemInterface $item) { + $fileItem = $item->getValue(); + $file = File::load($fileItem['target_id']); + $contents = file_get_contents($file->getFileUri()); + $xml = new \SimpleXMLElement($contents); + $xml->registerXPathNamespace('fits', 'http://hul.harvard.edu/ois/xml/ns/fits/fits_output'); + $fits_metadata = $this->islandora_fits_child_xpath($xml); + $headers = array( + 'label' => t('Field'), + 'value' => t('Value'), + ); + if (count($fits_metadata) == 0) { + $variables['islandora_fits_table']['empty'] = ''; + $variables['islandora_fits_fieldsets']['empty'] = array( + '#type' => 'markup', + '#markup' => t('No technical metadata found.'), + ); + } else { + foreach ($fits_metadata as $tool_name => $vals_array) { + $variables['islandora_fits_data'][$tool_name] = array(); + $rows = &$variables['islandora_fits_data'][$tool_name]; + foreach ($vals_array as $field => $val_array) { + if (!array_key_exists($field, $rows)) { + $rows[$field] = array( + array('data' => Xss::filter($field), 'class' => 'islandora_fits_table_labels'), + ); + foreach ($val_array as $value) { + if (!isset($rows[$field]['value'])) { + $rows[$field]['value'] = array('data' => Xss::filter($value), 'class' => 'islandora_fits_table_values'); + } else { + $data = $rows[$field]['value']['data'] .= ' - ' . Xss::filter($value); + $rows[$field]['value'] = array('data' => $data, 'class' => 'islandora_fits_table_values'); + } + } + } + $table_attributes = array('class' => array('islandora_fits_table')); + + $table = array( + 'header' => $headers, + 'rows' => $rows, + 'attributes' => $table_attributes, + ); + + $variables['islandora_fits_table'][$tool_name] = $table; + $variables['islandora_fits_fieldsets'][$tool_name] = [ + '#theme' => 'table', + '#header' => $headers, + '#rows' => $rows, + '#attributes' => $table_attributes, + '#header_columns' => 4, + ]; + } + } + } + + $output = $variables['islandora_fits_fieldsets']; + return render($output); + } + + /** + * Finds the the first set of children from the FITS xml. + * + * Once it has these it passes them off recursively. + * + * @param SimpleXMLElement $xml + * The SimpleXMLElement to parse. + * + * @return array + * An array containing key/value pairs of fields and data. + */ + public function islandora_fits_child_xpath($xml) { + $results = $xml->xpath('/*|/*/fits:metadata'); + $output = array(); + foreach ($results as $result) { + $this->islandora_fits_children($result, $output); + } + return $output; + } + + /** + * Finds children for fits module. + * + * Recursive function that searches continuously until + * we grab the node's text value and add to + * the output array. + * + * @param SimpleXMLElement $child + * The current child that we are searching through. + * + * @param array $output + * An array containing key/value pairs of fields and data. + */ + public function islandora_fits_children($child, &$output) { + $grandchildren = $child->xpath('*/*'); + + if (count($grandchildren) > 0) { + foreach ($grandchildren as $grandchild) { + $this->islandora_fits_children($grandchild, $output); + } + } else { + $text_results = $child->xpath('text()'); + $tool_name = FALSE; + if ($text_results) { + foreach ($text_results as $text) { + foreach ($text->attributes() as $key => $value) { + if ($key === 'toolname') { + $tool_name = trim((string)$value); + } + } + $output_text = trim((string)$text); + if (!empty($output_text)) { + $fits_out = $this->islandora_fits_construct_output($child->getName(), $tool_name); + $tool_label = $fits_out['tool']; + $field_label = $fits_out['name']; + // Need to check if the label already exists in our output + // such that we do not duplicate entries. + if ($tool_label) { + if (isset($output[$tool_label])) { + if (!array_key_exists($field_label, $output[$tool_label])) { + $output[$tool_label][$field_label][] = $output_text; + } else { + if (!in_array($output_text, $output[$tool_label][$field_label])) { + $output[$tool_label][$field_label][] = $output_text; + } + } + } else { + $output[$tool_label][$field_label][] = $output_text; + } + } // No tool attribute. + else { + if (isset($output['Unknown'][$field_label])) { + if (!in_array($output_text, $output['Unknown'][$field_label])) { + $output['Unknown'][$field_label][] = $output_text; + } + } else { + $output['Unknown'][$field_label][] = $output_text; + } + } + } + } + } + } + + } + + /** + * Builds display by parsing strings. + * + * @param string $node_name + * Name of the current node that we will display. + * @param string $tool_name + * Name of the tool used to generate the metadata. + * + * @return array + * Constructed node name for output. + */ + public function islandora_fits_construct_output($node_name, $tool_name) { + // Construct an arbitrary string with all capitals in it. + $capitals = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $name_array = str_split($node_name); + $space_position = array(); + + // Check to see which characters are capitals so we can split + // them up for cleaner display. + foreach ($name_array as $key => $value) { + if (strpos($capitals, $value) !== FALSE && $key !== 0) { + $space_position[] = $key; + } + } + if (count($space_position)) { + // Needed in event we add multiple spaces so need to keep track. + $pos_offset = 0; + foreach ($space_position as $pos) { + $node_name = substr_replace($node_name, ' ', $pos + $pos_offset, 0); + $pos_offset++; + } + } + $node_name = ucwords($node_name); + + return array('name' => $node_name, 'tool' => ucwords($tool_name)); + } + + +}