Browse Source

coder standards

pull/907/head
Alan Stanley 7 years ago
parent
commit
0517fd181d
  1. 25
      README.md
  2. 8
      css/islandora_fits.css
  3. 36
      islandora_fits.install
  4. 211
      islandora_fits.module
  5. 117
      src/Plugin/Field/FieldFormatter/FitsFormatter.php
  6. 688
      src/Services/XMLTransform.php

25
README.md

@ -9,11 +9,13 @@ Install and enable this module in the usual way
#### Install FITS Webservice
FITS xmls are generated from an easily installed web service.
Get the latest fits.zip and fits.war from https://projects.iq.harvard.edu/fits/downloads
(on my box I had to install a missing zip library with ‘sudo apt-get install php7.1-zip’)
(on my box I had to install a missing zip library with
‘sudo apt-get install php7.1-zip’)
Install following their instructions.
Copy the .war file to your webapps directory and test.
Edit the catalina.properties file on the Drupal server by adding the following two lines to the bottom of the file-
Edit the catalina.properties file on the Drupal server by adding the
following two lines to the bottom of the file-
fits.home=/<path-to-fits>/fits
shared.loader=/<path-to-fits>/fits/lib/*.jar
@ -27,16 +29,23 @@ Restart Tomcat and test with
Get code from https://github.com/roblib/CrayFits and install. This code can live anywhere, including an external server,
but most installations will have it at /var/www/html.
The App runs by entering php bin/console server:start *:8050 in the App root folder.
The server is stopped with php bin/console server:stop. On a production machine you'd probably want to configure an additonal port in Apache.
The App runs by entering php bin/console server:start *:8050 in the App
root folder.
The server is stopped with php bin/console server:stop.
On a production machine you'd probably want to configure an additional
port in Apache.
Note: The location of the fits webserver is stored in the .env file in the root dir of the Symfony app. This will have to be reconfigured if the Fits server is anywhere other than localhost:8080/fits
Note: The location of the fits webserver is stored in the .env file in the
root dir of the Symfony app. This will have to be reconfigured if the Fits
server is anywhere other than localhost:8080/fits
#### Adding FITs requests to the queue
Copy the file `assets/ca.islandora.alpaca.connector.ocr.blueprint.xml` to `/opt/karak/deploy` on your server. There is no need to restart.
Copy the file `assets/ca.islandora.alpaca.connector.ocr.blueprint.xml`
to `/opt/karak/deploy` on your server. There is no need to restart.
#### Adding Checksum to Display
A pseudo field with the computed checksum can be added to Repository Item display. Naviage to `admin/structure/types/manage/islandora_object/display` to enable or disable display of `File Checksum`.
A pseudo field with the computed checksum can be added to Repository Item
display. Navigate to `admin/structure/types/manage/islandora_object/display`
to enable or disable display of `File Checksum`.

8
css/islandora_fits.css

@ -1,9 +1,11 @@
.islandora_fits_table {
width: 50em;
width: 50em;
}
.islandora_fits_table_labels {
width: 50%;
width: 50%;
}
.islandora_fits_table_values {
width: 50%;
width: 50%;
}

36
islandora_fits.install

@ -0,0 +1,36 @@
<?php
/**
* @file
* Install/update hook implementations.
*/
use Drupal\taxonomy\Entity\Term;
use Drupal\field\Entity\FieldConfig;
/**
* Implements hook_install().
*/
function islandora_fits_install() {
$term_name = 'FITS File';
$test_terms = taxonomy_term_load_multiple_by_name($term_name);
if (!$test_terms) {
$term = Term::create([
'parent' => [],
'name' => $term_name,
'vid' => 'islandora_media_use',
'description' => 'Technical Metadata associated with an original media file',
'field_external_uri' => ['uri' => 'https://projects.iq.harvard.edu/fits'],
])->save();
}
// Add xml extension if it doesn't already exist.
$field = FieldConfig::load("media.file.field_media_file");
$fieldSettings = $field->getSettings();
$extensions = $fieldSettings['file_extensions'];
if (!strpos($extensions, 'xml')) {
$fieldSettings['file_extensions'] .= ' xml';
$field->set('settings', $fieldSettings);
}
}

211
islandora_fits.module

@ -5,171 +5,142 @@
* Contains islandora_fits.module.
*/
use Drupal\field\Entity\FieldConfig;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\media\MediaInterface;
use Drupal\taxonomy\Entity\Term;
use Drupal\file\Entity\File;
use Drupal\media\Entity\Media;
/**
* Implements hook_help().
*/
function islandora_fits_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the islandora_fits module.
case 'help.page.islandora_fits':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Enables Technical Metadata derivative generation') . '</p>';
return $output;
default:
}
}
/**
* Implements hook_install().
*/
function islandora_fits_install() {
$term_name = 'FITS File';
$test_terms = taxonomy_term_load_multiple_by_name($term_name);
if (!$test_terms) {
$term = Term::create(array(
'parent' => [],
'name' => $term_name,
'vid' => 'islandora_media_use',
'description' => 'Technical Metadata associated with an original media file',
'field_external_uri' => ['uri' => 'https://projects.iq.harvard.edu/fits'],
))->save();
}
// Add xml extension if it doesn't already exist;
$field = FieldConfig::load("media.file.field_media_file");
$fieldSettings = $field->getSettings();
$extensions = $fieldSettings['file_extensions'];
if (!strpos($extensions, 'xml')) {
$fieldSettings['file_extensions'] .= ' xml';
$field->set('settings', $fieldSettings);
}
switch ($route_name) {
// Main module help for the islandora_fits module.
case 'help.page.islandora_fits':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Enables Technical Metadata derivative generation') . '</p>';
return $output;
default:
}
}
/**
* Implements hook_theme().
*/
function islandora_fits_theme($existing, $type, $theme, $path) {
return [
'fits' => [
'variables' => [
'title' => 'FITS data',
'link' => NULL,
'output' => [],
],
],
];
return [
'fits' => [
'variables' => [
'title' => 'FITS data',
'link' => NULL,
'output' => [],
],
],
];
}
/**
* Implements hook_ENTITY_TYPE_presave().
*/
function islandora_fits_media_presave(MediaInterface $media) {
if ($media->bundle() != 'fits_technical_metadata') {
return;
}
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$media->set('field_complete', TRUE);
$file_id = $media->get('field_media_file')->getValue()[0]['target_id'];
$file = File::load($file_id);
$data = file_get_contents($file->getFileUri());
// Adds any new fields to FITS media type.
$has_new = $transformer->check_new($data);
if ($has_new) {
$media->set('field_complete', FALSE);
} else {
$transformer->populate_media($data, $media);
}
if ($media->bundle() != 'fits_technical_metadata') {
return;
}
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$media->set('field_complete', TRUE);
$file_id = $media->get('field_media_file')->getValue()[0]['target_id'];
$file = File::load($file_id);
$data = file_get_contents($file->getFileUri());
// Adds any new fields to FITS media type.
$has_new = $transformer->check_new($data);
if ($has_new) {
$media->set('field_complete', FALSE);
}
else {
$transformer->populate_media($data, $media);
}
}
/**
* Implements hook_media_update().
*/
function islandora_fits_media_update(MediaInterface $media) {
if ($media->bundle() != 'fits_technical_metadata') {
return;
}
if ($media->get('field_complete')->value == FALSE) {
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$file_id = $media->get('field_media_file')->getValue()[0]['target_id'];
$file = File::load($file_id);
$data = file_get_contents($file->getFileUri());
$transformer->add_media_fields($data);
$new_media = Media::load($media->id());
$new_media->set('field_complete', TRUE);
$new_media->save();
}
if ($media->bundle() != 'fits_technical_metadata') {
return;
}
if ($media->get('field_complete')->value == FALSE) {
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$file_id = $media->get('field_media_file')->getValue()[0]['target_id'];
$file = File::load($file_id);
$data = file_get_contents($file->getFileUri());
$transformer->add_media_fields($data);
$new_media = Media::load($media->id());
$new_media->set('field_complete', TRUE);
$new_media->save();
}
}
/**
* Implements hook_media_insert().
*/
function islandora_fits_media_insert(MediaInterface $media) {
if ($media->bundle() != 'fits_technical_metadata') {
return;
}
islandora_fits_media_update($media);
if ($media->bundle() != 'fits_technical_metadata') {
return;
}
islandora_fits_media_update($media);
}
/**
* Implements hook_entity_extra_field_info().
*/
function islandora_fits_entity_extra_field_info() {
$extra = [];
$extra['node']['islandora_object']['display']['islandora_fits_checksum'] = array(
'label' => t('File Checksum'),
'description' => t('Checksum as discovered by FITs webservice'),
'weight' => 100,
'visible' => TRUE,
);
return $extra;
$extra = [];
$extra['node']['islandora_object']['display']['islandora_fits_checksum'] = [
'label' => t('File Checksum'),
'description' => t('Checksum as discovered by FITs webservice'),
'weight' => 100,
'visible' => TRUE,
];
return $extra;
}
/**
* Implements hook_entity_view().
*/
function islandora_fits_entity_view(array &$build, $entity, $display, $view_mode) {
$route_match_item = \Drupal::routeMatch()->getParameters()->all();
$current_entity = reset($route_match_item);
if ($entity === $current_entity) {
$medias = \Drupal::entityQuery(
'media')
->condition('field_media_of', $entity->id())
->condition('bundle', 'fits_technical_metadata')
->execute();
$mid = \reset($medias);
if ($mid) {
$fits = Media::load($mid);
$checksum = $fits->get('fits_ois_file_information_md5che')->value;
if ($checksum) {
$build['islandora_fits_checksum'] = [
'#type' => 'container',
'#attributes' => [
'id' => 'field-islandora-checksum',
],
'checksum' => [
'#type' => 'item',
'#title' => t('MD5 Checksum'),
'internal_uri' => [
'#type' => 'markup',
'#markup' => $checksum,
],
],
];
}
$route_match_item = \Drupal::routeMatch()->getParameters()->all();
$current_entity = reset($route_match_item);
if ($entity === $current_entity) {
$medias = \Drupal::entityQuery(
'media')
->condition('field_media_of', $entity->id())
->condition('bundle', 'fits_technical_metadata')
->execute();
$mid = \reset($medias);
if ($mid) {
$fits = Media::load($mid);
$checksum = $fits->get('fits_ois_file_information_md5che')->value;
if ($checksum) {
$build['islandora_fits_checksum'] = [
'#type' => 'container',
'#attributes' => [
'id' => 'field-islandora-checksum',
],
'checksum' => [
'#type' => 'item',
'#title' => t('MD5 Checksum'),
'internal_uri' => [
'#type' => 'markup',
'#markup' => $checksum,
],
],
];
}
}
}
}
}

117
src/Plugin/Field/FieldFormatter/FitsFormatter.php

@ -10,7 +10,6 @@ use Drupal\file\Entity\File;
use Drupal\Core\Link;
use Drupal\Core\Url;
/**
* Plugin implementation of the 'fits_formatter' formatter.
*
@ -24,70 +23,70 @@ use Drupal\Core\Url;
*/
class FitsFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
// Implement default settings.
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
// Implement default settings.
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
return [
// Implement settings form.
] + parent::settingsForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
return [
// Implement settings form.
] + parent::settingsForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];
// Implement settings summary.
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];
// Implement settings summary.
return $summary;
}
return $summary;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
foreach ($items as $delta => $item) {
$elements[$delta] = ['#markup' => $this->viewValue($item)];
}
foreach ($items as $delta => $item) {
$elements[$delta] = ['#markup' => $this->viewValue($item)];
}
return $elements;
}
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) {
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$fileItem = $item->getValue();
$file = File::load($fileItem['target_id']);
$url = Url::fromUri($file->url());
$link = Link::fromTextAndUrl("Link to XML", $url);
$link = $link->toRenderable();
$contents = file_get_contents($file->getFileUri());
if (mb_detect_encoding($contents) != 'UTF-8') {
$contents = utf8_encode($contents);
}
$output = $transformer->transformFits($contents);
$output['#link'] = $link;
$output['#title'] = $this->t("FITS Metadata");
return \Drupal::service('renderer')->render($output);
}
/**
* 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) {
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$fileItem = $item->getValue();
$file = File::load($fileItem['target_id']);
$url = Url::fromUri($file->url());
$link = Link::fromTextAndUrl("Link to XML", $url);
$link = $link->toRenderable();
$contents = file_get_contents($file->getFileUri());
if (mb_detect_encoding($contents) != 'UTF-8') {
$contents = utf8_encode($contents);
}
$output = $transformer->transformFits($contents);
$output['#link'] = $link;
$output['#title'] = $this->t("FITS Metadata");
return \Drupal::service('renderer')->render($output);
}
}

688
src/Services/XMLTransform.php

@ -2,8 +2,11 @@
namespace Drupal\islandora_fits\Services;
Use Drupal\Component\Utility\Xss;
use Drupal\Component\Utility\Xss;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
@ -11,345 +14,404 @@ use Drupal\field\Entity\FieldConfig;
* Class XMLTransform.
*/
class XMLTransform extends ServiceProviderBase {
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
private $renderer;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
private $entityManager;
/**
* List of characters to switch.
*
* @var array
*/
private $forbidden;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
private $messenger;
private $renderer;
private $entityManager;
private $forbidden;
private $messenger;
/**
* XMLTransform constructor.
*
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
* @param \Drupal\Core\Entity\EntityManagerInterface $entityManager
* The entity manager.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(RendererInterface $renderer, EntityManagerInterface $entityManager, MessengerInterface $messenger) {
$this->renderer = $renderer;
$this->entityManager = $entityManager;
$this->messenger = $messenger;
$this->forbidden = ['-', ' '];
}
/**
* Constructs a new XMLTransform object.
*/
public function __construct($renderer, $entityManager, $messenger) {
$this->renderer = $renderer;
$this->entityManager = $entityManager;
$this->messenger = $messenger;
$this->forbidden = ['-', ' '];
/**
* Transforms FITS xml into renderable array.
*
* @param string $input_xml
* Xml to be transformed.
*
* @return array|null
* Array of parsed results.
*/
public function transformFits($input_xml) {
$utf8 = mb_detect_encoding($input_xml, 'UTF-8', TRUE);
if (!$utf8) {
$input_xml = utf8_encode($input_xml);
}
/**
* Transforms FITS xml into renderable array.
*
* @param $input_xml
* @return array
*/
public function transformFits($input_xml) {
$utf8 = mb_detect_encoding($input_xml, 'UTF-8', true);
if (!$utf8) {
$input_xml = utf8_encode($input_xml);
}
try {
$xml = new \SimpleXMLElement($input_xml);
} catch (\Exception $e) {
$this->messenger->addWarning(t('File does not contain valid xml.'));
return;
}
$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) && $field != 'Filepath') {
$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,
];
}
}
}
$fieldsets = $variables['islandora_fits_fieldsets'];
$output = [];
foreach ($fieldsets as $title => $fieldset) {
$output[] = [
'title' => $title,
'data' => $fieldset,
try {
$xml = new \SimpleXMLElement($input_xml);
}
catch (\Exception $e) {
$this->messenger->addWarning(t('File does not contain valid xml.'));
return;
}
$xml->registerXPathNamespace('fits', 'http://hul.harvard.edu/ois/xml/ns/fits/fits_output');
$fits_metadata = $this->islandoraFitsChildXpath($xml);
$headers = [
'label' => t('Field'),
'value' => t('Value'),
];
if (count($fits_metadata) == 0) {
$variables['islandora_fits_table']['empty'] = '';
$variables['islandora_fits_fieldsets']['empty'] = [
'#type' => 'markup',
'#markup' => t('No technical metadata found.'),
];
}
else {
foreach ($fits_metadata as $tool_name => $vals_array) {
$variables['islandora_fits_data'][$tool_name] = [];
$rows = &$variables['islandora_fits_data'][$tool_name];
foreach ($vals_array as $field => $val_array) {
if (!array_key_exists($field, $rows) && $field != 'Filepath') {
$rows[$field] = [
['data' => Xss::filter($field), 'class' => 'islandora_fits_table_labels'],
];
foreach ($val_array as $value) {
if (!isset($rows[$field]['value'])) {
$rows[$field]['value'] = ['data' => Xss::filter($value), 'class' => 'islandora_fits_table_values'];
}
else {
$data = $rows[$field]['value']['data'] .= ' - ' . Xss::filter($value);
$rows[$field]['value'] = ['data' => $data, 'class' => 'islandora_fits_table_values'];
}
}
}
$table_attributes = ['class' => ['islandora_fits_table']];
$table = [
'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,
];
}
$renderable = [
'#theme' => 'fits',
'#output' => $output,
'#attached' => [
'library' => [
'islandora_fits/islandora_fits',
]
]
];
return $renderable;
}
}
$fieldsets = $variables['islandora_fits_fieldsets'];
$output = [];
foreach ($fieldsets as $title => $fieldset) {
$output[] = [
'title' => $title,
'data' => $fieldset,
];
}
$renderable = [
'#theme' => 'fits',
'#output' => $output,
'#attached' => [
'library' => [
'islandora_fits/islandora_fits',
],
],
];
return $renderable;
}
/**
* 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.
*/
private 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 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.
*/
private function islandoraFitsChildXpath(SimpleXMLElement $xml) {
$results = $xml->xpath('/*|/*/fits:metadata');
$output = [];
foreach ($results as $result) {
$this->islandoraFitsChildren($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.
*/
private function islandora_fits_children($child, &$output) {
$grandchildren = $child->xpath('*/*');
/**
* 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.
*/
private function islandoraFitsChildren(SimpleXMLElement $child, array &$output) {
$grandchildren = $child->xpath('*/*');
if (count($grandchildren) > 0) {
foreach ($grandchildren as $grandchild) {
$this->islandora_fits_children($grandchild, $output);
if (count($grandchildren) > 0) {
foreach ($grandchildren as $grandchild) {
$this->islandoraFitsChildren($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->islandoraFitsContructOutput($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;
}
}
} 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;
}
}
}
// 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.
*/
private 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();
/**
* 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.
*/
private function islandoraFitsContructOutput(string $node_name, string $tool_name) {
// Construct an arbitrary string with all capitals in it.
$capitals = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$name_array = str_split($node_name);
$space_position = [];
// 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));
// 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;
}
}
/**
* Adds fields to content type.
*
* @param $input_xml
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function add_media_fields($input_xml) {
$fields_added = FALSE;
$data = $this->transformFits($input_xml);
$all_fields = [];
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvest_values($datum));
}
$to_process = $this->normalize_names($all_fields);
foreach ($to_process as $field) {
$exists = FieldStorageConfig::loadByName('media', $field['field_name']);
if (!$exists) {
$field_storage = FieldStorageConfig::create([
'entity_type' => 'media',
'field_name' => $field['field_name'],
'type' => 'text',
]);
$field_storage->save();
}
$bundle_fields = $this->entityManager->getFieldDefinitions('media', 'fits_technical_metadata');
$bundle_keys = array_keys($bundle_fields);
if (!in_array($field['field_name'], $bundle_keys)) {
$field_storage = FieldStorageConfig::loadByName('media', $field['field_name']);
FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'fits_technical_metadata',
'label' => $field['field_label'],
])->save();
$fields_added = TRUE;
}
}
return $fields_added;
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);
/**
* Populates media.
*
* @param $input_xml
* @param $media
*/
public function populate_media($input_xml, &$media) {
$data = $this->transformFits($input_xml);
$all_fields = [];
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvest_values($datum));
}
$to_add = [];
foreach ($all_fields as $label => $field_value) {
$lower = strtolower($label);
$normalized = str_replace($this->forbidden, '_', $lower);
$field_name = substr("fits_$normalized", 0, 32);
$to_add[$field_name] = $field_value;
}
foreach ($to_add as $field_name => $field_value) {
$media->set($field_name, $field_value);
}
return ['name' => $node_name, 'tool' => ucwords($tool_name)];
}
/**
* Adds fields to content type.
*
* @param string $input_xml
* Input to be transformed.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*
* @return bool
* Fields to be formatted.
*/
public function addMediaFields(string $input_xml) {
$fields_added = FALSE;
$data = $this->transformFits($input_xml);
$all_fields = [];
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvestValues($datum));
}
$to_process = $this->normalizeNames($all_fields);
foreach ($to_process as $field) {
$exists = FieldStorageConfig::loadByName('media', $field['field_name']);
if (!$exists) {
$field_storage = FieldStorageConfig::create([
'entity_type' => 'media',
'field_name' => $field['field_name'],
'type' => 'text',
]);
$field_storage->save();
}
$bundle_fields = $this->entityManager->getFieldDefinitions('media', 'fits_technical_metadata');
$bundle_keys = array_keys($bundle_fields);
if (!in_array($field['field_name'], $bundle_keys)) {
$field_storage = FieldStorageConfig::loadByName('media', $field['field_name']);
FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'fits_technical_metadata',
'label' => $field['field_label'],
])->save();
$fields_added = TRUE;
}
}
return $fields_added;
}
/**
* Extracts and labels content.
*
* @param $input
* @return array
*/
private function harvest_values($input) {
$fields = [];
$label = str_replace(' ', '_', $input['title']);
$rows = $input['data']['#rows'];
foreach ($rows as $key => $value) {
$fields["{$label}_{$key}"] = $value['value']['data'];
}
return $fields;
/**
* Populates media.
*
* @param string $input_xml
* String to be transformed.
* @param \Drupal\media\MediaInterface $media
* Media to which transformed xml is to be added.
*/
public function populateMedia(string $input_xml, MediaInterface &$media) {
$data = $this->transformFits($input_xml);
$all_fields = [];
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvestValues($datum));
}
$to_add = [];
foreach ($all_fields as $label => $field_value) {
$lower = strtolower($label);
$normalized = str_replace($this->forbidden, '_', $lower);
$field_name = substr("fits_$normalized", 0, 32);
$to_add[$field_name] = $field_value;
}
foreach ($to_add as $field_name => $field_value) {
$media->set($field_name, $field_value);
}
}
/**
* Extracts and labels content.
*
* @param array $input
* Values to be harvested and prepped.
*
* @return array
* Fields prepped for display.
*/
private function harvestValues(array $input) {
$fields = [];
$label = str_replace(' ', '_', $input['title']);
$rows = $input['data']['#rows'];
foreach ($rows as $key => $value) {
$fields["{$label}_{$key}"] = $value['value']['data'];
}
return $fields;
/**
* Create standardized machine name fields.
*
* @param array $names
* @return array
*/
private function normalize_names(array $names) {
$normalized_names = [];
foreach ($names as $label => $field_value) {
$lower = strtolower($label);
$normalized = str_replace($this->forbidden, '_', $lower);
$field_name = substr("fits_$normalized", 0, 32);
}
$normalized_names[] = [
'field_label' => $label,
'field_name' => $field_name,
'field_value' => $field_value,
];
}
return $normalized_names;
/**
* Create standardized machine name fields.
*
* @param array $names
* Names to be normalized.
*
* @return array
* Normalized names.
*/
private function normalizeNames(array $names) {
$normalized_names = [];
foreach ($names as $label => $field_value) {
$lower = strtolower($label);
$normalized = str_replace($this->forbidden, '_', $lower);
$field_name = substr("fits_$normalized", 0, 32);
$normalized_names[] = [
'field_label' => $label,
'field_name' => $field_name,
'field_value' => $field_value,
];
}
return $normalized_names;
}
public function check_new($input_xml) {
$fields_added = FALSE;
$data = $this->transformFits($input_xml);
$all_fields = [];
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvest_values($datum));
}
$to_process = $this->normalize_names($all_fields);
foreach ($to_process as $field) {
$bundle_fields = $this->entityManager->getFieldDefinitions('media', 'fits_technical_metadata');
$bundle_keys = array_keys($bundle_fields);
if (!in_array($field['field_name'], $bundle_keys)) {
$fields_added = TRUE;
}
}
return $fields_added;
/**
* Checks to see if new fields are required.
*
* @param string $input_xml
* Xml to be checked.
*
* @return bool
* Whether fields havbe been added.
*/
public function checkNew(string $input_xml) {
$fields_added = FALSE;
$data = $this->transformFits($input_xml);
$all_fields = [];
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvestValues($datum));
}
$to_process = $this->normalizeNames($all_fields);
foreach ($to_process as $field) {
$bundle_fields = $this->entityManager->getFieldDefinitions('media', 'fits_technical_metadata');
$bundle_keys = array_keys($bundle_fields);
if (!in_array($field['field_name'], $bundle_keys)) {
$fields_added = TRUE;
}
}
return $fields_added;
}
}

Loading…
Cancel
Save