call(array('OpenaireModelSearch', 'loadServiceUrls')); $this -> pageSize = $cache -> call(array('OpenaireModelSearch', 'loadPageSize')); list($this -> defaultGeneralCriteria, $this -> defaultOtherCriteria) = $cache -> call(array('OpenaireModelSearch', 'loadDefaultForm')); } // Get service URLs from DB public static function loadServiceUrls() { $serviceUrls = array(); $db =& JFactory :: getDBO(); $db -> setQuery('SELECT * FROM `#__openaire` WHERE `key` like \'serviceUrl.%\''); foreach ($db -> loadAssocList() as $url) $serviceUrls[$url['key']] = $url['value']; return $serviceUrls; } // Get page size from DB public static function loadPageSize() { $db =& JFactory :: getDBO(); $db -> setQuery('SELECT `value` FROM `#__openaire` WHERE `key` = \'pageSize\''); return $db -> loadResult(); } // Get default form from dnet backend public static function loadDefaultForm() { $defaultGeneralCriteria = NULL; $defautlOtherCriteria = array(); $xml = self :: doGetXMLRequest('xmlForm', array(), 'openaire'); if ($xml == NULL) { // invalid xml JLog :: getInstance() -> addEntry(array('level' => 'error', 'comment' => 'Error loading default form: invalid XML response')); return; } foreach (self :: parseForm($xml) as $defaultSearchField) { if ($defaultSearchField['displayName'] == '') $defaultGeneralCriteria = $defaultSearchField; else $defaultOtherCriteria[] = $defaultSearchField; } return array($defaultGeneralCriteria, $defaultOtherCriteria); } public function getProjectPublications($project) { JLog :: getInstance() -> addEntry(array('level' => 'debug', 'comment' => "Retrieving publications of project $project")); $parameters = array(); $parameters['query'][0] = 'project="' . $project . '"'; $parameters['format'][0] = 'xml'; $parameters['size'][0] = 1; $xml = self :: doGetXMLRequest('xmlResults.action', $parameters, 'openaire'); if ($xml == NULL) { // invalid xml JLog :: getInstance() -> addEntry(array('level' => 'error', 'comment' => "Error counting publications of project $project: invalid XML response")); return NULL; } $publications = array(); $result = $this -> parseResult($xml); $numberOfDocuments = $result['numberOfDocuments']; JLog :: getInstance() -> addEntry(array('level' => 'debug', 'comment' => "Found $numberOfDocuments publications")); $parameters['size'][0] = 200; $parameters['view'][0] = 'all'; for ($page = 1; $page <= ceil($numberOfDocuments / 200); $page++) { JLog :: getInstance() -> addEntry(array('level' => 'debug', 'comment' => "Retrieving page $page")); $parameters['page'][0] = $page; $xml = self :: doGetXmlRequest('xmlResults.action', $parameters, 'openaire'); if ($xml == NULL) { // invalid xml JLog :: getInstance() -> addEntry(array('level' => 'error', 'comment' => "Error retrieving publications of project $acronym: invalid XML response")); return NULL; } $result = $this -> parseResult($xml); $publications = array_merge($publications, $result['documents']); } return $publications; } // Perform a GET request to the dnet backend and retrieve XML data private static function doGetXMLRequest($url, $parameters, $provider) { $request = new HttpRequest(self :: $serviceUrls['serviceUrl.' . $provider] . $url, HttpRequest :: METH_GET); $request -> setQueryData(implode('&', array_map("outer", array_keys($parameters), $parameters))); $request -> setOptions(array('redirect' => 3)); $log =& JLog :: getInstance(); $log -> addEntry(array('level' => 'debug', 'comment' => 'HTTP request is ' . $request -> getUrl() . '?' . $request -> getQueryData())); try { $request -> send(); if ($request -> getResponseCode() == 200) // success return $xml = DOMDocument :: loadXML(trim($request -> getResponseBody())); $log -> addEntry(array('level' => 'error', 'comment' => 'HTTP request ' . $request -> getUrl() . '?' . $request -> getQueryData() . ' failed: ' . $request -> getResponseStatus())); return NULL; } catch (HttpException $e) { $log -> addEntry(array('level' => 'error', 'comment' => 'HTTP request ' . $request -> getUrl() . '?' . $request -> getQueryData() . ' failed: ' . $e)); return NULL; } } // Perform a GET request to the dnet backend and retrieve plain text data private static function doGetPlainTextRequest($url, $parameters, $provider) { $request = new HttpRequest(self :: $serviceUrls['serviceUrl.' . $provider] . $url, HttpRequest :: METH_GET); $request -> setQueryData(implode('&', array_map("outer", array_keys($parameters), $parameters))); $request -> setOptions(array('redirect' => 3)); $log =& JLog :: getInstance(); $log -> addEntry(array('level' => 'debug', 'comment' => 'HTTP request is ' . $request -> getUrl() . '?' . $request -> getQueryData())); try { $request -> send(); if ($request -> getResponseCode() == 200) // success return trim($request -> getResponseBody()); $log -> addEntry(array('level' => 'error', 'comment' => 'HTTP request ' . $request -> getUrl() . '?' . $request -> getQueryData() . ' failed: ' . $request -> getResponseStatus())); return NULL; } catch (HttpException $e) { $log -> addEntry(array('level' => 'error', 'comment' => 'HTTP request ' . $request -> getUrl() . '?' . $request -> getQueryData() . ' failed: ' . $e)); return NULL; } } // Parse form XML as returned from the dnet backend private static function parseForm($xml) { $form = $xml -> getElementsByTagName('form'); if ($form -> length <= 0) // no form tag found return NULL; $form = $form -> item(0); $searchFields = array(); foreach ($form -> childNodes as $searchField) { // for each child if ($searchField -> nodeName == 'searchField') { // searchField tag found $displayName = ''; $fields = array(); foreach ($searchField -> childNodes as $child) { // for each child if ($child -> nodeName == 'displayName') // displayName tag found $displayName = trim($child -> nodeValue); else if ($child -> nodeName == 'checkbox') { // checkbox tag found $name = ''; $label = ''; foreach ($child -> childNodes as $checkboxChild) { // for each child if ($checkboxChild -> nodeName == 'name') // name tag found $name = trim($checkboxChild -> nodeValue); else if ($checkboxChild -> nodeName == 'label') // label tag found $label = trim($checkboxChild -> nodeValue); } $fields[] = array('type' => 'checkbox', 'name' => $name, 'label' => $label, 'selected' => FALSE); } else if ($child -> nodeName == 'hidden') { // hidden tag found $name = ''; $value = ''; foreach ($child -> childNodes as $hiddenChild) { // for each child if ($hiddenChild -> nodeName == 'name') // name tag found $name = trim($hiddenChild -> nodeValue); else if ($hiddenChild -> nodeName == 'value') // value tag found $value = trim($hiddenChild -> nodeValue); } $fields[] = array('type' => 'hidden', 'name' => $name, 'value' => $value); } else if ($child -> nodeName == 'text') { // text tag found $name = ''; $value = ''; foreach ($child -> childNodes as $textChild) { // for each child if ($textChild -> nodeName == 'name') // name tag found $name = trim($textChild -> nodeValue); else if ($textChild -> nodeName == 'value') // value tag found $value = trim($textChild -> nodeValue); } $fields[] = array('type' => 'text', 'name' => $name, 'value' => $value); } else if ($child -> nodeName == 'select') { // select tag found $name = ''; $options = array(); foreach ($child -> childNodes as $selectChild) { // for each child if ($selectChild -> nodeName == 'name') // name tag found $name = trim($selectChild -> nodeValue); else if ($selectChild -> nodeName == 'options') { // options tag found foreach ($selectChild -> childNodes as $option) { // for each child if ($option -> nodeName == 'option') { // option tag found $label = ''; $value = ''; $selected = ($option -> attributes -> getNamedItem('default') != NULL) && (trim($option -> attributes -> getNamedItem('default') -> nodeValue) != ''); foreach ($option -> childNodes as $optionChild) { // for each childNodes if ($optionChild -> nodeName == 'label') // label tag found $label = trim($optionChild -> nodeValue); else if ($optionChild -> nodeName == 'value') // value tag found $value = trim($optionChild -> nodeValue); } $options[] = array('label' => $label, 'value' => $value, 'selected' => $selected); } } } } $fields[] = array('type' => 'select', 'name' => $name, 'options' => $options); } } $searchFields[] = array('displayName' => $displayName, 'fields' => $fields); } } return $searchFields; } // Perform a search for documents matching certain criteria public function search($parameters = array(), $url = 'Search', $href = '', $provider = 'openaire') { $log =& JLog :: getInstance(); $log -> addEntry(array('level' => 'debug', 'comment' => 'Searching documents')); $keyword = ''; $form = array('defaultGeneralCriteria' => $this -> defaultGeneralCriteria, 'generalCriteria' => array($this -> defaultGeneralCriteria), 'otherCriteria' => $this -> defaultOtherCriteria); if (array_key_exists('href', $parameters) && ($parameters['href'] != NULL) && (count($parameters['href']) > 0)) { // href exists; ignore (almost) everything else $href = base64_decode($parameters['href'][0]); if ($href != '') { list($newUrl, $newParameters) = $this -> parseUrl($href); if (array_key_exists('page', $parameters) && ($parameters['page'] != NULL) && (count($parameters['page']) > 0)) // page exists; append it $newParameters['page'][0] = $parameters['page'][0]; if (array_key_exists('Itemid', $parameters) && ($parameters['Itemid'] != NULL) && (count($parameters['Itemid']) > 0)) // Itemid exists; append it $newParameters['Itemid'][0] = $parameters['Itemid'][0]; $log -> addEntry(array('level' => 'debug', 'comment' => 'Redirecting to ' . $href)); $href = $parameters['href'][0]; $parameters = $newParameters; $url = $newUrl; } } if (count($parameters) == 0) // no request to be made return array('keyword' => $keyword, 'form' => $form, 'href' => ''); if ((!array_key_exists('expand', $parameters)) || ($parameters['expand'] == NULL) || (count($parameters['expand']) == 0) || ($parameters['expand'][0] != 'false')) { // expand unless explicitly denied if ((!array_key_exists('size', $parameters)) || ($parameters['size'] == NULL) || (count($parameters['size']) == 0)) $parameters['size'][] = $this -> pageSize; $parameters['view'][] = 'summary'; $parameters['includeForm'][] = 'true'; $parameters['includeFilters'][] = 'true'; $parameters['includeStats'][] = 'true'; $parameters['includeResults'][] = 'true'; $parameters['format'][] = 'xml'; $log -> addEntry(array('level' => 'debug', 'comment' => 'Expanded parameters')); } if (array_key_exists('fields', $parameters) && ($parameters['fields'] != NULL)) { foreach ($parameters['fields'] as & $fields) { if ($fields == '') $fields = '""'; } } $xml = $this -> doGetXMLRequest($url, $parameters, $provider); if ($xml == NULL) { $log -> addEntry(array('level' => 'error', 'comment' => 'Error performing search for documents: invalid XML response')); return NULL; } $activatedForm = self :: parseForm($xml); if ($activatedForm != NULL) { $generalCriteria = array(); $otherCriteria = array(); foreach ($activatedForm as $activatedSearchField) { if ($activatedSearchField['displayName'] == '') $generalCriteria[] = $this -> activateSearchField($this -> defaultGeneralCriteria, $activatedSearchField); } foreach ($this -> defaultOtherCriteria as $defaultSearchField) { $activatedSearchField = $this -> getSearchField($activatedForm, $defaultSearchField['displayName']); $otherCriteria[] = (($activatedSearchField != NULL) ? $this -> activateSearchField($defaultSearchField, $activatedSearchField) : $defaultSearchField); } $form = array('defaultGeneralCriteria' => $this -> defaultGeneralCriteria, 'generalCriteria' => $generalCriteria, 'otherCriteria' => $otherCriteria); $keywordField = (array_key_exists(0, $generalCriteria) ? $this -> getField($generalCriteria[0], 'keyword') : NULL); if ($keywordField != NULL) $keyword = $keywordField['value']; } $filters = $this -> parseFilters($xml); $statistics = $this -> parseStatistics($xml); if ($filters != NULL) { foreach ($filters as $filter) { // ommit filtered statistics foreach ($statistics as $i => $statistic) { if ($filter['name'] == $statistic['name']) { array_splice($statistics, $i, 1); break; } } } } $result = $this -> parseResult($xml); $result['size'] = $parameters['size'][0]; return array('keyword' => $keyword, 'form' => $form, 'href' => $href, 'filters' => $filters, 'statistics' => $statistics, 'result' => $result); } // Perform a search for document details of a certain document public function searchDocument($parameters, $provider) { $log =& JLog :: getInstance(); $log -> addEntry(array('level' => 'debug', 'comment' => 'Searching document details')); if ((!array_key_exists('href', $parameters)) || ($parameters['href'] == NULL) || (count($parameters['href']) == 0) || ($parameters['href'][0] == '')) // href does not exist; nothing to search for return array(); $href = base64_decode($parameters['href'][0]); list($url, $newParameters) = $this -> parseUrl($href); $newParameters['view'][] = 'all'; $newParameters['format'][] = 'xml'; $log -> addEntry(array('level' => 'debug', 'comment' => 'Redirecting to ' . $href)); $xml = $this -> doGetXMLRequest($url, $newParameters, $provider); if ($xml == NULL) { $log -> addEntry(array('level' => 'error', 'comment' => 'Error performing search for document details: invalid XML response')); return NULL; } return $this -> parseDocument($xml); } // Perform a search for BibTeX of a certain document public function searchBibTeX($parameters, $provider) { $log =& JLog :: getInstance(); $log -> addEntry(array('level' => 'debug', 'comment' => 'Searching document BibTeX')); if ((!array_key_exists('href', $parameters)) || ($parameters['href'] == NULL) || (count($parameters['href']) == 0) || ($parameters['href'][0] == '')) // href does not exist; nothing to search for return NULL; $href = base64_decode($parameters['href'][0]); list($url, $newParameters) = $this -> parseUrl($href); $log -> addEntry(array('level' => 'debug', 'comment' => 'Redirecting to ' . $href)); $bibTeX = $this -> doGetPlainTextRequest($url, $newParameters, $provider); if (($bibTeX == NULL) || ($bibTeX == '')) { $log -> addEntry(array('level' => 'error', 'comment' => 'Error performing search for document BibTeX: no response')); return NULL; } return $bibTeX; } // Split a url in base and query parameters private function parseUrl($url) { list($url, $query) = explode('?', $url); foreach (explode('&', $query) as $parameter) { list($name, $value) = explode('=', $parameter, 2); $parameters[urldecode($name)][] = urldecode($value); } return array($url, $parameters); } // Parse filters out of the XML returned from the dnet backend. private function parseFilters($xml) { $filters = $xml -> getElementsByTagName('filters'); if ($filters -> length <= 0) // no filters tags found return NULL; $filters = $filters -> item(0); $result = array(); foreach ($filters -> childNodes as $filter) { // for each child if ($filter -> nodeName == 'filter') { // filter tag found $name = $filter -> attributes -> getNamedItem('name'); $name = (($name == NULL) ? '' : trim($name -> nodeValue)); $value = $filter -> attributes -> getNamedItem('value'); $value = (($value == NULL) ? '' : trim($value -> nodeValue)); $href = $filter -> attributes -> getNamedItem('href'); $href = (($href == NULL) ? '' : base64_encode(html_entity_decode(trim($href -> nodeValue)))); $result[] = array('name' => $name, 'value' => $value, 'href' => $href); } } return $result; } // Parse statistics out of the XML returned from the dnet backend. private function parseStatistics($xml) { $statistics = $xml -> getElementsByTagName('statistics'); if ($statistics -> length <= 0) // no statistics tag found return NULL; $statistics = $statistics -> item(0); $fields = array(); foreach ($statistics -> childNodes as $statisticsChild) { // for each child if ($statisticsChild -> nodeName == 'fields') { // fields tag found foreach ($statisticsChild -> childNodes as $field) { // for each child if ($field -> nodeName == 'field') { // field tag found $fieldName = $field-> attributes -> getNamedItem('name'); $fieldName = (($fieldName == NULL) ? '' : trim($fieldName -> nodeValue)); $values = array(); foreach ($field -> childNodes as $fieldChild) { // for each child if ($fieldChild -> nodeName == 'values') { // values tag found foreach ($fieldChild -> childNodes as $value) { // for each child if ($value -> nodeName == 'value') { // value tag found $valueName = $value -> attributes -> getNamedItem('name'); $valueName = (($valueName == NULL) ? '' : trim($valueName -> nodeValue)); $count = $value -> attributes -> getNamedItem('count'); $count = (($count == NULL) ? 0 : trim($count -> nodeValue)); $href = $value -> attributes -> getNamedItem('href'); $href = (($href == NULL) ? '' : base64_encode(html_entity_decode(trim($href -> nodeValue)))); $values[] = array('name' => $valueName, 'count' => $count, 'href' => $href); } } } } $fields[] = array('name' => $fieldName, 'values' => $values); } } } } return $fields; } // Parse search result out of the XML returned from the dnet backend. private function parseResult($xml) { $result = $xml -> getElementsByTagName('documents'); if ($result -> length <= 0) // no documents tag found return NULL; $result = $result -> item(0); $query = ''; $numberOfDocuments = 0; $page = 1; $numberOfPages = 0; $documents = array(); foreach ($result -> childNodes as $resultChild) { if ($resultChild -> nodeName == 'query') $query = trim($resultChild -> nodeValue); else if ($resultChild -> nodeName == 'numberOfDocuments') $numberOfDocuments = trim($resultChild -> nodeValue); else if ($resultChild -> nodeName == 'currentPage') $page = trim($resultChild -> nodeValue); else if ($resultChild -> nodeName == 'numberOfPages') $numberOfPages = trim($resultChild -> nodeValue); else if ($resultChild -> nodeName == 'document') { $fields = array(); foreach ($resultChild -> childNodes as $field) { // for each child if ($field -> nodeName == 'field') { // field tag found $name = ''; $values = array(); foreach ($field -> childNodes as $fieldChild) { // for each child if ($fieldChild -> nodeName == 'name') // name tag found $name = trim($fieldChild -> nodeValue); else if ($fieldChild -> nodeName == 'values') { // values tag found foreach ($fieldChild -> childNodes as $value) { // for each child if ($value -> nodeName == 'value') { // value tag found $type = ''; $displayValue = ''; $urlType = ''; $href = ''; $action = ''; foreach ($value -> childNodes as $valueChild) { // for each child if ($valueChild -> nodeName == 'type') // type tag found $type = trim($valueChild -> nodeValue); else if ($valueChild -> nodeName == 'displayValue') // displayValue tag found $displayValue = trim($valueChild -> nodeValue); else if ($valueChild -> nodeName == 'urlType') // urlType tag found $urlType = trim($valueChild -> nodeValue); else if ($valueChild -> nodeName == 'href') // href tag found $href = urldecode(trim($valueChild -> nodeValue)); else if ($valueChild -> nodeName == 'action') // action tag found $action = trim($valueChild -> nodeValue); } if ($type == 'text/plain') $values[] = array('type' => 'text/plain', 'displayValue' => $displayValue); else if ($type == 'url') if ($urlType == 'internal') $values[] = array('type' => 'url', 'displayValue' => $displayValue, 'urlType' => 'internal', 'href' => $href, 'action' => $action); else $values[] = array('type' => 'url', 'displayValue' => $displayValue, 'urlType' => $urlType, 'href' => $href); } } } } $fields[] = array('name' => $name, 'values' => $values); } } $documents[] = $fields; } } return array('query' => $query, 'numberOfDocuments' => $numberOfDocuments, 'page' => $page, 'numberOfPages' => $numberOfPages, 'documents' => $documents); } // Parse a single document out of the XML returned from the dnet backend. private function parseDocument($xml) { $result = $xml -> getElementsByTagName('document'); if ($result -> length <= 0) // no documents tag found return NULL; $result = $result -> item(0); $fields = array(); foreach ($result -> childNodes as $field) { // for each child if ($field -> nodeName == 'field') { // field tag found $name = ''; $values = array(); foreach ($field -> childNodes as $fieldChild) { // for each child if ($fieldChild -> nodeName == 'name') // name tag found $name = trim($fieldChild -> nodeValue); else if ($fieldChild -> nodeName == 'values') { // values tag found foreach ($fieldChild -> childNodes as $value) { // for each child if ($value -> nodeName == 'value') { // value tag found $type = ''; $displayValue = ''; $urlType = ''; $href = ''; $docId = ''; foreach ($value -> childNodes as $valueChild) { // for each child if ($valueChild -> nodeName == 'type') // type tag found $type = trim($valueChild -> nodeValue); else if ($valueChild -> nodeName == 'displayValue') // displayValue tag found $displayValue = trim($valueChild -> nodeValue); else if ($valueChild -> nodeName == 'urlType') // urlType tag found $urlType = trim($valueChild -> nodeValue); else if ($valueChild -> nodeName == 'href') // href tag found $href = urldecode(trim($valueChild -> nodeValue)); else if ($valueChild -> nodeName == 'docId') // docId tag found $docId = trim($valueChild -> nodeValue); } if ($type == 'text/plain') $values[] = array('type' => 'text/plain', 'displayValue' => $displayValue); else if ($type == 'url') $values[] = array('type' => 'url', 'displayValue' => $displayValue, 'urlType' => $urlType, 'href' => $href, 'docId' => $docId); } } } } $fields[] = array('name' => $name, 'values' => $values); } } return $fields; } // Return a copy of a default search field, activating its inner fields as specified by an activated search field. private function activateSearchField($defaultSearchField, $activatedSearchField) { $fields = array(); foreach ($defaultSearchField['fields'] as $defaultField) { $activatedField = $this -> getField($activatedSearchField, $defaultField['name']); $field = array('name' => $defaultField['name'], 'type' => $defaultField['type']); switch ($field['type']) { case 'checkbox': $field['label'] = $defaultField['label']; $field['selected'] = ($activatedField != NULL); break; case 'hidden': case 'text': $field['value'] = (($activatedField != NULL) ? $activatedField['value'] : ''); break; case 'select': $options = array(); foreach($defaultField['options'] as $defaultOption) { $activatedOption = $this -> getOption($activatedField, $defaultOption['label']); $option = array('label' => $defaultOption['label'], 'value' => $defaultOption['value']); $option['selected'] = ($activatedOption != NULL); $options[] = $option; } $field['options'] = $options; } $fields[] = $field; } return array('displayName' => $defaultSearchField['displayName'], 'fields' => $fields); } // Retrieve a search field from an array of search fields by display name. private function getSearchField($searchFields, $searchFieldDisplayName) { foreach ($searchFields as $searchField) { if ($searchField['displayName'] == $searchFieldDisplayName) return $searchField; } return NULL; } // Retrieve a field of a search field by name. private function getField($searchField, $fieldName) { foreach ($searchField['fields'] as $field) { if ($field['name'] == $fieldName) return $field; } return NULL; } // Retrieve a search field option by label. private function getOption($selectField, $optionLabel) { foreach ($selectField['options'] as $option) { if ($option['label'] == $optionLabel) return $option; } return NULL; } } ?>