From 0d6acf3e5493d3ca0a0d230e8738c54a921ac103 Mon Sep 17 00:00:00 2001 From: NRayya <82588017+NRayya@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:28:44 +0200 Subject: [PATCH 1/7] feat: assign DOIs to collections --- app/Actions/Coconut/AssignDOI.php | 50 +++++++ .../Commands/AssignCollectionsIdentifiers.php | 83 ++++++++++++ app/Console/Commands/AssignDOIs.php | 46 +++++++ app/Models/Collection.php | 1 + app/Models/HasDOI.php | 114 ++++++++++++++++ app/Providers/DOIServiceProvider.php | 24 ++++ app/Services/DOI/DOIService.php | 18 +++ app/Services/DOI/DataCite.php | 126 ++++++++++++++++++ config/app.php | 2 + config/doi.php | 36 +++++ 10 files changed, 500 insertions(+) create mode 100644 app/Actions/Coconut/AssignDOI.php create mode 100644 app/Console/Commands/AssignCollectionsIdentifiers.php create mode 100644 app/Console/Commands/AssignDOIs.php create mode 100644 app/Models/HasDOI.php create mode 100644 app/Providers/DOIServiceProvider.php create mode 100644 app/Services/DOI/DOIService.php create mode 100644 app/Services/DOI/DataCite.php create mode 100644 config/doi.php 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 new file mode 100644 index 00000000..579c0a79 --- /dev/null +++ b/app/Console/Commands/AssignCollectionsIdentifiers.php @@ -0,0 +1,83 @@ +fetchLastIndex() + 1; + $data = []; + $this->info('Assigning identifiers to collections'); + Collection::select('identifier', 'id')->where([ + ['identifier', '=', null], + ])->chunk($batchSize, function ($collections) use (&$currentIndex) { + $data = []; + $header = ['id', 'identifier']; + foreach ($collections as $collection) { + if (! $collection->identifier) { + $data[] = array_combine($header, [$collection->id, $this->generateIdentifier($currentIndex)]); + $currentIndex++; + } + } + $this->insertBatch($data); + }); + $this->info('Assigning identifiers to collections: Done'); + } + + public function generateIdentifier($index) + { + return 'CNPC'.str_pad($index, 4, '0', STR_PAD_LEFT); + } + + public function fetchLastIndex() + { + $ticker = Ticker::where('type', 'collection')->first(); + + return (int) $ticker->index; + } + + /** + * Insert a batch of data into the database. + * + * @return void + */ + private function insertBatch(array $data) + { + DB::transaction(function () use ($data) { + foreach ($data as $row) { + Collection::updateorCreate( + [ + 'id' => $row['id'], + ], + [ + 'identifier' => $row['identifier'], + ] + ); + } + }); + } +} diff --git a/app/Console/Commands/AssignDOIs.php b/app/Console/Commands/AssignDOIs.php new file mode 100644 index 00000000..38d20252 --- /dev/null +++ b/app/Console/Commands/AssignDOIs.php @@ -0,0 +1,46 @@ +get(); + + foreach ($collections as $collection) { + // echo $collection->identifier."\r\n"; + $collectionDOI = $collection->doi ? $collection->doi : null; + $assigner->assign($collection); + } + }); + } +} diff --git a/app/Models/Collection.php b/app/Models/Collection.php index f5fa2501..fa6f50de 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; diff --git a/app/Models/HasDOI.php b/app/Models/HasDOI.php new file mode 100644 index 00000000..1f1d6319 --- /dev/null +++ b/app/Models/HasDOI.php @@ -0,0 +1,114 @@ +getIdentifier($this, 'identifier'); + if ($this->doi == null) { + $url = 'https://dev.coconut.naturalproducts.net/collections/'.$identifier; // ToDo: fix collections url + $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; + echo $doi; + $url = 'https://dev.coconut.naturalproducts.net/collections/'.$identifier; + echo $url; + $suffix = Config::get('app.name').'.'.$identifier; + echo $suffix; + $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, + ], + ]; + + dd(json_encode($body)); + // dd($body); + + $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']), + ], + +]; From b03eae89bf8c0752f7b5037067f1cb8985908f4c Mon Sep 17 00:00:00 2001 From: Venkata Chandra Sekhar Nainala Date: Thu, 12 Sep 2024 16:40:20 +0200 Subject: [PATCH 2/7] fix: DOI issue fixed --- app/Console/Commands/AssignCollectionsIdentifiers.php | 4 +++- app/Services/DOI/DataCite.php | 8 +------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/Console/Commands/AssignCollectionsIdentifiers.php b/app/Console/Commands/AssignCollectionsIdentifiers.php index d2148355..64e7a71d 100644 --- a/app/Console/Commands/AssignCollectionsIdentifiers.php +++ b/app/Console/Commands/AssignCollectionsIdentifiers.php @@ -50,9 +50,11 @@ 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() { $ticker = Ticker::where('type', 'collection')->first(); diff --git a/app/Services/DOI/DataCite.php b/app/Services/DOI/DataCite.php index 4d9f1dde..db6d7a3f 100644 --- a/app/Services/DOI/DataCite.php +++ b/app/Services/DOI/DataCite.php @@ -41,11 +41,8 @@ public function getDOI($doi) public function createDOI($identifier, $metadata = []) { $doi = $this->prefix.'/'.Config::get('app.name').'.'.$identifier; - echo $doi; - $url = 'https://dev.coconut.naturalproducts.net/collections/'.$identifier; - echo $url; + $url = 'https://coconut.naturalproducts.net/collections/'.$identifier; $suffix = Config::get('app.name').'.'.$identifier; - echo $suffix; $attributes = [ 'doi' => $this->prefix.'/'.Config::get('app.name').'.'.$identifier, 'prefix' => $this->prefix, @@ -66,9 +63,6 @@ public function createDOI($identifier, $metadata = []) ], ]; - dd(json_encode($body)); - // dd($body); - $response = $this->client->post('/dois', [RequestOptions::JSON => $body] ); From 73380ae0dbf1f7889e1f4bb0de5a1566ab780e52 Mon Sep 17 00:00:00 2001 From: Venkata Chandra Sekhar Nainala Date: Mon, 2 Dec 2024 15:04:16 +0100 Subject: [PATCH 3/7] fix: updated readme --- README.md | 2 -- 1 file changed, 2 deletions(-) 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. From 6fd1a713e222b04b60f28fb87597eaf734180080 Mon Sep 17 00:00:00 2001 From: Venkata Chandra Sekhar Nainala Date: Mon, 2 Dec 2024 15:13:22 +0100 Subject: [PATCH 4/7] fix: updated coconut collection assign doi command updated --- app/Console/Commands/AssignDOIs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Commands/AssignDOIs.php b/app/Console/Commands/AssignDOIs.php index 4e96970a..ac47e4b4 100644 --- a/app/Console/Commands/AssignDOIs.php +++ b/app/Console/Commands/AssignDOIs.php @@ -14,7 +14,7 @@ class AssignDOIs extends Command * * @var string */ - protected $signature = 'collection:assign-dois'; + protected $signature = 'coconut:collection-assign-doi'; /** * The console command description. From d3fb756cf85479626809362ee41551200e855c2b Mon Sep 17 00:00:00 2001 From: Venkata Chandra Sekhar Nainala Date: Mon, 2 Dec 2024 15:13:57 +0100 Subject: [PATCH 5/7] chore: code formatting updates --- app/Console/Commands/AssignCollectionsIdentifiers.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Console/Commands/AssignCollectionsIdentifiers.php b/app/Console/Commands/AssignCollectionsIdentifiers.php index 64e7a71d..2f53919b 100644 --- a/app/Console/Commands/AssignCollectionsIdentifiers.php +++ b/app/Console/Commands/AssignCollectionsIdentifiers.php @@ -51,9 +51,9 @@ public function handle() public function generateIdentifier($index) { $prefix = (env('APP_ENV') === 'production') ? 'CNPC' : 'CNPC_DEV'; - return $prefix . str_pad($index, 6, '0', STR_PAD_LEFT); - } + return $prefix.str_pad($index, 6, '0', STR_PAD_LEFT); + } public function fetchLastIndex() { From 916cc600144f7954da82b6d1505916960480e886 Mon Sep 17 00:00:00 2001 From: Venkata Chandra Sekhar Nainala Date: Mon, 2 Dec 2024 15:59:38 +0100 Subject: [PATCH 6/7] fix: DOI issues fix --- app/Models/Collection.php | 1 + app/Models/HasDOI.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Models/Collection.php b/app/Models/Collection.php index 774a62a9..44a04795 100644 --- a/app/Models/Collection.php +++ b/app/Models/Collection.php @@ -42,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 index 1f1d6319..d8522324 100644 --- a/app/Models/HasDOI.php +++ b/app/Models/HasDOI.php @@ -10,12 +10,12 @@ public function generateDOI($doiService) if (! is_null($doi_host)) { $identifier = $this->getIdentifier($this, 'identifier'); if ($this->doi == null) { - $url = 'https://dev.coconut.naturalproducts.net/collections/'.$identifier; // ToDo: fix collections url + $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->datacite_schema = $doiResponse; $this->save(); } From a3b1b5f6ee7ae659c2a1ea5e8b77fedfeb483b03 Mon Sep 17 00:00:00 2001 From: Venkata Chandra Sekhar Nainala Date: Mon, 2 Dec 2024 16:17:35 +0100 Subject: [PATCH 7/7] fix: enabled DOI links on collection pages --- resources/views/livewire/search.blade.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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)