'error',
'text' => _x('An error has occurred, please try again later', 'pmid lookup error message', 'anno'),
);
// Only Allow nubmers for our ID, commas are also allowed, but only when looking up multiple articles.
$pubmed_id = trim($pubmed_id);
if (preg_match('/[^0-9]/', $pubmed_id) || $pubmed_id > 4294967295) {
anno_reference_error_response(_x('Invalid PMID', 'pmid lookup error message', 'anno'));
}
// Generate the URL for lookup
$url = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id='.$pubmed_id;
// Use wp.com functions if available for lookup.
if (function_exists('vip_safe_wp_remote_get')) {
$response = vip_safe_wp_remote_get($url);
}
else {
$response = wp_remote_get($url);
}
if (is_wp_error($response) || (isset($response['response']['code']) && $response['response']['code'] != 200) || !isset($response['body'])) {
anno_reference_error_response();
}
else {
include_once(CFCT_PATH.'functions/phpquery/phpquery.php');
phpQuery::newDocumentXML($response['body']);
phpQuery::getDocument();
$errors = pq('ERROR');
$body = pq('DocSum');
if ($errors->length > 0 || $body->length == 0) {
anno_reference_error_response();
}
else {
$text = '';
// Authors
$authors = pq('Item[Name="Author"]');
$author_arr = array();
foreach ($authors as $author) {
$author = pq($author);
$author_arr[] = $author->text();
}
if (!empty($author_arr)) {
$text .= implode(', ', $author_arr).'. ';
}
// Title
$title = pq('Item[Name="Title"]')->text();
if (!empty($title)) {
// Titles already have period
$text .= $title.' ';
}
// Source
$source = pq('Item[Name="Source"]')->text();
if (!empty($source)) {
$text .= $source.'. ';
}
// Date, Volume, Issue, Page
$date_meta = '';
$date = pq('Item[Name="PubDate"]')->text();
$volume = pq('Item[Name="Volume"]')->text();
$issue = pq('Item[Name="Issue"]')->text();
$page = pq('Item[Name="Pages"]')->text();
if (!empty($date)) {
$date_meta .= $date;
}
if (!empty($volume) || !empty($issue) || !empty($page)) {
$date_meta .= ';';
if (!empty($volume)) {
$date_meta .= $volume;
}
if (!empty($issue)) {
$date_meta .= '('.$issue.')';
}
if (!empty($page)) {
$date_meta .= ':'.$page;
}
}
if (!empty($date_meta)) {
$text .= $date_meta.'. ';
}
$text .= _x('PubMed PMID:', 'Reference text for PubMed lookup', 'anno').$pubmed_id.'.';
$lookup_response = array(
'message' => 'success',
'text' => esc_textarea($text),
);
}
}
echo json_encode($lookup_response);
die();
}
add_action('wp_ajax_anno-import-pubmed', 'anno_reference_import_pubmed');
/**
* AJAX handler that looks up an article based on PMID and parses the data for a reference.
* Echos a JSON encoded array
*
* @return void
*/
function anno_reference_import_doi() {
$doi = null;
$url = null;
$author_arr = [];
check_ajax_referer('anno_import_doi', '_ajax_nonce-import-doi');
if (!isset($_POST['doi'])) {
anno_reference_error_response();
}
else {
$doi = $_POST['doi'];
}
$lookup_response = array(
'message' => 'error',
'text' => _x('An error has occurred, please try again later', 'pmid lookup error message', 'anno'),
);
// DOIs cannot contain any control characters. As defined here: http://www.doi.org/handbook_2000/appendix_1.html
$doi = trim($doi);
if (preg_match('/[\x00-\x1F\x7F]/', $doi)) {
anno_reference_error_response(_x('Invalid DOI', 'pmid lookup error message', 'anno'));
}
// Generate the URL for lookup
$crossref_login = cfct_get_option('crossref_login');
$crossref_pass = cfct_get_option('crossref_pass');
// Empty login, or empty password and login is not an email.
if (empty($crossref_login) || (empty($crossref_pass) && !anno_is_valid_email($crossref_login))) {
anno_reference_error_response(_x('Invalid CrossRef Login', 'pmid lookup error message', 'anno'));
}
// Empty pass, just try passing login
else if (empty($croossref_pass)) {
$url = 'http://www.crossref.org/openurl/?pid='.$crossref_login.'&id=doi:'.$doi.'&noredirect=true';
}
// Password and Login not empty, pass both in query. Caught later if invalid.
else {
$url = 'http://www.crossref.org/openurl/?pid='.$crossref_login.':'.$crossref_pass.'&id=doi:'.$doi.'&noredirect=true';
}
// Use wp.com functions if available for lookup.
if (function_exists('vip_safe_wp_remote_get')) {
$response = vip_safe_wp_remote_get($url);
}
else {
$response = wp_remote_get($url);
}
if (is_wp_error($response) || (isset($response['response']['code']) && $response['response']['code'] != 200) || !isset($response['body'])) {
anno_reference_error_response();
}
else {
include_once(CFCT_PATH.'functions/phpquery/phpquery.php');
phpQuery::newDocumentXML($response['body']);
phpQuery::getDocument();
$html = pq('html');
// If we find an HTML tag, echo error.
if ($html->length > 0) {
// We should only hit an HTML page for malformed URLs or invalid logins
// @TODO error for invalid login.
anno_reference_error_response(_x('Invalid DOI', 'pmid lookup error message', 'anno'));
}
$query_status = pq('query')->attr('status');
// Error if unresolved
if ($query_status == 'unresolved') {
$lookup_response = anno_reference_error_response(pq('msg')->text());
}
// Process resolved queries
else if ($query_status == 'resolved') {
$text = '';
// There should only be a single 'first' author.
$prime_author = pq('contributor[sequence="first"][contributor_role="author"]');
$author_text = anno_reference_doi_process_author($prime_author);
if (!empty($author_text)) {
$author_arr[] = $author_text;
}
$additional_authors = pq('contributor[sequence="additional"][contributor_role="author"]');
foreach ($additional_authors as $additional_author) {
$additional_author = pq($additional_author);
$author_text = anno_reference_doi_process_author($additional_author);
if (!empty($author_text)) {
$author_arr[] = $author_text;
}
}
$text .= implode(', ', $author_arr).'. ';
// Title
$title = pq('article_title')->text();
if (!empty($title)) {
// Titles do not have periods
$text .= $title.'. ';
}
// Source
$source = pq('journal_title')->text();
if (!empty($source)) {
$text .= $source.'. ';
}
// Date, Volume, Issue, Page
$date_meta = '';
$date = pq('year')->text();
$volume = pq('volume')->text();
$issue = pq('issue')->text();
$first_page = pq('first_page')->text();
$last_page = pq('last_page')->text();
if (!empty($date)) {
$date_meta .= $date;
}
if (!empty($volume) || !empty($issue) || !empty($page)) {
$date_meta .= ';';
if (!empty($volume)) {
$date_meta .= $volume;
}
if (!empty($issue)) {
$date_meta .= '('.$issue.')';
}
if (!empty($first_page)) {
$date_meta .= ':'.$first_page;
}
if (!empty($last_page)) {
$date_meta .= '-'.$last_page;
}
}
if (!empty($date_meta)) {
$text .= $date_meta.'. ';
}
$text .= _x('DOI:', 'Reference text for doi lookup', 'anno').$doi.'.';
$lookup_response = array(
'message' => 'success',
'text' => esc_textarea($text),
);
}
// Neither resolved nor unresolved, throw generic error
else {
anno_reference_error_response();
}
}
echo json_encode($lookup_response);
die();
}
add_action('wp_ajax_anno-import-doi', 'anno_reference_import_doi');
/**
* Echos out a JSON encoded array for errors with reference lookup.
*
* @param String $message Error message to be used, otherwise a default will be generated
* @return void
*/
function anno_reference_error_response($message = null) {
if (empty($message)) {
$message = _x('An error has occurred, please try again later', 'pmid lookup error message', 'anno');
}
echo json_encode(array(
'message' => 'error',
'text' => $message,
));
// No need to continue if we've encountered an error
die();
}
/**
* Generate author text for a DOI XML document
* @param phpQueryObject $author author wrapping element
* @return string
*/
function anno_reference_doi_process_author($author) {
$text = '';
//Last, First, Suffix
$last_name = pq('surname', $author)->text();
$first_name = pq('given_name', $author)->text();
$suffix = pq('suffix', $author)->text();
if (!empty($last_name)) {
$text .= $last_name;
if (!empty($first_name) || !empty($suffix)) {
$text .= ', ';
}
}
if (!empty($first_name)) {
$text .= $first_name;
if (!empty($suffix)) {
$text .= ', ';
}
}
if (!empty($suffix)) {
$text .= $suffix;
}
return $text;
}
/**
* Generate an article XML for CrossRef deposit
*
* @param int $article_id WP post ID
* @param int $user_id WP User ID
*
* @return todo
*/
function anno_doi_article_deposit($article_id, $user_id) {
if (!(current_user_can('administrator') || current_user_can('editor'))) {
return array(
'message' => 'error',
'markup' => _x('You do not have the correct permissions to perform this action', 'DOI deposit error message', 'anno'),
);
}
$article = get_post($article_id);
if ($article->post_status != 'publish') {
return array(
'message' => 'error',
'markup' => _x('Article must be published in order to deposit.', 'DOI deposit error message', 'anno'),
);
}
$journal_title = cfct_get_option('journal_name');
$journal_issn = cfct_get_option('journal_issn');
$registrant_code = cfct_get_option('registrant_code');
$crossref_id = cfct_get_option('crossref_login');
$crossref_pass = cfct_get_option('crossref_pass');
$error_markup = null;
// We don't want this to be passed in as a parameter, in case someone has hijacked the POST var this would come in on
$doi = anno_get_doi($article_id);
// User required credentials
if (empty($crossref_id) || empty($crossref_pass) || empty($registrant_code)) {
$error_markup = _x('Invalid or Empty CrossRef Credentials', 'DOI deposit error message', 'anno');
}
// Journal Required Fields
if (empty($journal_title) || empty($journal_issn)) {
$error_markup = _x('Invalid or Empty Journal Data', 'DOI deposit error message', 'anno');
}
// Make sure we're only submitting Published articles
if ($article->post_status !== 'publish') {
$error_markup = _x('Article must be published to submit a DOI request', 'DOI deposit error message', 'anon');
}
$article_year = date('Y', strtotime($article->post_date));
// Article Required Fields
if (empty($article->post_title) || empty($article_year) || empty($doi)) {
$error_markup = _x('Invalid or Empty Article Data', 'DOI deposit error message', 'anon');
}
if (!empty($error_markup)) {
return array(
'message' => 'error',
'markup' => $error_markup,
);
}
// Journal Required Fields:
// full_title, ISSN
// (rec) abbrev_title
//
// Article
// titles, publication_date (year), doi_data
// (rec) contributors, publication_date (day, month), pages (first_page, last_page), citation_list
// Journal Title
$journal_title_xml = ''.$journal_title.'';
// Journal ISSN
$journal_issn_xml = ''.$journal_issn.'';
// Journal abbr
if ($journal_title_abbr = cfct_get_option('journal_abbr')) {
$journal_title_abbr_xml = ''.$journal_title_abbr.'';
}
else {
$journal_title_abbr_xml = '';
}
$authors = get_post_meta($article->ID, '_anno_author_snapshot', true);
if (is_array($authors) && !empty($authors)) {
$i = 0;
$author_xml = '';
foreach ($authors as $author) {
// First author is always the primary.
if ($i == 0) {
$sequence = 'first';
}
else {
$sequence = 'additional';
}
$author_xml .= '';
if (!empty($author['given_names'])) {
$author_xml .= ''.esc_html($author['given_names']).'';
}
if (!empty($author['surname'])) {
$author_xml .= ''.esc_html($author['surname']).'';
}
if (!empty($author['suffix'])) {
$author_xml .= ''.esc_html($author['suffix']).'';
}
if (!empty($author['affiliation'])) {
$author_xml .= ''.esc_html($author['affiliation']).'';
}
$author_xml .= '';
$i++;
}
}
else {
// @TODO throw error
return array(
'message' => 'error',
'code' => '0',
'markup' => '',
);
}
if (strpos('10.'.$registrant_code.'/', $doi) === false) {
$doi = '10.'.$registrant_code.'/'.$doi;
}
$citation_xml = '';
if ($citation_xml = get_post_meta($article->ID, '_anno_references', true)) {
if (!empty($citations) && is_array($citation_xml)) {
foreach ($citations as $citation_key => $citation) {
if (isset($citation['text']) && !empty($citation['text'])) {
$citation_xml .= '
'.esc_html($citation_xml).'
';
}
}
// @TODO check other Element xml creation in a similar manner.
if (!empty($citation_xml)) {
$citation_xml = ''.$citation_xml.'';
}
}
}
// Use old parameter based links, in case permalink structure is changed in the future
$permalink = home_url('?p=' . $article->ID);
$current_user = wp_get_current_user();
$depositor_xml = '
'.$current_user->display_name.'
'.$current_user->user_email.'
';
$xml = '
'.time().''.
$depositor_xml
.'
'.$journal_title_xml.'
'.$journal_title_abbr_xml.'
'.$journal_issn_xml.'
'.esc_html($article->post_title).'
'.$author_xml.'
'.$article_year.'
'.$doi.'
'.strtotime($article->post_date).'
'.$permalink.'
'.$citation_xml.
/*
Figure 1:
This is the caption of the first figure...
Web resolution image
10.9876/S0003695199019014/f1
http://ojps.aip.org:18000/link/?apl/74/1/76/f1
Video 1:
This is a description of the video...
10.9876/S0003695199019014/video1
http://ojps.aip.org:18000/link/?apl/74/1/76/video1
*/
'
';
// @TODO Verify (Attempt to deposit in test DB)
$filename = 'crossref-deposit-'.$article->ID.'.xml';
$file_handler = fopen($filename, 'w');
if (!$file_handler) {
fclose($file_handler);
return array(
'message' => 'error',
'markup' => _x('Could not create file to be deposited, please check your system setup', 'DOI deposit error message', 'anno'),
);
}
fwrite($file_handler, $xml);
$test_url = 'http://doi.crossref.org/servlet/deposit?operation=doMDUpload&login_id='.$crossref_id.'&login_passwd='.$crossref_pass.'&area=test';
$test_args = array(
'headers' => array(
'Content-type' => 'multipart/form-data',
'Content-Disposition' => 'form-data; name="fname"; filename="'.$filename.'";',
),
);
$test_result = wp_remote_post($test_url, $test_args);
fclose($file_handler);
return array('test');
// @TODO Deposit, use area=live
// $url = 'http://www.crossref.org/openurl/?pid='.$crossref_login.'&id=doi:'.$doi.'&noredirect=true';
// @TODO Submit meta
// DOI should no longer be able to be submitted, update corresponding post meta
}
function anno_doi_deposit_ajax() {
check_ajax_referer('anno_doi_deposit', '_ajax_nonce-doi-deposit');
// Make sure we have an article ID and user ID
if (empty($_POST['article_id'])) {
die();
}
$article_id = (int) $_POST['article_id'];
// If we get an error that the DOI already exists:
$response = anno_doi_article_deposit($article_id, get_current_user_id());
echo json_encode($response);
die();
}
add_action('wp_ajax_anno-doi-deposit', 'anno_doi_deposit_ajax');
/**
* Get an existing DOI for a post, or generate a new one
*
* @param int $post_id
* @param bool $generate_new_doi whether or not to force a new DOI generation
*
* @return string DOI for this article
*/
function anno_get_doi($post_id, $generate_new_doi = false) {
if ($generate_new_doi) {
$registrant_code = cfct_get_option('registrant_code');
$doi = '10.'.$registrant_code.'/'.uniqid('', false);
update_post_meta($post_id, '_anno_doi', $doi);
}
else {
$doi = get_post_meta($post_id, '_anno_doi', true);
if (empty($doi)) {
$registrant_code = cfct_get_option('registrant_code');
$doi = '10.'.$registrant_code.'/'.uniqid('', false);
update_post_meta($post_id, '_anno_doi', $doi);
}
}
return $doi;
}
/**
* Ajax handler for regenerating a new DOI
*/
function anno_doi_regenerate_ajax() {
check_ajax_referer('anno_doi_regenerate', '_ajax_nonce-doi-regenerate');
if (empty($_POST['article_id'])) {
die();
}
$new_doi = anno_get_doi((int) $_POST['article_id'], true);
echo json_encode(array(
'doi' => $new_doi,
'status' => _x('New DOI Generated', 'DOI generation message', 'anno'),
));
die();
}
add_action('wp_ajax_anno-doi-regenerate', 'anno_doi_regenerate_ajax');
/**
* Markup for regeneration submission
* @return string HTML String for regeneration markup
*/
function anno_regenerate_doi_markup() {
$html = '';
$html .= wp_nonce_field('anno_doi_regenerate', '_ajax_nonce-doi-regenerate', true, false);
return $html;
}
?>