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 #### Install FITS Webservice
FITS xmls are generated from an easily installed web service. 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 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. Install following their instructions.
Copy the .war file to your webapps directory and test. 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 fits.home=/<path-to-fits>/fits
shared.loader=/<path-to-fits>/fits/lib/*.jar 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, 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. 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 App runs by entering php bin/console server:start *:8050 in the App
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. 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 #### 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 #### 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 { .islandora_fits_table {
width: 50em; width: 50em;
} }
.islandora_fits_table_labels { .islandora_fits_table_labels {
width: 50%; width: 50%;
} }
.islandora_fits_table_values { .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. * Contains islandora_fits.module.
*/ */
use Drupal\field\Entity\FieldConfig;
use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\media\MediaInterface; use Drupal\media\MediaInterface;
use Drupal\taxonomy\Entity\Term;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\media\Entity\Media; use Drupal\media\Entity\Media;
/** /**
* Implements hook_help(). * Implements hook_help().
*/ */
function islandora_fits_help($route_name, RouteMatchInterface $route_match) { function islandora_fits_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) { switch ($route_name) {
// Main module help for the islandora_fits module. // Main module help for the islandora_fits module.
case 'help.page.islandora_fits': case 'help.page.islandora_fits':
$output = ''; $output = '';
$output .= '<h3>' . t('About') . '</h3>'; $output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Enables Technical Metadata derivative generation') . '</p>'; $output .= '<p>' . t('Enables Technical Metadata derivative generation') . '</p>';
return $output; return $output;
default: 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);
}
} }
/** /**
* Implements hook_theme(). * Implements hook_theme().
*/ */
function islandora_fits_theme($existing, $type, $theme, $path) { function islandora_fits_theme($existing, $type, $theme, $path) {
return [ return [
'fits' => [ 'fits' => [
'variables' => [ 'variables' => [
'title' => 'FITS data', 'title' => 'FITS data',
'link' => NULL, 'link' => NULL,
'output' => [], 'output' => [],
], ],
], ],
]; ];
} }
/** /**
* Implements hook_ENTITY_TYPE_presave(). * Implements hook_ENTITY_TYPE_presave().
*/ */
function islandora_fits_media_presave(MediaInterface $media) { function islandora_fits_media_presave(MediaInterface $media) {
if ($media->bundle() != 'fits_technical_metadata') { if ($media->bundle() != 'fits_technical_metadata') {
return; return;
} }
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml'); $transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$media->set('field_complete', TRUE); $media->set('field_complete', TRUE);
$file_id = $media->get('field_media_file')->getValue()[0]['target_id']; $file_id = $media->get('field_media_file')->getValue()[0]['target_id'];
$file = File::load($file_id); $file = File::load($file_id);
$data = file_get_contents($file->getFileUri()); $data = file_get_contents($file->getFileUri());
// Adds any new fields to FITS media type. // Adds any new fields to FITS media type.
$has_new = $transformer->check_new($data); $has_new = $transformer->check_new($data);
if ($has_new) { if ($has_new) {
$media->set('field_complete', FALSE); $media->set('field_complete', FALSE);
} else { }
$transformer->populate_media($data, $media); else {
} $transformer->populate_media($data, $media);
}
} }
/** /**
* Implements hook_media_update(). * Implements hook_media_update().
*/ */
function islandora_fits_media_update(MediaInterface $media) { function islandora_fits_media_update(MediaInterface $media) {
if ($media->bundle() != 'fits_technical_metadata') { if ($media->bundle() != 'fits_technical_metadata') {
return; return;
} }
if ($media->get('field_complete')->value == FALSE) { if ($media->get('field_complete')->value == FALSE) {
$transformer = \Drupal::getContainer()->get('islandora_fits.transformxml'); $transformer = \Drupal::getContainer()->get('islandora_fits.transformxml');
$file_id = $media->get('field_media_file')->getValue()[0]['target_id']; $file_id = $media->get('field_media_file')->getValue()[0]['target_id'];
$file = File::load($file_id); $file = File::load($file_id);
$data = file_get_contents($file->getFileUri()); $data = file_get_contents($file->getFileUri());
$transformer->add_media_fields($data); $transformer->add_media_fields($data);
$new_media = Media::load($media->id()); $new_media = Media::load($media->id());
$new_media->set('field_complete', TRUE); $new_media->set('field_complete', TRUE);
$new_media->save(); $new_media->save();
} }
} }
/** /**
* Implements hook_media_insert(). * Implements hook_media_insert().
*/ */
function islandora_fits_media_insert(MediaInterface $media) { function islandora_fits_media_insert(MediaInterface $media) {
if ($media->bundle() != 'fits_technical_metadata') { if ($media->bundle() != 'fits_technical_metadata') {
return; return;
} }
islandora_fits_media_update($media); islandora_fits_media_update($media);
} }
/** /**
* Implements hook_entity_extra_field_info(). * Implements hook_entity_extra_field_info().
*/ */
function islandora_fits_entity_extra_field_info() { function islandora_fits_entity_extra_field_info() {
$extra = []; $extra = [];
$extra['node']['islandora_object']['display']['islandora_fits_checksum'] = array( $extra['node']['islandora_object']['display']['islandora_fits_checksum'] = [
'label' => t('File Checksum'), 'label' => t('File Checksum'),
'description' => t('Checksum as discovered by FITs webservice'), 'description' => t('Checksum as discovered by FITs webservice'),
'weight' => 100, 'weight' => 100,
'visible' => TRUE, 'visible' => TRUE,
); ];
return $extra; return $extra;
} }
/** /**
* Implements hook_entity_view(). * Implements hook_entity_view().
*/ */
function islandora_fits_entity_view(array &$build, $entity, $display, $view_mode) { function islandora_fits_entity_view(array &$build, $entity, $display, $view_mode) {
$route_match_item = \Drupal::routeMatch()->getParameters()->all(); $route_match_item = \Drupal::routeMatch()->getParameters()->all();
$current_entity = reset($route_match_item); $current_entity = reset($route_match_item);
if ($entity === $current_entity) {
$medias = \Drupal::entityQuery( if ($entity === $current_entity) {
'media') $medias = \Drupal::entityQuery(
->condition('field_media_of', $entity->id()) 'media')
->condition('bundle', 'fits_technical_metadata') ->condition('field_media_of', $entity->id())
->execute(); ->condition('bundle', 'fits_technical_metadata')
$mid = \reset($medias); ->execute();
if ($mid) { $mid = \reset($medias);
$fits = Media::load($mid); if ($mid) {
$checksum = $fits->get('fits_ois_file_information_md5che')->value; $fits = Media::load($mid);
if ($checksum) { $checksum = $fits->get('fits_ois_file_information_md5che')->value;
$build['islandora_fits_checksum'] = [ if ($checksum) {
'#type' => 'container', $build['islandora_fits_checksum'] = [
'#attributes' => [ '#type' => 'container',
'id' => 'field-islandora-checksum', '#attributes' => [
], 'id' => 'field-islandora-checksum',
'checksum' => [ ],
'#type' => 'item', 'checksum' => [
'#title' => t('MD5 Checksum'), '#type' => 'item',
'internal_uri' => [ '#title' => t('MD5 Checksum'),
'#type' => 'markup', 'internal_uri' => [
'#markup' => $checksum, '#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\Link;
use Drupal\Core\Url; use Drupal\Core\Url;
/** /**
* Plugin implementation of the 'fits_formatter' formatter. * Plugin implementation of the 'fits_formatter' formatter.
* *
@ -24,70 +23,70 @@ use Drupal\Core\Url;
*/ */
class FitsFormatter extends FormatterBase { class FitsFormatter extends FormatterBase {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function defaultSettings() { public static function defaultSettings() {
return [ return [
// Implement default settings. // Implement default settings.
] + parent::defaultSettings(); ] + parent::defaultSettings();
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function settingsForm(array $form, FormStateInterface $form_state) { public function settingsForm(array $form, FormStateInterface $form_state) {
return [ return [
// Implement settings form. // Implement settings form.
] + parent::settingsForm($form, $form_state); ] + parent::settingsForm($form, $form_state);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function settingsSummary() { public function settingsSummary() {
$summary = []; $summary = [];
// Implement settings summary. // Implement settings summary.
return $summary;
}
return $summary; /**
} * {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
/** foreach ($items as $delta => $item) {
* {@inheritdoc} $elements[$delta] = ['#markup' => $this->viewValue($item)];
*/ }
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
foreach ($items as $delta => $item) { return $elements;
$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) {
$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; namespace Drupal\islandora_fits\Services;
Use Drupal\Component\Utility\Xss; use Drupal\Component\Utility\Xss;
use Drupal\Core\DependencyInjection\ServiceProviderBase; 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\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldConfig;
@ -11,345 +14,404 @@ use Drupal\field\Entity\FieldConfig;
* Class XMLTransform. * Class XMLTransform.
*/ */
class XMLTransform extends ServiceProviderBase { 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; * XMLTransform constructor.
private $forbidden; *
private $messenger; * @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. * Transforms FITS xml into renderable array.
*/ *
public function __construct($renderer, $entityManager, $messenger) { * @param string $input_xml
$this->renderer = $renderer; * Xml to be transformed.
$this->entityManager = $entityManager; *
$this->messenger = $messenger; * @return array|null
$this->forbidden = ['-', ' ']; * 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);
} }
try {
/** $xml = new \SimpleXMLElement($input_xml);
* Transforms FITS xml into renderable array. }
* catch (\Exception $e) {
* @param $input_xml $this->messenger->addWarning(t('File does not contain valid xml.'));
* @return array return;
*/ }
public function transformFits($input_xml) { $xml->registerXPathNamespace('fits', 'http://hul.harvard.edu/ois/xml/ns/fits/fits_output');
$utf8 = mb_detect_encoding($input_xml, 'UTF-8', true); $fits_metadata = $this->islandoraFitsChildXpath($xml);
if (!$utf8) { $headers = [
$input_xml = utf8_encode($input_xml); 'label' => t('Field'),
} 'value' => t('Value'),
try { ];
$xml = new \SimpleXMLElement($input_xml); if (count($fits_metadata) == 0) {
} catch (\Exception $e) { $variables['islandora_fits_table']['empty'] = '';
$this->messenger->addWarning(t('File does not contain valid xml.')); $variables['islandora_fits_fieldsets']['empty'] = [
return; '#type' => 'markup',
} '#markup' => t('No technical metadata found.'),
$xml->registerXPathNamespace('fits', 'http://hul.harvard.edu/ois/xml/ns/fits/fits_output'); ];
$fits_metadata = $this->islandora_fits_child_xpath($xml); }
$headers = array( else {
'label' => t('Field'), foreach ($fits_metadata as $tool_name => $vals_array) {
'value' => t('Value'), $variables['islandora_fits_data'][$tool_name] = [];
); $rows = &$variables['islandora_fits_data'][$tool_name];
if (count($fits_metadata) == 0) { foreach ($vals_array as $field => $val_array) {
$variables['islandora_fits_table']['empty'] = ''; if (!array_key_exists($field, $rows) && $field != 'Filepath') {
$variables['islandora_fits_fieldsets']['empty'] = array( $rows[$field] = [
'#type' => 'markup', ['data' => Xss::filter($field), 'class' => 'islandora_fits_table_labels'],
'#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,
]; ];
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, $fieldsets = $variables['islandora_fits_fieldsets'];
'#attached' => [ $output = [];
'library' => [ foreach ($fieldsets as $title => $fieldset) {
'islandora_fits/islandora_fits', $output[] = [
] 'title' => $title,
] 'data' => $fieldset,
]; ];
return $renderable;
} }
$renderable = [
'#theme' => 'fits',
'#output' => $output,
'#attached' => [
'library' => [
'islandora_fits/islandora_fits',
],
],
];
return $renderable;
}
/** /**
* Finds the the first set of children from the FITS xml. * Finds the the first set of children from the FITS xml.
* *
* Once it has these it passes them off recursively. * Once it has these it passes them off recursively.
* *
* @param SimpleXMLElement $xml * @param SimpleXMLElement $xml
* The SimpleXMLElement to parse. * The SimpleXMLElement to parse.
* *
* @return array * @return array
* An array containing key/value pairs of fields and data. * An array containing key/value pairs of fields and data.
*/ */
private function islandora_fits_child_xpath($xml) { private function islandoraFitsChildXpath(SimpleXMLElement $xml) {
$results = $xml->xpath('/*|/*/fits:metadata'); $results = $xml->xpath('/*|/*/fits:metadata');
$output = array(); $output = [];
foreach ($results as $result) { foreach ($results as $result) {
$this->islandora_fits_children($result, $output); $this->islandoraFitsChildren($result, $output);
}
return $output;
} }
return $output;
}
/** /**
* Finds children for fits module. * Finds children for fits module.
* *
* Recursive function that searches continuously until * Recursive function that searches continuously until
* we grab the node's text value and add to * we grab the node's text value and add to
* the output array. * the output array.
* *
* @param SimpleXMLElement $child * @param SimpleXMLElement $child
* The current child that we are searching through. * The current child that we are searching through.
* * @param array $output
* @param array $output * An array containing key/value pairs of fields and data.
* An array containing key/value pairs of fields and data. */
*/ private function islandoraFitsChildren(SimpleXMLElement $child, array &$output) {
private function islandora_fits_children($child, &$output) { $grandchildren = $child->xpath('*/*');
$grandchildren = $child->xpath('*/*');
if (count($grandchildren) > 0) { if (count($grandchildren) > 0) {
foreach ($grandchildren as $grandchild) { foreach ($grandchildren as $grandchild) {
$this->islandora_fits_children($grandchild, $output); $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 { // No tool attribute.
$text_results = $child->xpath('text()'); else {
$tool_name = FALSE; if (isset($output['Unknown'][$field_label])) {
if ($text_results) { if (!in_array($output_text, $output['Unknown'][$field_label])) {
foreach ($text_results as $text) { $output['Unknown'][$field_label][] = $output_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;
}
}
}
} }
}
else {
$output['Unknown'][$field_label][] = $output_text;
}
} }
}
} }
}
} }
}
/** /**
* Builds display by parsing strings. * Builds display by parsing strings.
* *
* @param string $node_name * @param string $node_name
* Name of the current node that we will display. * Name of the current node that we will display.
* @param string $tool_name * @param string $tool_name
* Name of the tool used to generate the metadata. * Name of the tool used to generate the metadata.
* *
* @return array * @return array
* Constructed node name for output. * Constructed node name for output.
*/ */
private function islandora_fits_construct_output($node_name, $tool_name) { private function islandoraFitsContructOutput(string $node_name, string $tool_name) {
// Construct an arbitrary string with all capitals in it. // Construct an arbitrary string with all capitals in it.
$capitals = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $capitals = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$name_array = str_split($node_name); $name_array = str_split($node_name);
$space_position = array(); $space_position = [];
// Check to see which characters are capitals so we can split // Check to see which characters are capitals so we can split
// them up for cleaner display. // them up for cleaner display.
foreach ($name_array as $key => $value) { foreach ($name_array as $key => $value) {
if (strpos($capitals, $value) !== FALSE && $key !== 0) { if (strpos($capitals, $value) !== FALSE && $key !== 0) {
$space_position[] = $key; $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));
} }
if (count($space_position)) {
/** // Needed in event we add multiple spaces so need to keep track.
* Adds fields to content type. $pos_offset = 0;
* foreach ($space_position as $pos) {
* @param $input_xml $node_name = substr_replace($node_name, ' ', $pos + $pos_offset, 0);
* @throws \Drupal\Core\Entity\EntityStorageException $pos_offset++;
*/ }
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;
} }
$node_name = ucwords($node_name);
/** return ['name' => $node_name, 'tool' => ucwords($tool_name)];
* Populates media. }
*
* @param $input_xml /**
* @param $media * Adds fields to content type.
*/ *
public function populate_media($input_xml, &$media) { * @param string $input_xml
$data = $this->transformFits($input_xml); * Input to be transformed.
$all_fields = []; *
foreach ($data['#output'] as $datum) { * @throws \Drupal\Core\Entity\EntityStorageException
$all_fields = array_merge($all_fields, $this->harvest_values($datum)); *
} * @return bool
$to_add = []; * Fields to be formatted.
foreach ($all_fields as $label => $field_value) { */
$lower = strtolower($label); public function addMediaFields(string $input_xml) {
$normalized = str_replace($this->forbidden, '_', $lower); $fields_added = FALSE;
$field_name = substr("fits_$normalized", 0, 32); $data = $this->transformFits($input_xml);
$to_add[$field_name] = $field_value; $all_fields = [];
} foreach ($data['#output'] as $datum) {
foreach ($to_add as $field_name => $field_value) { $all_fields = array_merge($all_fields, $this->harvestValues($datum));
$media->set($field_name, $field_value); }
} $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. * Populates media.
* *
* @param $input * @param string $input_xml
* @return array * String to be transformed.
*/ * @param \Drupal\media\MediaInterface $media
private function harvest_values($input) { * Media to which transformed xml is to be added.
$fields = []; */
$label = str_replace(' ', '_', $input['title']); public function populateMedia(string $input_xml, MediaInterface &$media) {
$rows = $input['data']['#rows']; $data = $this->transformFits($input_xml);
foreach ($rows as $key => $value) { $all_fields = [];
$fields["{$label}_{$key}"] = $value['value']['data']; foreach ($data['#output'] as $datum) {
} $all_fields = array_merge($all_fields, $this->harvestValues($datum));
return $fields; }
$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, * Create standardized machine name fields.
'field_name' => $field_name, *
'field_value' => $field_value, * @param array $names
]; * Names to be normalized.
} *
return $normalized_names; * @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; * Checks to see if new fields are required.
$data = $this->transformFits($input_xml); *
$all_fields = []; * @param string $input_xml
foreach ($data['#output'] as $datum) { * Xml to be checked.
$all_fields = array_merge($all_fields, $this->harvest_values($datum)); *
} * @return bool
$to_process = $this->normalize_names($all_fields); * Whether fields havbe been added.
foreach ($to_process as $field) { */
$bundle_fields = $this->entityManager->getFieldDefinitions('media', 'fits_technical_metadata'); public function checkNew(string $input_xml) {
$bundle_keys = array_keys($bundle_fields); $fields_added = FALSE;
if (!in_array($field['field_name'], $bundle_keys)) { $data = $this->transformFits($input_xml);
$fields_added = TRUE; $all_fields = [];
} foreach ($data['#output'] as $datum) {
} $all_fields = array_merge($all_fields, $this->harvestValues($datum));
return $fields_added;
} }
$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