mirror of
https://github.com/opencultureconsulting/oai-pmh2.git
synced 2025-04-06 00:00:47 +02:00
264 lines
6.6 KiB
PHP
264 lines
6.6 KiB
PHP
|
<?php
|
||
|
|
||
|
/**
|
||
|
* OAI-PMH 2.0 Data Provider
|
||
|
* Copyright (C) 2023 Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace OCC\OaiPmh2\Database;
|
||
|
|
||
|
use DateTime;
|
||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||
|
use Doctrine\Common\Collections\Collection;
|
||
|
use Doctrine\ORM\Mapping as ORM;
|
||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||
|
use Symfony\Component\Validator\Exception\ValidationFailedException;
|
||
|
use Symfony\Component\Validator\Validation;
|
||
|
|
||
|
/**
|
||
|
* Doctrine/ORM Entity for records.
|
||
|
*
|
||
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||
|
* @package opencultureconsulting/oai-pmh2
|
||
|
*/
|
||
|
#[ORM\Entity]
|
||
|
#[ORM\Table(name: 'records')]
|
||
|
class Record
|
||
|
{
|
||
|
/**
|
||
|
* The record identifier.
|
||
|
*/
|
||
|
#[ORM\Id]
|
||
|
#[ORM\Column(type: 'string')]
|
||
|
private string $identifier;
|
||
|
|
||
|
/**
|
||
|
* The associated format.
|
||
|
*/
|
||
|
#[ORM\Id]
|
||
|
#[ORM\ManyToOne(targetEntity: Format::class, inversedBy: 'records')]
|
||
|
#[ORM\JoinColumn(name: 'format', referencedColumnName: 'prefix')]
|
||
|
private Format $format;
|
||
|
|
||
|
/**
|
||
|
* The date and time of last change.
|
||
|
*/
|
||
|
#[ORM\Column(name: 'last_changed', type: 'datetime')]
|
||
|
private DateTime $lastChanged;
|
||
|
|
||
|
/**
|
||
|
* The record's content.
|
||
|
*/
|
||
|
#[ORM\Column(type: 'text')]
|
||
|
private string $content = '';
|
||
|
|
||
|
/**
|
||
|
* Collection of associated sets.
|
||
|
*
|
||
|
* @var Collection<int, Set>
|
||
|
*/
|
||
|
#[ORM\ManyToMany(targetEntity: Set::class, inversedBy: 'records', indexBy: 'spec')]
|
||
|
#[ORM\JoinTable(name: 'records_sets')]
|
||
|
#[ORM\JoinColumn(name: 'record_identifier', referencedColumnName: 'identifier')]
|
||
|
#[ORM\JoinColumn(name: 'record_format', referencedColumnName: 'format')]
|
||
|
#[ORM\InverseJoinColumn(name: 'set_spec', referencedColumnName: 'spec')]
|
||
|
private Collection $sets;
|
||
|
|
||
|
/**
|
||
|
* Get the record's content.
|
||
|
*
|
||
|
* @return string The record's content
|
||
|
*/
|
||
|
public function getContent(): string
|
||
|
{
|
||
|
return $this->content;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the record identifier.
|
||
|
*
|
||
|
* @return string The record identifier
|
||
|
*/
|
||
|
public function getIdentifier(): string
|
||
|
{
|
||
|
return $this->identifier;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update bi-directional association with format.
|
||
|
*
|
||
|
* @param Format $format The metadata prefix
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
private function addFormat(Format $format): void
|
||
|
{
|
||
|
$this->format = $format;
|
||
|
$format->addRecord($this);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Associate the record with a set.
|
||
|
*
|
||
|
* @param Set $set The set
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function addSet(Set $set): void
|
||
|
{
|
||
|
if (!$this->sets->contains($set)) {
|
||
|
$this->sets->add($set);
|
||
|
$set->addRecord($this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the associated format.
|
||
|
*
|
||
|
* @return Format The associated format
|
||
|
*/
|
||
|
public function getFormat(): Format
|
||
|
{
|
||
|
return $this->format;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the date and time of last change.
|
||
|
*
|
||
|
* @return DateTime The datetime of last change
|
||
|
*/
|
||
|
public function getLastChanged(): DateTime
|
||
|
{
|
||
|
return $this->lastChanged;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get a collection of associated sets.
|
||
|
*
|
||
|
* @return Collection<int, Set> The associated sets
|
||
|
*/
|
||
|
public function getSets(): Collection
|
||
|
{
|
||
|
return $this->sets;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove record from set.
|
||
|
*
|
||
|
* @param Set $set The set
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function removeSet(Set $set): void
|
||
|
{
|
||
|
if ($this->sets->contains($set)) {
|
||
|
$this->sets->removeElement($set);
|
||
|
$set->removeRecord($this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set record's content.
|
||
|
*
|
||
|
* @param string $data The record's content
|
||
|
* @param bool $validate Should the input be validated?
|
||
|
*
|
||
|
* @return void
|
||
|
*
|
||
|
* @throws ValidationFailedException
|
||
|
*/
|
||
|
public function setContent(string $data, bool $validate = true): void
|
||
|
{
|
||
|
$data = trim($data);
|
||
|
if ($validate && $data !== '') {
|
||
|
try {
|
||
|
$data = $this->validate($data);
|
||
|
} catch (ValidationFailedException $exception) {
|
||
|
throw $exception;
|
||
|
}
|
||
|
}
|
||
|
$this->content = $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set date and time of last change.
|
||
|
*
|
||
|
* @param ?DateTime $dateTime The datetime of last change or NULL for "NOW"
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function setLastChanged(?DateTime $dateTime = null): void
|
||
|
{
|
||
|
if (!isset($dateTime)) {
|
||
|
$dateTime = new DateTime();
|
||
|
}
|
||
|
$this->lastChanged = $dateTime;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Validate XML content.
|
||
|
*
|
||
|
* @param string $xml The XML string
|
||
|
*
|
||
|
* @return string The validated XML string
|
||
|
*
|
||
|
* @throws ValidationFailedException
|
||
|
*/
|
||
|
protected function validate(string $xml): string
|
||
|
{
|
||
|
$validator = Validation::createValidator();
|
||
|
$violations = $validator->validate($xml, new Assert\Type('string'));
|
||
|
if ($violations->count() > 0) {
|
||
|
throw new ValidationFailedException(null, $violations);
|
||
|
}
|
||
|
return $xml;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get new entity of record.
|
||
|
*
|
||
|
* @param string $identifier The record identifier
|
||
|
* @param Format $format The format
|
||
|
* @param string $data The record's content
|
||
|
*
|
||
|
* @throws ValidationFailedException
|
||
|
*/
|
||
|
public function __construct(string $identifier, Format $format, string $data = '')
|
||
|
{
|
||
|
try {
|
||
|
$this->identifier = $identifier;
|
||
|
$this->addFormat($format);
|
||
|
$this->setContent($data);
|
||
|
$this->setLastChanged();
|
||
|
$this->sets = new ArrayCollection();
|
||
|
} catch (ValidationFailedException $exception) {
|
||
|
throw $exception;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the record's content.
|
||
|
*
|
||
|
* @return string The record's content
|
||
|
*/
|
||
|
public function __toString(): string
|
||
|
{
|
||
|
return $this->content;
|
||
|
}
|
||
|
}
|