Last active
November 23, 2016 15:56
-
-
Save ashepherd/f56a27cfc79a0ebfd62ecede497a1fe5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file orcid-public-api-search.php | |
| * | |
| * How to use this code: | |
| * | |
| * STEP 1: GET A CLIENT TOKEN, IF YOU DON'T HAVE ONE ALREADY. OTHERWISE, SKIP THIS STEP | |
| * @see http://support.orcid.org/knowledgebase/articles/343182 | |
| * Call: _request_orcid_api_token() | |
| * | |
| * STEP 2: RUN ORCID QUERIES w. TOKEN | |
| * Call: _search_orcid_bios() | |
| * | |
| * STEP 3: CONVERT ORCID+XML to JSON | |
| * Call: _convert_orcid_xml_to_json() | |
| * | |
| * STEP 4: GET ARRAY OF RESULTS | |
| * Call: _orcid_search_results() | |
| */ | |
| // STEP 1: GET A CLIENT TOKEN | |
| $token = ''; | |
| $client_id = '<GET FROM ORCID>'; | |
| $client_secret = '<GET FROM ORCID>'; | |
| $response = _request_orcid_api_token($client_id, $client_secret); | |
| $requested_url = $response['request_url']; | |
| $status = $response['code']; | |
| echo "TOKEN Request URL: $requested_url\n"; | |
| echo "TOKEN Response Code: $status\n"; | |
| // Parse JSON response. | |
| $orcid_token_json = json_decode($response['response'], TRUE); | |
| if ($error_msg = _is_orcid_error($orcid_token_json)) { | |
| exit($error_msg); | |
| } | |
| // Make sure there's a token in the response. | |
| if (!empty($orcid_token_json['access_token'])) { | |
| $token = $orcid_token_json['access_token']; | |
| echo "TOKEN: '$token'\n"; | |
| // Look for expiration date. | |
| if (!empty($orcid_token_json['expires_in'])) { | |
| $expiration_date = date('Y-m-d H:i:s', time() + $orcid_token_json['expires_in']); | |
| echo "TOKEN Expiration date: $expiration_date\n"; | |
| } | |
| } | |
| else { | |
| exit("Could not find the access token from response: " . $response['response'] . "\n"); | |
| } | |
| // STEP 2: RUN ORCID QUERIES w. TOKEN | |
| $query = 'family-name:Smith+AND+given-names:J*+OR+email:adam@whoi.edu'; | |
| $number_of_results = 10; | |
| $offset = 0; | |
| $response = _search_orcid_bios($token, $query, $number_of_results, $offset); | |
| $requested_url = $response['request_url']; | |
| $status = $response['code']; | |
| echo "SEARCH Request URL: $requested_url\n"; | |
| echo "SEARCH Response Code: $status\n"; | |
| // STEP 3: CONVERT ORCID+XML to JSON | |
| $orcid_search_json = _convert_orcid_xml_to_json($response['response']); | |
| // STEP 4: GET ARRAY OF RESULTS | |
| if ($error_msg = _is_orcid_error($orcid_search_json)) { | |
| exit($error_msg); | |
| } | |
| $results = _orcid_search_results($orcid_search_json); | |
| // Display results. | |
| $total_hits = $results['total']; | |
| echo "Total matches found: $total_hits\n"; | |
| if (FALSE == $results['results']) { | |
| echo "No results.\n"; | |
| } | |
| else { | |
| $start_result_num = $offset + 1; | |
| $end_result_num = $offset + count($results['results']); | |
| echo "Reporting results $start_result_num - $end_result_num\n"; | |
| foreach ($results['results'] as $idx => $result) { | |
| $result_num = $start_result_num + $idx; | |
| echo "$result_num.\n" . json_encode($result, JSON_PRETTY_PRINT) . "\n"; | |
| } | |
| } | |
| /** | |
| * Search the public ORCID API. | |
| * For ORCID fields and examples, | |
| * @see: https://members.orcid.org/api/tutorial-searching-data-using-api | |
| * | |
| * @param string $token | |
| * Access token retrieved from _request_orcid_api_token() | |
| * | |
| * @param mixed $search_parameters | |
| * Either a string, in Lucene format or an array of key-value-pairs | |
| * If string, | |
| * Example: 'family-name:Smith+AND+given-names:J*+OR+email:j.smith@example.com' | |
| * If Array, | |
| * the keys are ORCID field names and values are the strings to search with, | |
| * all fields are joined with the 'AND' operator, | |
| * if the email field is provided, it is joined with the 'OR' operator | |
| * b/c a public email field is rarely available | |
| * Example: array('family-name' => 'Smith', 'given-names' => 'J*', 'email' => 'j.smith@example.com') | |
| * yields the query: 'family-name:Smith+AND+given-names:J*+OR+email:j.smith@example.com' | |
| * | |
| * @param int $number_of_results | |
| * The number of results to return | |
| * NOTE: the response contains the totoal number of matching results | |
| * | |
| * @param int $offset | |
| * The specific numbered result, or index, at which to start. This value starts at 0 | |
| * | |
| * @return Array | |
| * Result of _orcid_curl() | |
| */ | |
| function _search_orcid_bios($token, $search_parameters, $number_of_results = 10, $offset = 0) { | |
| $endpoint = 'https://pub.orcid.org/v1.2/search/orcid-bio/'; | |
| // Build the query string. | |
| $query = ''; | |
| if (!is_array($search_parameters)) { | |
| $query = strval($search_parameters); | |
| } | |
| else { | |
| // Build the query string for ORCiD fields using Lucene syntax. | |
| $email = FALSE; | |
| foreach ($search_parameters as $field => $value) { | |
| // Handle email with the 'OR' operator b/c public email addresses are rare. | |
| if ('email' == $field) { | |
| $email = $value; | |
| unset($search_parameters[$field]); | |
| continue; | |
| } | |
| $search_parameters[$field] = $field . ':' . urlencode($value); | |
| } | |
| $query = implode('+AND+', $params); | |
| if ($email) { | |
| $query .= '+OR+email:' . urlencode($email); | |
| } | |
| } | |
| $query .= '&rows=' . $number_of_results . '&start=' . $offset; | |
| $url = $endpoint . '?q=' . $query; | |
| // Build a cURL request for _orcid_curl(). | |
| $headers = array( | |
| 'Content-Type' => 'application/orcid+xml', | |
| 'Authorization' => 'Bearer ' . $token, | |
| ); | |
| return _orcid_curl($url, $headers); | |
| } | |
| /** | |
| * Get the ORCID search results as an array. | |
| * | |
| * @param Array $orcid_json | |
| * An ORCID response converted to an associative array | |
| * | |
| * @return Array | |
| * Keys of the array: | |
| * 'total' => The total number of hits found for the search. | |
| * May be larger than number of results returned. | |
| * 'results' => FALSE, if no results returned, i.e. no matches for criteria; | |
| * Array of resulting matches capped by the number of allowed/requested results | |
| */ | |
| function _orcid_search_results($orcid_json) { | |
| $results = array( | |
| 'total' => $orcid_json['orcid-search-results']['@attributes']['num-found'], | |
| ); | |
| switch ($results['total']) { | |
| case 0: | |
| $results['results'] = FALSE; | |
| break; | |
| case 1: | |
| $results['results'] = array($orcid_json['orcid-search-results']['orcid-search-result']); | |
| break; | |
| default: | |
| $results['results'] = $orcid_json['orcid-search-results']['orcid-search-result']; | |
| break; | |
| } | |
| return $results; | |
| } | |
| /** | |
| * Check if ORCID response has an error message. | |
| * | |
| * @param Array $orcid_json | |
| * An ORCID response converted to an associative array | |
| * | |
| * @return mixed | |
| * Either FALSE if no errors, or an error message as a string | |
| */ | |
| function _is_orcid_error($orcid_json) { | |
| return !empty($orcid_json['error-desc']) ? $orcid_json['error-desc'] : FALSE; | |
| } | |
| /** | |
| * Get a long-lived access token for querying the public ORCID API. | |
| * For registration details for obtaining client ID & secret, | |
| * @see http://support.orcid.org/knowledgebase/articles/343182 | |
| * | |
| * @param string $client_id | |
| * The client ID provided by ORCID upon registration | |
| * | |
| * @param string $client_secret | |
| * The client secret provided by ORCID upon registration | |
| * | |
| * @return Array | |
| * The JSON results from the token request | |
| * Keys include: | |
| * 'access_token' -> the long-lived token string | |
| * 'expires_in' -> the expiration date of the token when you add this value to 'time()' | |
| */ | |
| function _request_orcid_api_token($client_id, $client_secret) { | |
| $headers = array( | |
| 'Accept' => 'application/json', | |
| 'Content-Type' => 'application/x-www-form-urlencoded', | |
| ); | |
| $data = array( | |
| // Provided by ORCID. | |
| // @see: http://support.orcid.org/knowledgebase/articles/343182 | |
| 'client_id' => $client_id, | |
| 'client_secret' => $client_secret, | |
| // Hard-coded values requires by ORCID | |
| 'scope' => '/read-public', | |
| 'grant_type' => 'client_credentials', | |
| ); | |
| return _orcid_curl('https://pub.orcid.org/oauth/token', $headers, 'POST', $data); | |
| } | |
| /** | |
| * Convert an 'application/orcid+xml' string to a JSON object. | |
| * | |
| * @param string $xml | |
| * The ORCID XML | |
| * | |
| * @param Array | |
| * An associative array from json_decode() | |
| * @see http://php.net/manual/en/function.json-decode.php | |
| */ | |
| function _convert_orcid_xml_to_json($xml) { | |
| $simple_xml = simplexml_load_string($xml); | |
| $json = json_encode($simple_xml); | |
| return json_decode($json, TRUE); | |
| } | |
| /** | |
| * Make a cURL request. | |
| * | |
| * @param string $url | |
| * The URL to request. | |
| * | |
| * @param Array $headers | |
| * Request headers to set, formatted as 'header' => 'value' | |
| * e.g. array('Content-Type' => 'application/orcid+xml', 'Accept' => 'application/json'); | |
| * | |
| * @param Array $post_data (optional) | |
| * An array for http_build_query() of POST fields and values. | |
| * @see http://php.net/manual/en/function.http-build-query.php | |
| * | |
| * @param Array | |
| * Associative array with keys: | |
| * 'request_url' -> the URL that was requested (string) | |
| * 'response' -> the HTTP responde body (string) | |
| * 'code' -> response code (int) | |
| */ | |
| function _orcid_curl($url, $headers, $method = 'GET', $post_data = FALSE) { | |
| $ch = curl_init(); | |
| curl_setopt($ch, CURLOPT_URL, $url); | |
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
| curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | |
| // Set the headers. | |
| if (!empty($headers)) { | |
| $curl_headers = array(); | |
| foreach ($headers as $header => $value) { | |
| $curl_headers[] = $header . ': ' . $value; | |
| } | |
| curl_setopt($ch, CURLOPT_HTTPHEADER, $curl_headers); | |
| } | |
| if ('POST' == $method) { | |
| curl_setopt($ch, CURLOPT_POST, TRUE); | |
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data)); | |
| } | |
| // Execute the HTTP Request. | |
| $result = curl_exec($ch); | |
| $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
| // Close the cURL. | |
| curl_close($ch); | |
| // Return the data. | |
| return array( | |
| 'request_url' => $url, | |
| 'response' => $result, | |
| 'code' => $httpcode, | |
| ); | |
| } | |
| ?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment