@ -2,8 +2,11 @@
namespace Drupal\islandora_fits\Services;
namespace Drupal\islandora_fits\Services;
U se Drupal\Component\Utility\Xss;
u se 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,16 +14,42 @@ 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;
private $renderer;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
private $entityManager;
private $entityManager;
/**
* List of characters to switch.
*
* @var array
*/
private $forbidden;
private $forbidden;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
private $messenger;
private $messenger;
/**
/**
* Constructs a new XMLTransform object.
* 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($renderer, $entityManager, $messenger) {
public function __construct(RendererInterface $renderer, EntityManagerInterface $entityManager, MessengerInterface $messenger) {
$this->renderer = $renderer;
$this->renderer = $renderer;
$this->entityManager = $entityManager;
$this->entityManager = $entityManager;
$this->messenger = $messenger;
$this->messenger = $messenger;
@ -30,56 +59,62 @@ class XMLTransform extends ServiceProviderBase {
/**
/**
* Transforms FITS xml into renderable array.
* Transforms FITS xml into renderable array.
*
*
* @param $input_xml
* @param string $input_xml
* @return array
* Xml to be transformed.
*
* @return array|null
* Array of parsed results.
*/
*/
public function transformFits($input_xml) {
public function transformFits($input_xml) {
$utf8 = mb_detect_encoding($input_xml, 'UTF-8', true);
$utf8 = mb_detect_encoding($input_xml, 'UTF-8', TRUE );
if (!$utf8) {
if (!$utf8) {
$input_xml = utf8_encode($input_xml);
$input_xml = utf8_encode($input_xml);
}
}
try {
try {
$xml = new \SimpleXMLElement($input_xml);
$xml = new \SimpleXMLElement($input_xml);
} catch (\Exception $e) {
}
catch (\Exception $e) {
$this->messenger->addWarning(t('File does not contain valid xml.'));
$this->messenger->addWarning(t('File does not contain valid xml.'));
return;
return;
}
}
$xml->registerXPathNamespace('fits', 'http://hul.harvard.edu/ois/xml/ns/fits/fits_output');
$xml->registerXPathNamespace('fits', 'http://hul.harvard.edu/ois/xml/ns/fits/fits_output');
$fits_metadata = $this->islandora_fits_child_x path($xml);
$fits_metadata = $this->islandoraFitsChildX path($xml);
$headers = array(
$headers = [
'label' => t('Field'),
'label' => t('Field'),
'value' => t('Value'),
'value' => t('Value'),
) ;
] ;
if (count($fits_metadata) == 0) {
if (count($fits_metadata) == 0) {
$variables['islandora_fits_table']['empty'] = '';
$variables['islandora_fits_table']['empty'] = '';
$variables['islandora_fits_fieldsets']['empty'] = array(
$variables['islandora_fits_fieldsets']['empty'] = [
'#type' => 'markup',
'#type' => 'markup',
'#markup' => t('No technical metadata found.'),
'#markup' => t('No technical metadata found.'),
);
];
} else {
}
else {
foreach ($fits_metadata as $tool_name => $vals_array) {
foreach ($fits_metadata as $tool_name => $vals_array) {
$variables['islandora_fits_data'][$tool_name] = array() ;
$variables['islandora_fits_data'][$tool_name] = [] ;
$rows = &$variables['islandora_fits_data'][$tool_name];
$rows = &$variables['islandora_fits_data'][$tool_name];
foreach ($vals_array as $field => $val_array) {
foreach ($vals_array as $field => $val_array) {
if (!array_key_exists($field, $rows) & & $field != 'Filepath') {
if (!array_key_exists($field, $rows) & & $field != 'Filepath') {
$rows[$field] = array(
$rows[$field] = [
array( 'data' => Xss::filter($field), 'class' => 'islandora_fits_table_labels') ,
[ 'data' => Xss::filter($field), 'class' => 'islandora_fits_table_labels'] ,
) ;
] ;
foreach ($val_array as $value) {
foreach ($val_array as $value) {
if (!isset($rows[$field]['value'])) {
if (!isset($rows[$field]['value'])) {
$rows[$field]['value'] = array('data' => Xss::filter($value), 'class' => 'islandora_fits_table_values');
$rows[$field]['value'] = ['data' => Xss::filter($value), 'class' => 'islandora_fits_table_values'];
} else {
}
else {
$data = $rows[$field]['value']['data'] .= ' - ' . Xss::filter($value);
$data = $rows[$field]['value']['data'] .= ' - ' . Xss::filter($value);
$rows[$field]['value'] = array('data' => $data, 'class' => 'islandora_fits_table_values') ;
$rows[$field]['value'] = ['data' => $data, 'class' => 'islandora_fits_table_values'] ;
}
}
}
}
}
}
$table_attributes = array('class' => array('islandora_fits_table')) ;
$table_attributes = ['class' => ['islandora_fits_table']] ;
$table = array(
$table = [
'header' => $headers,
'header' => $headers,
'rows' => $rows,
'rows' => $rows,
'attributes' => $table_attributes,
'attributes' => $table_attributes,
) ;
] ;
$variables['islandora_fits_table'][$tool_name] = $table;
$variables['islandora_fits_table'][$tool_name] = $table;
$variables['islandora_fits_fieldsets'][$tool_name] = [
$variables['islandora_fits_fieldsets'][$tool_name] = [
'#theme' => 'table',
'#theme' => 'table',
@ -105,8 +140,8 @@ class XMLTransform extends ServiceProviderBase {
'#attached' => [
'#attached' => [
'library' => [
'library' => [
'islandora_fits/islandora_fits',
'islandora_fits/islandora_fits',
]
],
]
],
];
];
return $renderable;
return $renderable;
}
}
@ -122,11 +157,11 @@ class XMLTransform extends ServiceProviderBase {
* @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_c hildren($result, $output);
$this->islandoraFitsC hildren($result, $output);
}
}
return $output;
return $output;
}
}
@ -140,18 +175,18 @@ class XMLTransform extends ServiceProviderBase {
*
*
* @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 islandora_fits_children($child, & $output) {
private function islandoraFitsChildren(SimpleXMLElement $child, array & $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 {
else {
$text_results = $child->xpath('text()');
$text_results = $child->xpath('text()');
$tool_name = FALSE;
$tool_name = FALSE;
if ($text_results) {
if ($text_results) {
@ -163,7 +198,7 @@ class XMLTransform extends ServiceProviderBase {
}
}
$output_text = trim((string) $text);
$output_text = trim((string) $text);
if (!empty($output_text)) {
if (!empty($output_text)) {
$fits_out = $this->islandora_fits_construct_o utput($child->getName(), $tool_name);
$fits_out = $this->islandoraFitsContructO utput($child->getName(), $tool_name);
$tool_label = $fits_out['tool'];
$tool_label = $fits_out['tool'];
$field_label = $fits_out['name'];
$field_label = $fits_out['name'];
// Need to check if the label already exists in our output
// Need to check if the label already exists in our output
@ -172,21 +207,25 @@ class XMLTransform extends ServiceProviderBase {
if (isset($output[$tool_label])) {
if (isset($output[$tool_label])) {
if (!array_key_exists($field_label, $output[$tool_label])) {
if (!array_key_exists($field_label, $output[$tool_label])) {
$output[$tool_label][$field_label][] = $output_text;
$output[$tool_label][$field_label][] = $output_text;
} else {
}
else {
if (!in_array($output_text, $output[$tool_label][$field_label])) {
if (!in_array($output_text, $output[$tool_label][$field_label])) {
$output[$tool_label][$field_label][] = $output_text;
$output[$tool_label][$field_label][] = $output_text;
}
}
}
}
} else {
}
else {
$output[$tool_label][$field_label][] = $output_text;
$output[$tool_label][$field_label][] = $output_text;
}
}
} // No tool attribute.
}
// No tool attribute.
else {
else {
if (isset($output['Unknown'][$field_label])) {
if (isset($output['Unknown'][$field_label])) {
if (!in_array($output_text, $output['Unknown'][$field_label])) {
if (!in_array($output_text, $output['Unknown'][$field_label])) {
$output['Unknown'][$field_label][] = $output_text;
$output['Unknown'][$field_label][] = $output_text;
}
}
} else {
}
else {
$output['Unknown'][$field_label][] = $output_text;
$output['Unknown'][$field_label][] = $output_text;
}
}
}
}
@ -207,11 +246,11 @@ class XMLTransform extends ServiceProviderBase {
* @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.
@ -230,23 +269,28 @@ class XMLTransform extends ServiceProviderBase {
}
}
$node_name = ucwords($node_name);
$node_name = ucwords($node_name);
return array('name' => $node_name, 'tool' => ucwords($tool_name)) ;
return ['name' => $node_name, 'tool' => ucwords($tool_name)] ;
}
}
/**
/**
* Adds fields to content type.
* Adds fields to content type.
*
*
* @param $input_xml
* @param string $input_xml
* Input to be transformed.
*
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Drupal\Core\Entity\EntityStorageException
*
* @return bool
* Fields to be formatted.
*/
*/
public function add_media_fields($input_xml) {
public function addMediaFields(string $input_xml) {
$fields_added = FALSE;
$fields_added = FALSE;
$data = $this->transformFits($input_xml);
$data = $this->transformFits($input_xml);
$all_fields = [];
$all_fields = [];
foreach ($data['#output'] as $datum) {
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvest_v alues($datum));
$all_fields = array_merge($all_fields, $this->harvestV alues($datum));
}
}
$to_process = $this->normalize_n ames($all_fields);
$to_process = $this->normalizeN ames($all_fields);
foreach ($to_process as $field) {
foreach ($to_process as $field) {
$exists = FieldStorageConfig::loadByName('media', $field['field_name']);
$exists = FieldStorageConfig::loadByName('media', $field['field_name']);
if (!$exists) {
if (!$exists) {
@ -275,14 +319,16 @@ class XMLTransform extends ServiceProviderBase {
/**
/**
* Populates media.
* Populates media.
*
*
* @param $input_xml
* @param string $input_xml
* @param $media
* String to be transformed.
* @param \Drupal\media\MediaInterface $media
* Media to which transformed xml is to be added.
*/
*/
public function populate_media($input_xml, & $media) {
public function populateMedia(string $input_xml, MediaInterface & $media) {
$data = $this->transformFits($input_xml);
$data = $this->transformFits($input_xml);
$all_fields = [];
$all_fields = [];
foreach ($data['#output'] as $datum) {
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvest_v alues($datum));
$all_fields = array_merge($all_fields, $this->harvestV alues($datum));
}
}
$to_add = [];
$to_add = [];
foreach ($all_fields as $label => $field_value) {
foreach ($all_fields as $label => $field_value) {
@ -299,10 +345,13 @@ class XMLTransform extends ServiceProviderBase {
/**
/**
* Extracts and labels content.
* Extracts and labels content.
*
*
* @param $input
* @param array $input
* Values to be harvested and prepped.
*
* @return array
* @return array
* Fields prepped for display.
*/
*/
private function harvest_values( $input) {
private function harvestValues(array $input) {
$fields = [];
$fields = [];
$label = str_replace(' ', '_', $input['title']);
$label = str_replace(' ', '_', $input['title']);
$rows = $input['data']['#rows'];
$rows = $input['data']['#rows'];
@ -317,9 +366,12 @@ class XMLTransform extends ServiceProviderBase {
* Create standardized machine name fields.
* Create standardized machine name fields.
*
*
* @param array $names
* @param array $names
* Names to be normalized.
*
* @return array
* @return array
* Normalized names.
*/
*/
private function normalize_n ames(array $names) {
private function normalizeN ames(array $names) {
$normalized_names = [];
$normalized_names = [];
foreach ($names as $label => $field_value) {
foreach ($names as $label => $field_value) {
$lower = strtolower($label);
$lower = strtolower($label);
@ -335,14 +387,23 @@ class XMLTransform extends ServiceProviderBase {
return $normalized_names;
return $normalized_names;
}
}
public function check_new($input_xml) {
/**
* 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;
$fields_added = FALSE;
$data = $this->transformFits($input_xml);
$data = $this->transformFits($input_xml);
$all_fields = [];
$all_fields = [];
foreach ($data['#output'] as $datum) {
foreach ($data['#output'] as $datum) {
$all_fields = array_merge($all_fields, $this->harvest_values($datum));
$all_fields = array_merge($all_fields, $this->harvestV alues($datum));
}
}
$to_process = $this->normalize_names($all_fields);
$to_process = $this->normalizeN ames($all_fields);
foreach ($to_process as $field) {
foreach ($to_process as $field) {
$bundle_fields = $this->entityManager->getFieldDefinitions('media', 'fits_technical_metadata');
$bundle_fields = $this->entityManager->getFieldDefinitions('media', 'fits_technical_metadata');
$bundle_keys = array_keys($bundle_fields);
$bundle_keys = array_keys($bundle_fields);
@ -352,4 +413,5 @@ class XMLTransform extends ServiceProviderBase {
}
}
return $fields_added;
return $fields_added;
}
}
}
}