You are here

biblio.crossref.client.php in Bibliography Module 6.2

File

modules/crossref/biblio.crossref.client.php
View source
<?php

class BiblioCrossRefClient {
  const BASE_URL = 'http://www.crossref.org/openurl/';
  private $pid;
  private $doi;
  private $query;
  private $url;
  private $nodes;
  private $node;
  private $parser;
  private $element;
  private $attribute;
  private $auth_category;
  private $contrib_count;
  private $org_count;
  private $field_map;
  private $type_map;
  public function __construct($doi = '', $id = '') {
    $this
      ->setDOI($doi);
    $this
      ->setUserID($id);
    $this
      ->setURL(self::BASE_URL);
    $this->field_map = array();
    $this->type_map = array();
  }
  public function setURL($url) {
    $this->url = $url;
  }
  public function setDOI($doi) {
    $this->doi = $doi;
  }
  public function getDOI() {
    return $this->doi;
  }
  public function setUserID($id) {
    $this->pid = $id;
  }
  public function getUserID() {
    return $this->pid;
  }
  public function getQuery() {
    return $this->query;
  }
  public function fetch() {
    $this->query = $this->url . '?pid=' . $this->pid . '&noredirect=true&format=unixref&id=doi%3A' . $this->doi;
    if (!($xml = file_get_contents($this->query))) {
      drupal_set_message(t('Could not open crossref.org for XML input'), 'error');
      return;
    }
    $this->nodes = array();
    $this->parser = drupal_xml_parser_create($xml);

    // use case-folding so we are sure to find the tag in
    xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, FALSE);
    xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, TRUE);
    xml_set_object($this->parser, $this);
    xml_set_element_handler($this->parser, 'unixref_startElement', 'unixref_endElement');
    xml_set_character_data_handler($this->parser, 'unixref_characterData');
    if (!xml_parse($this->parser, $xml)) {
      drupal_set_message(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser)), 'error');
    }
    xml_parser_free($this->parser);
    return $this->node;
  }
  function fetchByAuthorTitle($author, $title) {
    $qdata = simplexml_load_string('<query_batch version="2.0" xsi:schemaLocation="http://www.crossref.org/qschema/2.0 http://www.crossref.org/qschema/crossref_query_input2.0.xsd" xmlns="http://www.crossref.org/qschema/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />');
    $qdata->head->email_address = $this->pid;
    $qdata->head->doi_batch_id = uniqid('NA');
    $qdata->body->query = '';
    $query = $qdata->body->query;
    $query['enable-multiple-hits'] = 'exact';
    $query['key'] = 'key';
    $query->article_title = $title;
    $query->article_title['match'] = 'fuzzy';
    $query->author = $author;
    $query->author['search-all-authors'] = 'true';
    $this->query = url($this->url, array(
      'external' => TRUE,
      'query' => array(
        'pid' => $this->pid,
        'noredirect' => 'true',
        'format' => 'unixref',
        'qdata' => (string) $qdata
          ->asXml(),
      ),
    ));
    $response = drupal_http_request($this->query);
    if ($response->code != 200) {
      drupal_set_message(t('Could not open crossref.org for XML author/title query.'), 'error');
      return array();
    }
    $xml = simplexml_load_string($response->data);
    $results = array();
    foreach ($xml->doi_record as $record) {
      $result = array(
        'full' => $record
          ->asXml(),
        'doi' => $record
          ->xpath('.//doi[1]'),
        'title' => $record
          ->xpath('.//title[1]'),
      );
      $result['full'] = preg_replace('@<[^>]+>@s', '.', $result['full']);
      $result['full'] = preg_replace('@\\.[\\s\\.]+@', '. ', $result['full']);
      $result['full'] = trim($result['full'], '. ');
      $result['doi'] = (string) $result['doi'][0];
      $result['title'] = (string) $result['title'][0];
      $results[] = $result;
    }
    return $results;
  }
  function unixref_startElement($parser, $name, $attrs) {
    switch ($name) {
      case 'doi_record':
        $this->node = array();
        $this->element = $name;
        break;
      case 'book':
      case 'journal':
      case 'standard':
      case 'conference':
      case 'report-paper':
      case 'dissertation':
      case 'database':
      case 'sa_component':
        $this->node['biblio_type'] = $this
          ->_unixref_type_map($name);
        $this->element = $name;
        break;
      case 'journal_article':
      case 'conference_paper':
      case 'content_item':
      case 'report-paper_metadata':
      case 'standard_metadata':
      case 'database_date':
      case 'component':
        $this->node['year'] = '';
        $this->node['doi'] = '';
        $this->element = $name;
        break;
      case 'person_name':
        $this->auth_category = $this
          ->_unixref_get_contributor_category($attrs['contributor_role']);
        if (!isset($this->contrib_count)) {
          $this->contrib_count = 0;
        }
        $this->element = $name;
        break;
      case 'organization':
        if (!isset($this->org_count)) {
          $this->org_count = 0;
        }
        $this->element = $name;
        break;
      case 'issn':
        if (isset($attrs['media_type'])) {
          $this->attribute = $attrs['media_type'];
        }
        $this->element = $name;
        break;
      case 'isbn':
        if (isset($attrs['media_type'])) {
          $this->attribute = $attrs['media_type'];
        }
        $this->element = $name;
        break;
      case 'i':

      // HTML font style tags
      case 'b':
      case 'u':
      case 'sub':
      case 'sup':
        $this
          ->unixref_characterData(NULL, ' <' . $name . '>');
        break;
      default:
        $this->element = $name;
    }
  }
  function unixref_decode(&$item, $key) {
    $item = html_entity_decode($item, NULL, 'UTF-8');
  }
  function unixref_endElement($parser, $name) {
    switch ($name) {
      case 'doi_record':
        array_walk_recursive($this->node, array(
          $this,
          'unixref_decode',
        ));
        $this->node['biblio_crossref_id'] = $this->node['biblio_doi'] = $this
          ->getDOI();
        $this->node['biblio_crossref_md5'] = md5(serialize($this->node));
        $this->nodes[] = $this->node;

        //biblio_save_node($node, $batch, $session_id, $save_node);
        break;
      case 'person_name':
        $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['auth_type'] = _biblio_get_auth_type($this->auth_category, $this->node['biblio_type']);
        $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['name'] = $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['lastname'];
        if (isset($this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['firstname'])) {
          $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['name'] .= ', ' . $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['firstname'];
        }
        $this->auth_category = '';
        $this->contrib_count++;
        break;
      case 'organization':
        $this->node['biblio_contributors'][5][$this->org_count]['auth_type'] = _biblio_get_auth_type(5, $this->node['biblio_type']);
        $this->org_count++;
        break;
      case 'pages':
        if (isset($this->node['biblio_first_page'])) {
          $this->node['biblio_pages'] = $this->node['biblio_first_page'];
        }
        if (isset($this->node['biblio_last_page'])) {
          $this->node['biblio_pages'] .= ' - ' . $this->node['biblio_last_page'];
        }
        break;
      case 'publication_date':
        break;
      case 'journal_issue':
        $this->node['biblio_date'] = (!empty($this->node['month']) ? $this->node['month'] . '/' : '') . $this->node['year'];
        if (empty($this->node['biblio_year'])) {
          $this->node['biblio_year'] = $this->node['year'];
        }
        break;
      case 'journal_article':
      case 'conference_paper':
      case 'content_item':
      case 'report-paper_metadata':
      case 'standard_metadata':
      case 'database_date':
      case 'component':
        if (!empty($this->node['year'])) {
          $this->node['biblio_year'] = $this->node['year'];
        }

        //        $this->node['biblio_doi']  = $this->node['doi'];
        break;
      case 'issn':
      case 'isbn':
        $this->attribute = '';
        break;
      case 'i':

      // HTML font style tags
      case 'b':
      case 'u':
      case 'sub':
      case 'sup':
        $this
          ->unixref_characterData(NULL, '</' . $name . '> ');
        break;
      default:
    }
  }
  function unixref_characterData($parser, $data) {
    $data = htmlspecialchars_decode($data);
    if (trim($data)) {
      switch ($this->element) {
        case 'surname':
          $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['lastname'] .= $data;
          break;
        case 'given_name':
          $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['firstname'] .= $data;
          break;
        case 'suffix':
          $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['suffix'] .= $data;
          break;
        case 'affiliation':
          $this->node['biblio_contributors'][$this->auth_category][$this->contrib_count]['affiliation'] .= $data;
          break;
        case 'organization':
          $this->node['biblio_contributors'][5][$this->org_count]['name'] .= $data;
          break;
        case 'year':
          $this->node['year'] = $data;
          break;
        case 'month':
          $this->node['month'] = $data;
          break;
        case 'day':
          $this->node['day'] = $data;
          break;
        case 'issn':
        case 'isbn':
          if ($this->attribute == 'print') {
            if ($field = $this
              ->_unixref_field_map(trim($this->element))) {
              $this->node[$field] = $data;
            }
          }
          break;
        default:
          if ($field = $this
            ->_unixref_field_map(trim($this->element))) {
            $this->node[$field] .= $data;
          }
      }
    }
  }

  /*
   * map a unixref XML field to a biblio field
   */
  function _unixref_field_map($field) {
    if (empty($this->field_map)) {
      $this->field_map = biblio_get_map('field_map', 'crossref');
    }
    return isset($this->field_map[$field]) ? $this->field_map[$field] : FALSE;
  }
  function _unixref_type_map($type) {
    if (empty($this->type_map)) {
      $this->type_map = biblio_get_map('type_map', 'crossref');
    }
    return isset($this->type_map[$type]) ? $this->type_map[$type] : 129;

    //return the biblio type or 129 (Misc) if type not found
  }
  function _unixref_get_contributor_category($role) {
    if ($role == 'author') {
      return 1;
    }
    if ($role == 'editor') {
      return 2;
    }
    if ($role == 'chair') {
      return 3;
    }
    if ($role == 'translator') {
      return 4;
    }
    return NULL;
  }

}

Classes