-
Daniel Berthereau authoredDaniel Berthereau authored
Mods.php 8.23 KiB
<?php
/**
* @author John Flatness
* @copyright Copyright 2009 John Flatness
* @copyright BibLibre, 2016
* @copyright Daniel Berthereau, 2014-2018
* @license http://www.gnu.org/licenses/gpl-3.0.txt
*/
namespace OaiPmhRepository\OaiPmh\Metadata;
use DOMElement;
use Omeka\Api\Representation\ItemRepresentation;
/**
* Class implementing MODS metadata output format.
*
* @link https://www.loc.gov/standards/mods/
*/
class Mods extends AbstractMetadata
{
/** OAI-PMH metadata prefix */
const METADATA_PREFIX = 'mods';
/** XML namespace for output format */
const METADATA_NAMESPACE = 'http://www.loc.gov/mods/v3';
/** XML schema for output format */
const METADATA_SCHEMA = 'http://www.loc.gov/standards/mods/v3/mods-3-3.xsd';
/**
* Appends MODS metadata.
*
* @link http://www.loc.gov/standards/mods/dcsimple-mods.html
*
* {@inheritDoc}
*/
public function appendMetadata(DOMElement $metadataElement, ItemRepresentation $item)
{
$document = $metadataElement->ownerDocument;
$mods = $document->createElementNS(self::METADATA_NAMESPACE, 'mods');
$metadataElement->appendChild($mods);
/* Must manually specify XML schema uri per spec, but DOM won't include
* a redundant xmlns:xsi attribute, so we just set the attribute
*/
$mods->setAttribute('xmlns:xsi', self::XML_SCHEMA_NAMESPACE_URI);
$mods->setAttribute('xsi:schemaLocation', self::METADATA_NAMESPACE
. ' ' . self::METADATA_SCHEMA);
$titles = $item->value('dcterms:title', ['all' => true, 'default' => []]);
foreach ($titles as $title) {
$titleInfo = $this->appendNewElement($mods, 'titleInfo');
$this->appendNewElement($titleInfo, 'title', (string) $title);
}
$creators = $item->value('dcterms:creator', ['all' => true, 'default' => []]);
foreach ($creators as $creator) {
$name = $this->appendNewElement($mods, 'name');
$this->appendNewElement($name, 'namePart', (string) $creator);
$role = $this->appendNewElement($name, 'role');
$roleTerm = $this->appendNewElement($role, 'roleTerm', 'creator');
$roleTerm->setAttribute('type', 'text');
}
$contributors = $item->value('dcterms:contributor', ['all' => true, 'default' => []]);
foreach ($contributors as $contributor) {
$name = $this->appendNewElement($mods, 'name');
$this->appendNewElement($name, 'namePart', (string) $contributor);
$role = $this->appendNewElement($name, 'role');
$roleTerm = $this->appendNewElement($role, 'roleTerm', 'contributor');
$roleTerm->setAttribute('type', 'text');
}
$subjects = $item->value('dcterms:subject', ['all' => true, 'default' => []]);
foreach ($subjects as $subject) {
$subjectTag = $this->appendNewElement($mods, 'subject');
$this->appendNewElement($subjectTag, 'topic', (string) $subject);
}
$descriptions = $item->value('dcterms:description', ['all' => true, 'default' => []]);
foreach ($descriptions as $description) {
$this->appendNewElement($mods, 'note', (string) $description);
}
$formats = $item->value('dcterms:format', ['all' => true, 'default' => []]);
foreach ($formats as $format) {
$physicalDescription = $this->appendNewElement($mods, 'physicalDescription');
$this->appendNewElement($physicalDescription, 'form', (string) $format);
}
$languages = $item->value('dcterms:language', ['all' => true, 'default' => []]);
foreach ($languages as $language) {
$languageElement = $this->appendNewElement($mods, 'language');
$languageTerm = $this->appendNewElement($languageElement, 'languageTerm', (string) $language);
$languageTerm->setAttribute('type', 'text');
}
$rights = $item->value('dcterms:rights', ['all' => true, 'default' => []]);
foreach ($rights as $right) {
$this->appendNewElement($mods, 'accessCondition', (string) $right);
}
$types = $item->value('dcterms:type', ['all' => true, 'default' => []]);
foreach ($types as $type) {
$this->appendNewElement($mods, 'genre', (string) $type);
}
$identifiers = $item->value('dcterms:identifier', ['all' => true, 'default' => []]);
foreach ($identifiers as $identifier) {
$text = (string) $identifier;
$idElement = $this->appendNewElement($mods, 'identifier', $text);
if ($this->_isUrl($text)) {
$idElement->setAttribute('type', 'uri');
} else {
$idElement->setAttribute('type', 'local');
}
}
$sources = $item->value('dcterms:source', ['all' => true, 'default' => []]);
foreach ($sources as $source) {
$this->_addRelatedItem($mods, (string) $source, true);
}
$relations = $item->value('dcterms:relation', ['all' => true, 'default' => []]);
foreach ($relations as $relation) {
$this->_addRelatedItem($mods, (string) $relation);
}
$location = $this->appendNewElement($mods, 'location');
if ($this->isGlobalRepository()) {
$mainSite = $this->settings->get('default_site');
if ($mainSite) {
$mainSiteSlug = $resource->getServiceLocator()->get('ControllerPluginManager')
->get('api')->read('sites', $mainSite)->getContent()->slug();
$append = $this->settings->get('oaipmhrepository_append_identifier_global');
$url = $item->siteUrl($mainSiteSlug, $append === 'absolute_site_url');
} else {
$url = $item->apiUrl();
}
} else {
$append = $this->settings->get('oaipmhrepository_append_identifier_site');
$url = $item->siteUrl(null, $append === 'absolute_site_url');
}
$url = $this->appendNewElement($location, 'url', $url);
$url->setAttribute('usage', 'primary display');
$publishers = $item->value('dcterms:publisher', ['all' => true, 'default' => []]);
$dates = $item->value('dcterms:date', ['all' => true, 'default' => []]);
// Empty originInfo sections are illegal
if (count($publishers) + count($dates) > 0) {
$originInfo = $this->appendNewElement($mods, 'originInfo');
foreach ($publishers as $publisher) {
$this->appendNewElement($originInfo, 'publisher', (string) $publisher);
}
foreach ($dates as $date) {
$this->appendNewElement($originInfo, 'dateOther', (string) $date);
}
}
$recordInfo = $this->appendNewElement($mods, 'recordInfo');
$this->appendNewElement($recordInfo, 'recordIdentifier', $item->id());
}
/**
* Add a relatedItem element.
*
* Checks the $text to see if it looks like a URL, and creates a
* location subelement if so. Otherwise, a titleInfo is used.
*
* @param DomElement $mods
* @param string $text
* @param bool $original
*/
private function _addRelatedItem($mods, $text, $original = false)
{
$relatedItem = $this->appendNewElement($mods, 'relatedItem');
if ($this->_isUrl($text)) {
$titleInfo = $this->appendNewElement($relatedItem, 'titleInfo');
$this->appendNewElement($titleInfo, 'title', $text);
} else {
$location = $this->appendNewElement($relatedItem, 'location');
$this->appendNewElement($location, 'url', $text);
}
if ($original) {
$relatedItem->setAttribute('type', 'original');
}
}
/**
* Returns whether the given test is (looks like) a URL.
*
* @param string $text
* @return bool
*/
private function _isUrl($text)
{
return strncmp($text, 'http://', 7) || strncmp($text, 'https://', 8);
}
public function getMetadataPrefix()
{
return self::METADATA_PREFIX;
}
public function getMetadataSchema()
{
return self::METADATA_SCHEMA;
}
public function getMetadataNamespace()
{
return self::METADATA_NAMESPACE;
}
}