- DOI implementation wit unit testing

This commit is contained in:
Arno Kaimbacher 2021-02-26 17:02:07 +01:00
parent 7f9bd089b1
commit 9b6a6469d7
20 changed files with 2128 additions and 360 deletions

View File

@ -7,6 +7,12 @@
"settings": { "settings": {
// "phpfmt.php_bin": "\"C:\\ProgramData\\scoop\\apps\\php-nts\\current\\php.exe\"", // "phpfmt.php_bin": "\"C:\\ProgramData\\scoop\\apps\\php-nts\\current\\php.exe\"",
"phpfmt.php_bin": "php", "phpfmt.php_bin": "php",
"phpfmt.psr2": true "phpfmt.psr2": true,
"phpcs.standard": "PSR2",
"phpcs.executablePath": "C:\\Users\\arno\\scoop\\apps\\composer\\current\\home\\vendor\\bin\\phpcs",
"phpsab.standard": "PSR2",
"phpsab.executablePathCBF": "C:\\Users\\arno\\scoop\\apps\\composer\\current\\home\\vendor\\bin\\phpcbf.bat",
"phpsab.executablePathCS":"C:\\Users\\arno\\scoop\\apps\\composer\\current\\home\\vendor\\bin\\phpcs.bat",
"phpsab.snifferEnable": true
} }
} }

View File

@ -0,0 +1,203 @@
<?php
namespace App\Http\Controllers;
use App\Interfaces\DOIInterface;
use App\Models\Dataset;
use App\Models\DatasetIdentifier;
use Illuminate\Http\Request;
use App\Models\Oai\OaiModelError;
use App\Exceptions\OaiModelException;
use Illuminate\Support\Facades\Log;
class DoiController extends Controller
{
protected $doiService;
protected $LaudatioUtils;
/**
* Holds xml representation of document information to be processed.
*
* @var \DomDocument Defaults to null.
*/
protected $xml = null;
/**
* Holds the stylesheet for the transformation.
*
* @var \DomDocument Defaults to null.
*/
protected $xslt = null;
/**
* Holds the xslt processor.
*
* @var \XSLTProcessor Defaults to null.
*/
protected $proc = null;
/**
* DOIController constructor.
* @param DoiInterface $DOIService
*/
public function __construct(DoiInterface $DoiClient)
{
$this->doiClient = $DoiClient;
$this->xml = new \DomDocument();
$this->proc = new \XSLTProcessor();
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create(Request $request)
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$dataId = $request->input('publish_id');
// Setup stylesheet
$this->loadStyleSheet(public_path() .'\prefixes\doi_datacite.xslt');
// set timestamp
$date = new \DateTime();
$unixTimestamp = $date->getTimestamp();
$this->proc->setParameter('', 'unixTimestamp', $unixTimestamp);
$prefix = config('tethys.datacite_prefix');
$this->proc->setParameter('', 'prefix', $prefix);
$repIdentifier = "tethys";
$this->proc->setParameter('', 'repIdentifier', $repIdentifier);
$this->xml->appendChild($this->xml->createElement('Datasets'));
$dataset = Dataset::where('publish_id', '=', $dataId)->firstOrFail();
if (is_null($dataset)) {
throw new OaiModelException('Dataset is not available for registering DOI!', OaiModelError::NORECORDSMATCH);
}
$dataset->fetchValues();
$xmlModel = new \App\Library\Xml\XmlModel();
$xmlModel->setModel($dataset);
$xmlModel->excludeEmptyFields();
$cache = ($dataset->xmlCache) ? $dataset->xmlCache : new \App\Models\XmlCache();
$xmlModel->setXmlCache($cache);
$domNode = $xmlModel->getDomDocument()->getElementsByTagName('Rdr_Dataset')->item(0);
$node = $this->xml->importNode($domNode, true);
$this->addSpecInformation($node, 'data-type:' . $dataset->type);
$this->xml->documentElement->appendChild($node);
$xmlMeta = $this->proc->transformToXML($this->xml);
Log::alert($xmlMeta);
//create doiValue and correspunfing landingpage of tehtys
$doiValue = $prefix . '/tethys.' . $dataset->publish_id;
$appUrl = config('app.url');
$landingPageUrl = $appUrl . "/dataset/" . $dataset->publish_id;
$response = $this->doiClient->registerDoi($doiValue, $xmlMeta, $landingPageUrl);
if ($response->getStatusCode() == 201) {
$doi = new DatasetIdentifier();
$doi['value'] = $doiValue;
$doi['dataset_id'] = $dataset->id;
$doi['type'] = "doi";
$doi['status'] = "registered";
$doi['registration_ts'] = now();
// $doi->save();
}
}
/**
* Display the specified resource.
*
* @param \App\Models\DatasetIdentifier $doi
* @return \Illuminate\Http\Response
*/
public function show(DatasetIdentifier $doi)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\DatasetIdentifier $doi
* @return \Illuminate\Http\Response
*/
public function edit(DatasetIdentifier $doi)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\DatasetIdentifier $doi
* @return \Illuminate\Http\Response
*/
public function update(Request $request, DatasetIdentifier $doi)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\DatasetIdentifier $doi
* @return \Illuminate\Http\Response
*/
public function destroy(DatasetIdentifier $doi)
{
//
}
/**
* Load an xslt stylesheet.
*
* @return void
*/
private function loadStyleSheet($stylesheet)
{
$this->xslt = new \DomDocument;
$this->xslt->load($stylesheet);
$this->proc->importStyleSheet($this->xslt);
if (isset($_SERVER['HTTP_HOST'])) {
$this->proc->setParameter('', 'host', $_SERVER['HTTP_HOST']);
}
//$this->proc->setParameter('', 'server', $this->getRequest()->getBaseUrl());
}
private function addSpecInformation(\DOMNode $document, $information)
{
$setSpecAttribute = $this->xml->createAttribute('Value');
$setSpecAttributeValue = $this->xml->createTextNode($information);
$setSpecAttribute->appendChild($setSpecAttributeValue);
$setSpecElement = $this->xml->createElement('SetSpec');
//$setSpecElement =new \DOMElement("SetSpec");
$setSpecElement->appendChild($setSpecAttribute);
$document->appendChild($setSpecElement);
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Created by Visual Studio Code.
* User: kaiarn
* Date: 19.02.2021
*/
namespace App\Interfaces;
interface DoiInterface
{
public function registerDoi($doiValue, $xmlMeta, $landingPageUrl);
public function getMetadataForDoi($identifier);
public function updateMetadataForDoi($identifier, $new_meta);
public function deleteMetadataForDoi($identifier);
// public function deleteDoiByCurlRequest($doi);
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Models;
use App\Models\Dataset;
use Illuminate\Database\Eloquent\Model;
class DatasetIdentifier extends Model
{
protected $table = 'dataset_identifierss';
protected $guarded = array();
/**
* The dataset that belong to the DocumentIdentifier.
*/
public function dataset()
{
return $this->belongsTo(Dataset::class, 'document_id', 'id');
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* Visual Studio Code.
* User: kaiarn
* Date: 19.02.21
*/
namespace App\Providers;
use App\Tethys\Utils\DoiService;
use Illuminate\Support\ServiceProvider;
class DoiServiceProvider extends ServiceProvider
{
protected $defer = true;
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
$this->app->singleton('App\Interfaces\DoiInterface', function ($app) {
return new DoiService();
});
}
public function provides()
{
return [DoiService::class];
}
}

View File

@ -0,0 +1,212 @@
<?php
namespace App\Tethys\Utils;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use App\Interfaces\DoiInterface;
class DoiClient implements DoiInterface
{
private $username;
private $password;
private $serviceUrl;
public function __construct()
{
$datacite_environment = "production"; //config('tethys.datacite_environment');
if ($datacite_environment == "debug") {
$this->username = config('tethys.datacite_test_username');
$this->password = config('tethys.datacite_test_password');
$this->serviceUrl = config('tethys.test_datacite_service_url');
$this->prefix = config('tethys.datacite_prefix');
} elseif ($datacite_environment == "production") {
$this->username = config('tethys.datacite_username');
$this->password = config('tethys.datacite_password');
$this->serviceUrl = config('tethys.datacite_service_url');
$this->prefix = config('tethys.datacite_prefix');
}
if (is_null($this->username) || is_null($this->password) || is_null($this->serviceUrl)) {
$message = 'missing configuration settings to properly initialize DOI client';
Log::error($message);
throw new DoiClientException($message);
}
}
/**
* Creates a DOI or ARK with the given identifier
*
* @param string $identifier The desired DOI identifier e.g. '10.5072/tethys.999',
* @param $xmlMeta
* @param $landingPageUrl e.g. https://www.tethys.at/dataset/1
*
* @return GuzzleHttp\Psr7\Response The http response in the form of a Guzzle response
*/
public function registerDoi($doiValue, $xmlMeta, $landingPageUrl)
{
// Schritt 1: Metadaten als XML registrieren
$response = null;
$url = $this->serviceUrl . '/metadata/' . $doiValue;
try {
$client = new Client([
'auth' => [$this->username, $this->password],
// 'base_uri' => $url,
'verify' => false,
'headers' => [
'Content-Type' => 'application/xml;charset=UTF-8',
],
// 'body' => $xmlMeta,
]);
// Provide the body as a string.
$response = $client->request('PUT', $url, [
'body' => $xmlMeta,
]);
} catch (\Exception $e) {
$message = 'request to ' . $url . ' failed with ' . $e->getMessage();
// $this->log($message, 'err');
throw new DoiClientException($message);
}
// Response Codes
// 201 Created: operation successful
// 400 Bad Request: invalid XML, wrong prefix
// 401 Unauthorised: no login
// 403 Forbidden: login problem, quota exceeded
// 415 Wrong Content Type : Not including content type in the header.
// 422 Unprocessable Entity : invalid XML
if ($response->getStatusCode() != 201) {
$message = 'unexpected DataCite MDS response code ' . $response->getStatusCode();
// $this->log($message, 'err');
throw new DoiClientException($message);
}
// Schritt 2: Register the DOI name
// DOI und URL der Frontdoor des zugehörigen Dokuments übergeben
$url = $this->serviceUrl . '/doi/' . $doiValue;
try {
$client = new Client(
[
'auth' => [$this->username, $this->password],
'verify' => false,
'headers' => [
'Content-Type' => 'text/plain;charset=UTF-8',
],
]
);
$data = "doi=$doiValue\nurl=" . $landingPageUrl;
// $client->setRawData($data, 'text/plain;charset=UTF-8');
$response = $client->request('PUT', $url, [
'body' => $data,
'headers' => [
'Content-Type' => 'text/plain;charset=UTF-8',
],
]);
} catch (\Exception $e) {
$message = 'request to ' . $url . ' failed with ' . $e->getMessage();
// $this->log($message, 'err');
throw new DoiClientException($message);
}
// Response Codes
// 201 Created: operation successful
// 400 Bad Request: request body must be exactly two lines: DOI and URL; wrong domain, wrong prefix;
// 401 Unauthorised: no login
// 403 Forbidden: login problem, quota exceeded
// 412 Precondition failed: metadata must be uploaded first.
// $this->log('DataCite response status code (expected 201): ' . $response->getStatus());
// $this->log('DataCite response body: ' . $response->getBody());
if ($response->getStatusCode() != 201) {
$message = 'unexpected DataCite MDS response code ' . $response->getStatusCode();
// $this->log($message, 'err');
throw new DoiClientException($message);
}
return $response;
}
/* Response Status Codes
* 200 OK: operation successful
* 204 No Content : DOI is known to DataCite Metadata Store (MDS), but is not minted (or not resolvable e.g. due
* to handle's latency)
* 401 Unauthorized: no login
* 403 Login problem or dataset belongs to another party
* 404 Not Found: DOI does not exist in our database (e.g. registration pending)
*
* @param $doiValue
* @param $landingPageURL
*
* @return bool Methode liefert true, wenn die DOI erfolgreich registiert wurde und die Prüfung positiv ausfällt.
*
* @throws ClientException
*
*/
public function checkDoi($doiValue, $landingPageURL): bool
{
$response = null;
$url = $this->serviceUrl . '/doi/' . $doiValue;
try {
$client = new Client([
'base_uri' => $this->serviceUrl . '/doi/' . $doiValue,
'auth' => [$this->username, $this->password],
'verify' => false,
]);
$response = $client->request('GET');
} catch (\Exception $e) {
$message = 'request to ' . $url . ' failed with ' . $e->getMessage();
Log::error($message);
// throw new \Exception($message);
return false;
}
$statusCode = $response->getStatusCode();
// in $body steht die URL zur Frontdoor, die mit der DOI verknüpft wurde
$body = $response->getBody();
// $this->log('DataCite response status code (expected 200): ' . $statusCode);
// $this->log('DataCite response body (expected ' . $landingPageURL . '): ' . $body);
return ($statusCode == 200 && $landingPageURL == $body);
}
public function getMetadataForDoi($identifier)
{
//
}
public function updateMetadataForDoi($identifier, $new_meta)
{
//
}
/**
* Markiert den Datensatz zur übergebenen DOI als inaktiv.
*
* @param $doiValue
*
* @throws ClientException
*/
public function deleteMetadataForDoi($doiValue)
{
$response = null;
$url = $this->serviceUrl . '/metadata/' . $doiValue;
try {
$client = new Client([
'base_uri' => $url,
'auth' => [$this->username, $this->password],
'verify' => false,
]);
$response = $client->request('DELETE');
} catch (\Exception $e) {
$message = 'request to ' . $url . ' failed with ' . $e->getMessage();
Log::error($message, 'err');
throw new DoiClientException($message);
}
// $this->log('DataCite response status code (expected 200): ' . $response->getStatus());
if ($response->getStatusCode() != 200) {
$message = 'unexpected DataCite MDS response code ' . $response->getStatusCode();
Log::error($message, 'err');
throw new DoiClientException($message);
}
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace App\Tethys\Utils;
class DoiClientException extends \Exception
{
}

View File

@ -15,8 +15,9 @@
"doctrine/dbal": "v2.4.2", "doctrine/dbal": "v2.4.2",
"felixkiss/uniquewith-validator": "^3.1", "felixkiss/uniquewith-validator": "^3.1",
"fideloper/proxy": "^4.0", "fideloper/proxy": "^4.0",
"guzzlehttp/guzzle": "^7.2",
"halpdesk/zizaco-entrust-laravel-6.0": "^1.9", "halpdesk/zizaco-entrust-laravel-6.0": "^1.9",
"laravel/framework": "^6.2", "laravel/framework": "^6.20",
"laravel/tinker": "^2.0", "laravel/tinker": "^2.0",
"laravelcollective/html": "^6.1", "laravelcollective/html": "^6.1",
"mcamara/laravel-localization": "^1.3", "mcamara/laravel-localization": "^1.3",
@ -24,8 +25,8 @@
"yajra/laravel-datatables-oracle": "^9.0" "yajra/laravel-datatables-oracle": "^9.0"
}, },
"require-dev": { "require-dev": {
"fzaninotto/faker": "^1.8", "fzaninotto/faker": "^1.9.1",
"phpunit/phpunit": "^7.0" "phpunit/phpunit": "^8.5.8|^9.3.3"
}, },
"autoload": { "autoload": {
"files": [ "files": [
@ -56,7 +57,8 @@
"post-autoload-dump": [ "post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi" "@php artisan package:discover --ansi"
] ],
"test": "php vendor/phpunit/phpunit/phpunit --testsuite Feature"
}, },
"config": { "config": {
"preferred-install": "dist", "preferred-install": "dist",

1265
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -178,15 +178,15 @@ return [
/* /*
* Application Service Providers... * Application Service Providers...
*/ */
'App\Providers\AppServiceProvider', App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class, App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class, // App\Providers\BroadcastServiceProvider::class,
'App\Providers\ConfigServiceProvider', App\Providers\ConfigServiceProvider::class,
'App\Providers\EventServiceProvider', App\Providers\EventServiceProvider::class,
'App\Providers\RouteServiceProvider', App\Providers\RouteServiceProvider::class,
// List off others providers... // List off others providers...
App\Providers\SolariumServiceProvider::class, App\Providers\SolariumServiceProvider::class,
App\Providers\DoiServiceProvider::class,
], ],
@ -203,9 +203,9 @@ return [
'aliases' => [ 'aliases' => [
'App' => 'Illuminate\Support\Facades\App', 'App' => Illuminate\Support\Facades\App::class,
'Arr' => Illuminate\Support\Arr::class, 'Arr' => Illuminate\Support\Arr::class,
'Artisan' => 'Illuminate\Support\Facades\Artisan', 'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class, 'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class, 'Blade' => Illuminate\Support\Facades\Blade::class,
'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
@ -219,10 +219,10 @@ return [
'Event' => 'Illuminate\Support\Facades\Event', 'Event' => 'Illuminate\Support\Facades\Event',
'File' => 'Illuminate\Support\Facades\File', 'File' => 'Illuminate\Support\Facades\File',
'Gate' => Illuminate\Support\Facades\Gate::class, 'Gate' => Illuminate\Support\Facades\Gate::class,
'Hash' => 'Illuminate\Support\Facades\Hash', 'Hash' => Illuminate\Support\Facades\Hash::class,
'Input' => 'Illuminate\Support\Facades\Input', 'Input' => Illuminate\Support\Facades\Input::class,
// 'Inspiring' => 'Illuminate\Foundation\Inspiring', // 'Inspiring' => 'Illuminate\Foundation\Inspiring',
'Lang' => 'Illuminate\Support\Facades\Lang', 'Lang' => Illuminate\Support\Facades\Lang::class,
'Log' => Illuminate\Support\Facades\Log::class, 'Log' => Illuminate\Support\Facades\Log::class,
'Mail' => 'Illuminate\Support\Facades\Mail', 'Mail' => 'Illuminate\Support\Facades\Mail',
'Notification' => Illuminate\Support\Facades\Notification::class, 'Notification' => Illuminate\Support\Facades\Notification::class,
@ -247,7 +247,8 @@ return [
// 'HTML' => 'Illuminate\Html\HtmlFacade', // 'HTML' => 'Illuminate\Html\HtmlFacade',
// 'Form' => 'Collective\Html\FormFacade', // 'Form' => 'Collective\Html\FormFacade',
// 'Html' => 'Collective\Html\HtmlFacade', // 'Html' => 'Collective\Html\HtmlFacade',
'Breadcrumbs' => DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs::class, // 'Breadcrumbs' => DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs::class,
'Breadcrumbs' => Diglactic\Breadcrumbs\Breadcrumbs::class,
//'Datatables' => Yajra\DataTables\Facades\DataTables::class //'Datatables' => Yajra\DataTables\Facades\DataTables::class
], ],

View File

@ -45,6 +45,18 @@ return [
*/ */
'connections' => [ 'connections' => [
'testing' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'pgsql'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'charset' => 'utf8',
'prefix' => '',
'schema' => env('DB_SCHEMA', 'public'),
'sslmode' => 'prefer',
],
'sqlite' => [ 'sqlite' => [
'driver' => 'sqlite', 'driver' => 'sqlite',
@ -56,9 +68,9 @@ return [
'driver' => 'pgsql', 'driver' => 'pgsql',
'host' => env('DB_HOST', 'pgsql'), 'host' => env('DB_HOST', 'pgsql'),
'port' => env('DB_PORT', '5432'), 'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'repository'), 'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME', 'opus4admin'), 'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD', 'opus4admin007'), 'password' => env('DB_PASSWORD'),
'charset' => 'utf8', 'charset' => 'utf8',
'prefix' => '', 'prefix' => '',
'schema' => env('DB_SCHEMA', 'public'), 'schema' => env('DB_SCHEMA', 'public'),
@ -68,10 +80,10 @@ return [
'sqlsrv' => [ 'sqlsrv' => [
'driver' => 'sqlsrv', 'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'zontik\test'), 'host' => env('DB_HOST'),
'database' => env('DB_DATABASE', 'opusdb'), 'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME', 'opus4'), 'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD', 'opus4007'), 'password' => env('DB_PASSWORD'),
'prefix' => '', 'prefix' => '',
], ],

13
config/tethys.php Normal file
View File

@ -0,0 +1,13 @@
<?php
return [
'repoid' => 3156505,
'ccBaseuri' => 'https://creativecommons.org/licenses/|/3.0/',
'datacite_username' => env('DATACITE_USERNAME'),
// 'datacite_test_username' => env('DATACITE_TEST_USERNAME'),
'datacite_password' => env('DATACITE_PASSWORD'),
// 'datacite_test_password' => env('DATACITE_TEST_PASSWORD'),
'datacite_service_url' => env('DATACITE_SERVICE_URL'),
// 'datacite_test_service_url' => env('DATACITE_TEST_SERVICE_URL'),
'datacite_prefix' => env('DATACITE_PREFIX'),
'base_domain' => 'https://www.tethys.at/',
];

View File

@ -0,0 +1,54 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateDatasetIdentifiersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('dataset_identifiers', function (Blueprint $table) {
// primary key
$table->increments('id');
// foreign key to: documents.id
$table->integer('dataset_id')->unsigned();
;
$table->foreign('dataset_id')->references('id')->on('documents')
->onUpdate('cascade')->onDelete('cascade');
// value of the identifier
$table->string('value', 255);
$table->enum(
'type',
["doi", "handle", "isbn", "issn", "url", "urn"]
);
// DOI registration status
$table->enum(
'status',
['draft', 'registered', 'findable']
)->nullable();
// timestamp of DOI registration
$table->timestamp('registration_ts');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('dataset_identifiers', function (Blueprint $table) {
//
});
}
}

10
doi_notes.txt Normal file
View File

@ -0,0 +1,10 @@
doi_notes:
php artisan make:controller DOIController --resource --model "Models\DatasetIdentifier"
composer require guzzlehttp/guzzle
php artisan make:migration create_dataset_identifiers_table --table="dataset_identifiers"

View File

@ -1,23 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
backupStaticAttributes="false" xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="bootstrap/autoload.php" bootstrap="vendor/autoload.php"
colors="true" colors="true"
convertErrorsToExceptions="true" cacheResult ="false">
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites> <testsuites>
<testsuite name="Application Test Suite"> <testsuite name="Application Test Suite">
<directory>./tests/</directory> <directory>./tests/</directory>
</testsuite> </testsuite>
<!-- <testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite> -->
<testsuite name="Feature">
<directory>./tests/Feature</directory>
</testsuite>
</testsuites> </testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php> <php>
<env name="APP_ENV" value="testing"/> <env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/> <server name="BCRYPT_ROUNDS" value="4"/>
<env name="SESSION_DRIVER" value="array"/> <server name="CACHE_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/> <server name="DB_CONNECTION" value="testing"/>
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="MAIL_DRIVER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
</php> </php>
</phpunit> </phpunit>

View File

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* This file is part of TETHYS.
*
* LICENCE
* TETHYS 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 2 of the Licence, or any later version.
* OPUS 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 OPUS; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @category Application
* @package Module_Oai
* @author Arno Kaimbacher <arno.kaimbacher@geologie.ac.at>
* @copyright Copyright (c) 2018-2019, GBA TETHYS development team
* @license http://www.gnu.org/licenses/gpl.html General Public License
*/
-->
<!--
/**
* Transforms the xml representation of an TETHYS model dataset to datacite
* xml as required by the OAI-PMH protocol.
*/
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:php="http://php.net/xsl" exclude-result-prefixes="php">
<xsl:output method="xml" indent="yes" />
<xsl:param name="unixTimestamp" />
<xsl:param name="prefix" />
<xsl:param name="repIdentifier" />
<!--create the head of oai response -->
<xsl:template match="Rdr_Dataset">
<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://datacite.org/schema/kernel-4" xsi:schemaLocation="http://datacite.org/schema/kernel-4 http://schema.datacite.org/meta/kernel-4.3/metadata.xsd">
<!-- <isReferenceQuality>true</isReferenceQuality>
<schemaVersion>4.3</schemaVersion>
<datacentreSymbol>RDR.GBA</datacentreSymbol> -->
<identifier identifierType="DOI">
<xsl:value-of select="$prefix" />
<xsl:text>/</xsl:text>
<xsl:value-of select="$repIdentifier" />
<xsl:text>.</xsl:text>
<xsl:value-of select="@PublishId" />
</identifier>
<!--<datacite:creator>-->
<creators>
<xsl:apply-templates select="PersonAuthor" mode="oai_datacite" />
</creators>
<titles>
<xsl:apply-templates select="TitleMain" mode="oai_datacite" />
<xsl:apply-templates select="TitleAdditional" mode="oai_datacite" />
</titles>
<publisher>
<!-- <xsl:value-of select="@PublisherName" /> -->
<xsl:value-of select="@CreatingCorporation" />
</publisher>
<publicationYear>
<xsl:value-of select="ServerDatePublished/@Year"/>
</publicationYear>
<subjects>
<xsl:apply-templates select="Subject" mode="oai_datacite" />
</subjects>
<language>
<xsl:value-of select="@Language" />
</language>
<xsl:if test="PersonContributor">
<contributors>
<xsl:apply-templates select="PersonContributor" mode="oai_datacite" />
</contributors>
</xsl:if>
<dates>
<xsl:call-template name="RdrDate2" mode="oai_datacite" />
</dates>
<resourceType resourceTypeGeneral="Dataset">
<xsl:text>Dataset</xsl:text>
<!-- <xsl:value-of select="@Type" /> -->
</resourceType>
<alternateIdentifiers>
<xsl:call-template name="AlternateIdentifier"/>
</alternateIdentifiers>
<xsl:if test="Reference">
<relatedIdentifiers>
<xsl:apply-templates select="Reference" mode="oai_datacite" />
</relatedIdentifiers>
</xsl:if>
<rightsList>
<xsl:apply-templates select="Licence" mode="oai_datacite" />
</rightsList>
<sizes>
<size>
<xsl:value-of select="count(File)"/>
<xsl:text> datasets</xsl:text>
</size>
</sizes>
<formats>
<xsl:apply-templates select="File/@MimeType" mode="oai_datacite" />
</formats>
<descriptions>
<xsl:apply-templates select="TitleAbstract" mode="oai_datacite" />
<xsl:apply-templates select="TitleAbstractAdditional" mode="oai_datacite" />
</descriptions>
<geoLocations>
<xsl:apply-templates select="Coverage" mode="oai_datacite" />
<!-- <geoLocation>
<geoLocationBox>
<westBoundLongitude>6.58987</westBoundLongitude>
<eastBoundLongitude>6.83639</eastBoundLongitude>
<southBoundLatitude>50.16</southBoundLatitude>
<northBoundLatitude>50.18691</northBoundLatitude>
</geoLocationBox>
</geoLocation> -->
</geoLocations>
</resource>
</xsl:template>
<xsl:template name="RdrDate2" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<xsl:if test="EmbargoDate and ($unixTimestamp &lt; EmbargoDate/@UnixTimestamp)">
<date>
<xsl:attribute name="dateType">Available</xsl:attribute>
<xsl:variable name="embargoDate" select="concat(
EmbargoDate/@Year, '-',
format-number(EmbargoDate/@Month,'00'), '-',
format-number(EmbargoDate/@Day,'00')
)" />
<xsl:value-of select="$embargoDate" />
</date>
</xsl:if>
<xsl:if test="CreatedAt">
<date>
<xsl:attribute name="dateType">Created</xsl:attribute>
<xsl:variable name="createdAt" select="concat(
CreatedAt/@Year, '-',
format-number(CreatedAt/@Month,'00'), '-',
format-number(CreatedAt/@Day,'00')
)" />
<xsl:value-of select="$createdAt" />
</date>
</xsl:if>
</xsl:template>
<xsl:template match="Coverage" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<geoLocation>
<geoLocationBox>
<westBoundLongitude>
<xsl:value-of select="@XMin" />
</westBoundLongitude>
<eastBoundLongitude>
<xsl:value-of select="@XMax" />
</eastBoundLongitude>
<southBoundLatitude>
<xsl:value-of select="@YMin" />
</southBoundLatitude>
<northBoundLatitude>
<xsl:value-of select="@YMax" />
</northBoundLatitude>
</geoLocationBox>
</geoLocation>
</xsl:template>
<xsl:template match="TitleAbstract" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<description>
<xsl:attribute name="xml:lang">
<xsl:value-of select="@Language" />
</xsl:attribute>
<xsl:if test="@Type != ''">
<xsl:attribute name="descriptionType">
<xsl:value-of select="@Type" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="@Value" />
</description>
</xsl:template>
<xsl:template match="TitleAbstractAdditional" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<description>
<xsl:attribute name="xml:lang">
<xsl:value-of select="@Language" />
</xsl:attribute>
<xsl:if test="@Type != ''">
<xsl:attribute name="descriptionType">
<xsl:value-of select="@Type" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="@Value" />
</description>
</xsl:template>
<xsl:template match="TitleMain" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<title>
<xsl:if test="@Language != ''">
<xsl:attribute name="xml:lang">
<xsl:value-of select="@Language" />
</xsl:attribute>
</xsl:if>
<xsl:if test="@Type != '' and @Type != 'Main'">
<xsl:attribute name="titleType">
<xsl:value-of select="@Type" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="@Value"/>
</title>
</xsl:template>
<xsl:template match="TitleAdditional" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<title>
<xsl:if test="@Language != ''">
<xsl:attribute name="xml:lang">
<xsl:value-of select="@Language" />
</xsl:attribute>
</xsl:if>
<xsl:if test="@Type != '' and @Type != 'Main'">
<xsl:attribute name="titleType">
<xsl:value-of select="@Type" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="@Value"/>
</title>
</xsl:template>
<xsl:template match="Subject" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<subject>
<xsl:if test="@Language != ''">
<xsl:attribute name="xml:lang">
<xsl:value-of select="@Language" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="@Value" />
</subject>
</xsl:template>
<xsl:template name="AlternateIdentifier" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<alternateIdentifier >
<xsl:attribute name="alternateIdentifierType">
<xsl:text>url</xsl:text>
</xsl:attribute>
<!-- <xsl:variable name="identifier" select="concat($repURL, '/dataset/', @Id)" /> -->
<xsl:value-of select="@landingpage"/>
</alternateIdentifier >
</xsl:template>
<xsl:template match="Reference" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<relatedIdentifier>
<xsl:attribute name="relatedIdentifierType">
<xsl:value-of select="@Type" />
</xsl:attribute>
<xsl:attribute name="relationType">
<xsl:value-of select="@Relation" />
</xsl:attribute>
<xsl:value-of select="@Value" />
</relatedIdentifier>
</xsl:template>
<xsl:template match="PersonContributor" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<contributor>
<xsl:if test="@ContributorType != ''">
<xsl:attribute name="contributorType">
<xsl:value-of select="@ContributorType" />
</xsl:attribute>
</xsl:if>
<contributorName>
<!-- <xsl:if test="@NameType != ''">
<xsl:attribute name="nameType">
<xsl:value-of select="@NameType" />
</xsl:attribute>
</xsl:if> -->
<xsl:value-of select="concat(@FirstName, ' ',@LastName)" />
</contributorName>
</contributor>
</xsl:template>
<xsl:template match="PersonAuthor" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<creator>
<creatorName>
<xsl:if test="@NameType != ''">
<xsl:attribute name="nameType">
<xsl:value-of select="@NameType" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="@LastName" />
<xsl:if test="@FirstName != ''">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:value-of select="@FirstName" />
<xsl:if test="@AcademicTitle != ''">
<xsl:text> (</xsl:text>
<xsl:value-of select="@AcademicTitle" />
<xsl:text>)</xsl:text>
</xsl:if>
</creatorName>
<givenName>
<xsl:value-of select="@FirstName" />
</givenName>
<familyName>
<xsl:value-of select="@LastName" />
</familyName>
<xsl:if test="@IdentifierOrcid != ''">
<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">
<xsl:value-of select="@IdentifierOrcid" />
</nameIdentifier>
</xsl:if>
<!--
<nameType><xsl:value-of select="@NameType" /></nameType>
</xsl:if> -->
<affiliation>GBA</affiliation>
</creator>
</xsl:template>
<xsl:template match="File/@MimeType" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<format>
<xsl:value-of select="." />
</format>
</xsl:template>
<xsl:template match="Licence" mode="oai_datacite"
xmlns="http://datacite.org/schema/kernel-4">
<rights>
<xsl:if test="@LinkLicence != ''">
<xsl:attribute name="rightsURI">
<xsl:value-of select="@LinkLicence" />
</xsl:attribute>
</xsl:if>
<xsl:attribute name="schemeURI">
<xsl:text>https://spdx.org/licenses/</xsl:text>
</xsl:attribute>
<xsl:attribute name="rightsIdentifierScheme">
<xsl:text>SPDX</xsl:text>
</xsl:attribute>
<xsl:attribute name="rightsIdentifier">
<xsl:text>CC-BY-NC-ND-4.0</xsl:text>
</xsl:attribute>
<xsl:value-of select="@NameLong" />
</rights>
<xsl:if test="@Name = 'CC BY' or @Name = 'CC BY-SA'">
<rights>
<xsl:attribute name="rightsURI">
<xsl:text>info:eu-repo/semantics/openAccess</xsl:text>
</xsl:attribute>
<xsl:text>Open Access</xsl:text>
</rights>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,5 +1,6 @@
<?php <?php
use DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs; // use DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs;
use Diglactic\Breadcrumbs\Breadcrumbs;
// Dashboard // Dashboard
Breadcrumbs::register('settings.dashboard', function ($trail) { Breadcrumbs::register('settings.dashboard', function ($trail) {

View File

@ -1,4 +1,5 @@
<?php <?php
namespace Tests;
class ExampleTest extends TestCase class ExampleTest extends TestCase
{ {
@ -11,7 +12,6 @@ class ExampleTest extends TestCase
public function testBasicExample() public function testBasicExample()
{ {
$response = $this->call('GET', '/'); $response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
} }
} }

View File

@ -0,0 +1,68 @@
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\Tethys\Utils\DoiClient;
use Illuminate\Http\Request;
class DoiClientTest extends TestCase
{
/**
* A basic feature test example.
*
* @return void
*/
// public function testExample()
// {
// $response = $this->get('/');
// $response->assertStatus(200);
// }
// public function testCheckDoi()
// {
// $client = new DoiClient();
// // $this->setExpectedException('Opus\Doi\ClientException');
// $result = $client->checkDoi(
// '10.5072/tethys-999',
// 'http://localhost/opus4/frontdoor/index/index/999'
// );
// $this->assertTrue($result);
// $result = $client->checkDoi(
// '10.5072/tethys-999',
// 'http://localhost/opus4/frontdoor/index/index/111'
// );
// $this->assertFalse($result);
// }
public function testRegisterDoiWithDataCiteTestAccount()
{
// $this->markTestSkipped(
// 'Test kann nur manuell gestartet werden (Zugangsdaten zum MDS-Testservice von DataCite erforderlich)'
// );
$myRequest = new Request();
$myRequest->setMethod('POST');
$myRequest->request->add(
[
'publish_id' => 1,
'path' => 'https://www.demo.laudatio-repository.org/foo'
]
);
$doiController = new \App\Http\Controllers\DoiController(new DoiClient());
$doiController->store($myRequest);
// $client = new DoiClient();
// $client->registerDoi(
// '10.5072/tethys-999',
// xmlMeta,
// 'http://localhost/opus4/frontdoor/index/index/999'
// );
}
}

View File

@ -1,6 +1,10 @@
<?php <?php
namespace Tests;
class TestCase extends Illuminate\Foundation\Testing\TestCase use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{ {
/** /**
* Creates the application. * Creates the application.
@ -9,10 +13,8 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
*/ */
public function createApplication() public function createApplication()
{ {
$app = require __DIR__.'/../bootstrap/app.php'; $app = require __DIR__ . '/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
return $app; return $app;
} }
} }