diff --git a/README.md b/README.md
index 54c17671..9c599485 100644
--- a/README.md
+++ b/README.md
@@ -43,8 +43,6 @@ COCONUT infrastructure code is licensed under the MIT license - see the [LICENSE
### COCONUT 2.0
- Venkata Chandrasekhar, Kohulan Rajan, Sri Ram Sagar Kanakam, Nisha Sharma, Viktor Weißenborn, Jonas Schaub, Christoph Steinbeck, COCONUT 2.0: a comprehensive overhaul and curation of the collection of open natural products database, Nucleic Acids Research, 2024;, gkae1063, https://doi.org/10.1093/nar/gkae1063
-
-https://doi.org/10.1093/nar/gkae1063
### COCONUT (Legacy)
- Sorokina, M., Merseburger, P., Rajan, K. et al. (2021). COCONUT online: COlleCtion of Open Natural prodUcTs database. *Journal of Cheminformatics*, 13, 2.
diff --git a/app/Actions/Coconut/AssignDOI.php b/app/Actions/Coconut/AssignDOI.php
new file mode 100644
index 00000000..e074baf7
--- /dev/null
+++ b/app/Actions/Coconut/AssignDOI.php
@@ -0,0 +1,50 @@
+doiService = $doiService;
+ }
+
+ /**
+ * Archive the given model.
+ *
+ * @param mixed $model
+ * @return void
+ */
+ public function assign($model)
+ {
+ $collection = null;
+ if ($model instanceof Collection) {
+ $collection = $model;
+ }
+ if ($collection) {
+ $collectionIdentifier = $collection->identifier ? $collection->identifier : null;
+ if ($collectionIdentifier == null) {
+ $collectionTicker = Ticker::whereType('collection')->first();
+ $collectionIdentifier = $collectionTicker->index + 1;
+ $collectionTicker->index = $collectionIdentifier;
+ $collectionTicker->save();
+
+ $collection->identifier = $collectionIdentifier;
+ $collection->save();
+ }
+ $collection->fresh()->generateDOI($this->doiService);
+ echo $collection->identifier."\r\n";
+ }
+ }
+}
diff --git a/app/Console/Commands/AssignCollectionsIdentifiers.php b/app/Console/Commands/AssignCollectionsIdentifiers.php
index d2148355..2f53919b 100644
--- a/app/Console/Commands/AssignCollectionsIdentifiers.php
+++ b/app/Console/Commands/AssignCollectionsIdentifiers.php
@@ -50,7 +50,9 @@ public function handle()
public function generateIdentifier($index)
{
- return 'CNPC'.str_pad($index, 4, '0', STR_PAD_LEFT);
+ $prefix = (env('APP_ENV') === 'production') ? 'CNPC' : 'CNPC_DEV';
+
+ return $prefix.str_pad($index, 6, '0', STR_PAD_LEFT);
}
public function fetchLastIndex()
diff --git a/app/Console/Commands/AssignDOIs.php b/app/Console/Commands/AssignDOIs.php
new file mode 100644
index 00000000..ac47e4b4
--- /dev/null
+++ b/app/Console/Commands/AssignDOIs.php
@@ -0,0 +1,45 @@
+get();
+
+ foreach ($collections as $collection) {
+ $collectionDOI = $collection->doi ? $collection->doi : null;
+ $assigner->assign($collection);
+ }
+ });
+ }
+}
diff --git a/app/Models/Collection.php b/app/Models/Collection.php
index 5b4aca08..44a04795 100644
--- a/app/Models/Collection.php
+++ b/app/Models/Collection.php
@@ -15,6 +15,7 @@
class Collection extends Model implements Auditable, HasMedia
{
+ use HasDOI;
use HasFactory;
use HasTags;
use InteractsWithMedia;
@@ -41,6 +42,7 @@ protected static function booted()
'image',
'status',
'release_date',
+ 'datacite_schema',
];
/**
diff --git a/app/Models/HasDOI.php b/app/Models/HasDOI.php
new file mode 100644
index 00000000..d8522324
--- /dev/null
+++ b/app/Models/HasDOI.php
@@ -0,0 +1,114 @@
+getIdentifier($this, 'identifier');
+ if ($this->doi == null) {
+ $url = 'https://coconut.naturalproducts.net/collections/'.$identifier;
+ $attributes = $this->getMetadata();
+ $attributes['url'] = $url;
+ $doiResponse = $doiService->createDOI($identifier, $attributes);
+ $this->doi = $doiResponse['data']['id'];
+ $this->datacite_schema = $doiResponse;
+ $this->save();
+ }
+
+ }
+
+ }
+
+ public function getIdentifier($model, $key)
+ {
+ return $model->getAttributes()[$key];
+ }
+
+ public function getMetadata()
+ {
+ $title = $this->title;
+ $creators = [
+ ['name' => 'COCONUT',
+ 'nameType' => 'Organizational', ],
+ ];
+ $description = [
+ 'description' => $this->description,
+ 'descriptionType' => 'Other',
+ ];
+ $relatedIdentifiers = [
+ [
+ 'relatedIdentifier' => $this->url,
+ 'relatedIdentifierType' => 'URL',
+ 'relationType' => 'References',
+ ],
+ ];
+ $dates = [
+ [
+ 'date' => $this->created_at,
+ 'dateType' => 'Available',
+ ],
+ [
+ 'date' => $this->created_at,
+ 'dateType' => 'Submitted',
+ ],
+ [
+ 'date' => $this->updated_at,
+ 'dateType' => 'Updated',
+ ],
+ ];
+
+ $rights = [
+ [
+ 'rights' => 'Creative Commons Attribution 4.0 International',
+ 'rightsUri' => 'https://creativecommons.org/licenses/by/4.0/legalcode',
+ 'rightsIdentifier' => 'CC-BY-4.0',
+ 'rightsIdentifierScheme' => 'SPDX',
+ 'schemeUri' => 'https://spdx.org/licenses/',
+ ],
+ ];
+ $publicationYear = explode('-', $this->created_at)[0];
+ $subjects = [
+ ['subject' => 'Natural Product',
+ 'subjectScheme' => 'NCI Thesaurus OBO Edition',
+ 'schemeURI' => 'http://purl.obolibrary.org/obo/ncit/releases/2022-08-19/ncit.owl',
+ 'valueURI' => 'http://purl.obolibrary.org/obo/NCIT_C66892',
+ 'classificationCode' => 'NCIT:C66892',
+ ],
+ ];
+ $attributes = [
+ 'creators' => $creators,
+ 'titles' => [
+ [
+ 'title' => $title,
+ ],
+ ],
+ 'dates' => $dates,
+ 'language' => 'en',
+ 'rightsList' => $rights,
+ 'descriptions' => [$description],
+ 'relatedIdentifiers' => $relatedIdentifiers,
+ 'resourceType' => 'Collection',
+ 'resourceTypeGeneral' => 'Collection',
+ 'publicationYear' => $publicationYear,
+ 'subjects' => $subjects,
+ 'types' => [
+ 'ris' => 'DATA',
+ 'bibtex' => 'misc',
+ 'schemaOrg' => 'Collection',
+ 'resourceType' => 'Collection',
+ 'resourceTypeGeneral' => 'Collection',
+ ],
+ 'isActive' => true,
+ 'event' => 'publish',
+ 'state' => 'findable',
+ 'schemaVersion' => 'http://datacite.org/schema/kernel-4',
+
+ ];
+
+ return $attributes;
+ }
+}
diff --git a/app/Providers/DOIServiceProvider.php b/app/Providers/DOIServiceProvider.php
new file mode 100644
index 00000000..39d981db
--- /dev/null
+++ b/app/Providers/DOIServiceProvider.php
@@ -0,0 +1,24 @@
+app->bind(DOIService::class, function ($app) {
+ return match (config('doi.default')) {
+ 'datacite' => new DataCite
+ };
+ });
+ }
+}
diff --git a/app/Services/DOI/DOIService.php b/app/Services/DOI/DOIService.php
new file mode 100644
index 00000000..27a37b7f
--- /dev/null
+++ b/app/Services/DOI/DOIService.php
@@ -0,0 +1,18 @@
+client = new Client([
+ 'base_uri' => Config::get('doi.'.Config::get('doi.default').'.endpoint'),
+ 'auth' => [Config::get('doi.'.Config::get('doi.default').'.username'), Config::get('doi.'.Config::get('doi.default').'.secret')],
+ 'headers' => [
+ 'Accept' => 'application/vnd.api+json',
+ ],
+ ]);
+ $this->prefix = Config::get('doi.'.Config::get('doi.default').'.prefix');
+ }
+
+ /**
+ * Returns a list of DOIs
+ */
+ public function getDOIs()
+ {
+ $prefix = Config::get('doi.'.Config::get('doi.default').'.prefix');
+ $response = $this->client->get('/dois?prefix='.$prefix);
+
+ return $response->getBody();
+ }
+
+ public function getDOI($doi)
+ {
+ $response = $this->client->get('/dois/'.urlencode($doi));
+
+ return $response->getBody();
+ }
+
+ public function createDOI($identifier, $metadata = [])
+ {
+ $doi = $this->prefix.'/'.Config::get('app.name').'.'.$identifier;
+ $url = 'https://coconut.naturalproducts.net/collections/'.$identifier;
+ $suffix = Config::get('app.name').'.'.$identifier;
+ $attributes = [
+ 'doi' => $this->prefix.'/'.Config::get('app.name').'.'.$identifier,
+ 'prefix' => $this->prefix,
+ 'suffix' => Config::get('app.name').'.'.$identifier,
+ 'publisher' => Config::get('app.name'),
+ 'publicationYear' => now()->format('Y'),
+ 'language' => 'en',
+ ];
+
+ foreach ($metadata as $key => $value) {
+ $attributes[$key] = $value;
+ }
+
+ $body = [
+ 'data' => [
+ 'type' => 'dois',
+ 'attributes' => $attributes,
+ ],
+ ];
+
+ $response = $this->client->post('/dois',
+ [RequestOptions::JSON => $body]
+ );
+
+ $stream = $response->getBody();
+ $contents = $stream->getContents();
+
+ return json_decode($contents, true);
+ }
+
+ /**
+ * Update DataCite metadata based on DOI
+ *
+ * @param string $doi
+ * @param array $metadata
+ * @return array $contents
+ */
+ public function updateDOI($doi, $metadata = [])
+ {
+ foreach ($metadata as $key => $value) {
+ $attributes[$key] = $value;
+ }
+
+ $body = [
+ 'data' => [
+ 'type' => 'dois',
+ 'attributes' => $attributes,
+ ],
+ ];
+
+ $response = $this->client->put('/dois/'.urlencode($doi),
+ [RequestOptions::JSON => $body]
+ );
+
+ $stream = $response->getBody();
+ $contents = $stream->getContents();
+ $contents = json_decode($contents, true);
+
+ return $contents;
+ }
+
+ public function deleteDOI($doi)
+ {
+ $response = $this->client->delete('/dois/'.urlencode($doi));
+
+ return $response->getBody();
+ }
+
+ public function getDOIActivity($doi)
+ {
+ $response = $this->client->get('/dois/'.urlencode($doi).'/activities');
+
+ return $response->getBody();
+ }
+}
diff --git a/config/app.php b/config/app.php
index 0968d310..3acfe4a8 100644
--- a/config/app.php
+++ b/config/app.php
@@ -177,6 +177,8 @@
Spatie\Permission\PermissionServiceProvider::class,
OwenIt\Auditing\AuditingServiceProvider::class,
App\Providers\RestDocumentationServiceProvider::class,
+ App\Providers\DOIServiceProvider::class,
+
])->toArray(),
/*
diff --git a/config/doi.php b/config/doi.php
new file mode 100644
index 00000000..4855e6f3
--- /dev/null
+++ b/config/doi.php
@@ -0,0 +1,36 @@
+ env('DOI_PROVIDER', 'datacite'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | DataCite Options
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the configuration options that should be used when
+ | passwords are hashed using the Argon algorithm. These will allow you
+ | to control the amount of time it takes to hash the given password.
+ |
+ */
+
+ 'datacite' => [
+ 'username' => env('DATACITE_USERNAME'),
+ 'secret' => env('DATACITE_SECRET'),
+ 'prefix' => env('DATACITE_PREFIX'),
+ 'endpoint' => env('DATACITE_ENDPOINT', 'api.test.datacite.org'),
+ 'contributor_types' => env('DATACITE_CONTRIBUTOR_TYPE', ['ContactPerson', 'DataCollector', 'DataCurator', 'DataManager', 'Distributor', 'Editor', 'HostingInstitution', 'Producer', 'ProjectLeader', 'ProjectManager', 'ProjectMember', 'RegistrationAgency', 'RegistrationAuthority', 'RelatedPerson', 'Researcher', 'ResearchGroup', 'RightsHolder', 'Sponsor', 'Supervisor', 'WorkPackageLeader', 'Other']),
+ ],
+
+];
diff --git a/resources/views/livewire/search.blade.php b/resources/views/livewire/search.blade.php
index 7f65c618..56e8783e 100644
--- a/resources/views/livewire/search.blade.php
+++ b/resources/views/livewire/search.blade.php
@@ -13,7 +13,14 @@
$slug = Str::slug($collection->title);
$currentYearMonth = now()->format('Y-m');
@endphp
-
+
+ @if ($collection->doi)
+ DOI:
+ {{ $collection->doi }}
+
+ @endif
+
Download Collection (SDF) →