121 lines
3.7 KiB
PHP
121 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace app\common;
|
|
|
|
/**
|
|
* Europe PMC REST API
|
|
* @see https://europepmc.org/RestfulWebService
|
|
*/
|
|
class EuropePmcService
|
|
{
|
|
private $base = 'https://www.ebi.ac.uk/europepmc/webservices/rest';
|
|
private $timeout = 25;
|
|
|
|
public function searchByDoi($doi)
|
|
{
|
|
$doi = trim((string)$doi);
|
|
if ($doi === '') {
|
|
return null;
|
|
}
|
|
$query = 'DOI:"' . str_replace('"', '', $doi) . '"';
|
|
return $this->searchFirst($query);
|
|
}
|
|
|
|
public function searchByBibliographic($title, $author, $year = '')
|
|
{
|
|
$title = trim((string)$title);
|
|
if ($title === '') {
|
|
return null;
|
|
}
|
|
$parts = ['TITLE:"' . str_replace('"', '', $title) . '"'];
|
|
$author = trim((string)$author);
|
|
if ($author !== '') {
|
|
$firstAuthor = preg_split('/[,;]/', $author);
|
|
$firstAuthor = trim((string)($firstAuthor[0] ?? ''));
|
|
if ($firstAuthor !== '') {
|
|
$parts[] = 'AUTH:"' . str_replace('"', '', $firstAuthor) . '"';
|
|
}
|
|
}
|
|
$year = trim((string)$year);
|
|
if ($year !== '' && preg_match('/^(19|20)\d{2}$/', $year)) {
|
|
$parts[] = 'PUB_YEAR:' . $year;
|
|
}
|
|
return $this->searchFirst(implode(' AND ', $parts));
|
|
}
|
|
|
|
public function fetchFullTextByPmcid($pmcid)
|
|
{
|
|
$pmcid = strtoupper(trim((string)$pmcid));
|
|
if ($pmcid === '') {
|
|
return '';
|
|
}
|
|
if (strpos($pmcid, 'PMC') !== 0) {
|
|
$pmcid = 'PMC' . preg_replace('/\D/', '', $pmcid);
|
|
}
|
|
$url = $this->base . '/' . rawurlencode($pmcid) . '/fullTextXML';
|
|
$xml = $this->httpGet($url);
|
|
if ($xml === '') {
|
|
return '';
|
|
}
|
|
return $this->xmlToPlainText($xml);
|
|
}
|
|
|
|
private function searchFirst($query)
|
|
{
|
|
$url = $this->base . '/search?' . http_build_query([
|
|
'query' => $query,
|
|
'format' => 'json',
|
|
'pageSize' => 1,
|
|
]);
|
|
$raw = $this->httpGet($url);
|
|
if ($raw === '') {
|
|
return null;
|
|
}
|
|
$json = json_decode($raw, true);
|
|
$list = $json['resultList']['result'] ?? [];
|
|
if (empty($list[0]) || !is_array($list[0])) {
|
|
return null;
|
|
}
|
|
$row = $list[0];
|
|
return [
|
|
'title' => trim((string)($row['title'] ?? '')),
|
|
'abstract' => trim((string)($row['abstractText'] ?? '')),
|
|
'doi' => trim((string)($row['doi'] ?? '')),
|
|
'pmid' => trim((string)($row['pmid'] ?? '')),
|
|
'pmcid' => trim((string)($row['pmcid'] ?? '')),
|
|
'journal' => trim((string)($row['journalTitle'] ?? '')),
|
|
'year' => trim((string)($row['pubYear'] ?? '')),
|
|
'source' => 'europe_pmc',
|
|
];
|
|
}
|
|
|
|
private function xmlToPlainText($xml)
|
|
{
|
|
$xml = trim((string)$xml);
|
|
if ($xml === '') {
|
|
return '';
|
|
}
|
|
libxml_use_internal_errors(true);
|
|
$doc = new \DOMDocument();
|
|
if (!$doc->loadXML($xml)) {
|
|
return trim(strip_tags($xml));
|
|
}
|
|
return trim(preg_replace('/\s+/u', ' ', $doc->textContent));
|
|
}
|
|
|
|
private function httpGet($url)
|
|
{
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => $this->timeout,
|
|
CURLOPT_SSL_VERIFYPEER => false,
|
|
CURLOPT_HTTPHEADER => ['User-Agent: TMRjournals-EuropePMC/1.0'],
|
|
]);
|
|
$res = curl_exec($ch);
|
|
curl_close($ch);
|
|
return is_string($res) ? $res : '';
|
|
}
|
|
}
|