From 11c67234d00cb43889f9cdb3b6b3d7557f3de702 Mon Sep 17 00:00:00 2001 From: Ross Singer Date: Wed, 26 Mar 2014 16:50:43 -0400 Subject: [PATCH] Initial import as standalone lib --- .gitignore | 6 + composer.json | 26 +++ src/SRU/Client.php | 353 +++++++++++++++++++++++++++++ src/SRU/Record.php | 72 ++++++ src/SRU/ScanResponse.php | 21 ++ src/SRU/SearchRetrieveResponse.php | 97 ++++++++ 6 files changed, 575 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 src/SRU/Client.php create mode 100644 src/SRU/Record.php create mode 100644 src/SRU/ScanResponse.php create mode 100644 src/SRU/SearchRetrieveResponse.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..33832a3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ + +.idea/ +atlassian-ide-plugin.xml +vendor/ + +composer.lock diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..fd7aaf0 --- /dev/null +++ b/composer.json @@ -0,0 +1,26 @@ +{ + "name": "talis/SRUClient-php", + "description": "This is a php client library for SRU (http://www.loc.gov/standards/sru/)", + "keywords": ["sru", "php", "client library"], + "homepage": "https://github.com/talis/SRUclient-php", + "type": "library", + "license": "MIT", + "authors":[ + { + "name":"Ross Singer", + "email": "rxs@talis.com", + "homepage":"http://engineering.talis.com" + } + ], + "require":{ + "php": ">=5.3.0", + "phpunit/phpunit": ">=3.7.0@stable", + "monolog/monolog": ">=1.5.0", + "guzzle/guzzle":"~3.7" + }, + "autoload":{ + "psr-0": { + "SRU": "src" + } + } +} \ No newline at end of file diff --git a/src/SRU/Client.php b/src/SRU/Client.php new file mode 100644 index 0000000..96f19ce --- /dev/null +++ b/src/SRU/Client.php @@ -0,0 +1,353 @@ +baseUrl = $baseUrl; + if (isset($options['recordSchema'])) + { + $this->defaultRecordSchema = $options['recordSchema']; + } + if(isset($options['maximumRecords'])) + { + $this->defaultMaximumRecords = $options['maximumRecords']; + } + if(isset($options['httpMethod'])) + { + $this->defaultHttpMethod = $options['httpMethod']; + } + if(isset($options['version'])) + { + $this->defaultSRUVersion = $options['version']; + } + } + + /** + * Returns a DOMDocument of the explain operation response (or a string if $raw is true) + * @param bool $raw + * @return \DOMDocument|string + */ + public function explain($raw = false) + { + $explainResponse = $this->fetch(array("version" => $this->getDefaultSRUVersion(), "operation" => "explain")); + if ($raw == true) + { + $explain = $explainResponse->getBody(); + } + else + { + $explain = new \DOMDocument(); + $explain->loadXML($explainResponse->getBody()); + } + + return ($explain); + } + + /** + * Alias for searchRetrieve() + * + * @param string $query + * @param array $options + * @param bool $raw + * @return SearchRetrieveResponse|string + */ + public function search($query, $options = array(), $raw = false) + { + return ($this->searchRetrieve($query, $options, $raw)); + } + + /** + * Performs a searchRetrieve operation and returns a SearchRetrieveResponse object or a string is $raw is true + * + * @param string $query The CQL query string + * @param array $options The query options ('version', 'maximumRecords', 'startRecord', 'recordSchema', 'recordPacking') + * @param bool $raw If true, returns the response as a string + * @return SearchRetrieveResponse|string + */ + public function searchRetrieve($query, $options = array(), $raw = false) + { + $options['operation'] = 'searchRetrieve'; + $options["query"] = $query; + $options["version"] = isset($options['version']) ? $options['version'] : $this->getDefaultSRUVersion(); + $options['maximumRecords'] = isset($options['maximumRecords']) ? $options['maximumRecords'] : $this->defaultMaximumRecords; + $options['startRecord'] = isset($options['startRecord']) ? $options['startRecord'] : 1; + if (isset($options['recordSchema']) || $this->defaultRecordSchema) + { + $options['recordSchema'] = isset($options['recordSchema']) ? $options['recordSchema'] : $this->defaultRecordSchema; + } + $options['recordPacking'] = isset($options['recordPacking']) ? $options['recordPacking'] : "xml"; + $searchRetrieveResponse = $this->fetch($options); + if ($raw == true) + { + $searchRetrieve = $searchRetrieveResponse->getBody(); + } + else + { + $searchXML = new \DOMDocument(); + $searchXML->loadXML($searchRetrieveResponse->getBody()); + + $searchRetrieve = new SearchRetrieveResponse($searchXML); + } + + return ($searchRetrieve); + } + + /** + * Performs a scan operation and returns a ScanResponse object or a string is $raw is true + * + * @param string $query The CQL query string + * @param array $options The query options ('version', 'maximumTerms', 'scanClause') + * @param bool $raw If true, returns the response as a string + * @return SearchRetrieveResponse|string + */ + public function scan($scanClause, $options = array(), $raw = false) + { + $options['operation'] = 'scan'; + $options["scanClause"] = $scanClause; + $options["version"] = isset($options['version']) ? $options['version'] : $this->getDefaultSRUVersion(); + $options['maximumTerms'] = isset($options['maximumTerms']) ? $options['maximumTerms'] : $this->defaultMaximumRecords; + + $scanResponse = $this->fetch($options); + if ($raw == true) + { + $scan = $scanResponse->getBody(); + } + else + { + $scan = new ScanResponse($scanResponse->getBody()); + } + return ($scan); + } + + /** + * Returns the supported recordSchema identifiers as defined in the explain response + * @return array + */ + public function recordSchemas() + { + $explain = $this->explain(); + $xpath = new \DOMXPath($explain); + $xpath->registerNamespace("zs", "http://www.loc.gov/zing/srw/"); + $xpath->registerNamespace("ex", "http://explain.z3950.org/dtd/2.0/"); + + $nodes = $xpath->query("/zs:explainResponse/zs:record/zs:recordData/ex:explain/ex:schemaInfo/ex:schema"); + $schemas = array(); + foreach ($nodes as $node) + { + $schemas[$node->getAttribute("name")] = array("identifier" => $node->getAttribute("identifier")); + $titleList = $node->getElementsByTagName("title"); + foreach ($titleList as $title) + { + $schemas[$node->getAttribute("name")]["title"] = $title->nodeValue; + } + } + return ($schemas); + } + + /** + * Returns the supported indexes as defined in the explain response + * @return array + */ + public function indexes() + { + $explain = $this->explain(); + $xpath = new \DOMXPath($explain); + $xpath->registerNamespace("zs", "http://www.loc.gov/zing/srw/"); + $xpath->registerNamespace("ex", "http://explain.z3950.org/dtd/2.0/"); + + $nodes = $xpath->query("/zs:explainResponse/zs:record/zs:recordData/ex:explain/ex:indexInfo/ex:index/ex:map/ex:name"); + $indexes = array(); + foreach ($nodes as $node) + { + $idx = array("set" => $node->getAttribute("set"), "name" => $node->nodeValue); + $nodeList = $node->parentNode->parentNode->getElementsByTagName('title'); + foreach ($nodeList as $title) + { + $idx['title'] = $title->nodeValue; + } + $indexes[$node->getAttribute("set") . "." . $node->nodeValue] = $idx; + } + return ($indexes); + } + + /** + * Performs the HTTP request based on the defined request method + * @param array $args + * @param array $options + * @return \Guzzle\Http\Message\Response + */ + protected function fetch(array $args = NULL, array $options = array()) + { + $client = $this->getHttpClient(); + + if($this->defaultHttpMethod == 'GET') + { + if(empty($args)) + { + $url = $this->getBaseUrl(); + } else { + $url = $this->getBaseUrl() . "?" . http_build_query($args); + } + + $request = $client->get($url, $args, $options); + $response = $request->send(); + + return $response; + } else + { + $request = $client->post($this->getBaseUrl(), array(), $args, $options); + $response = $request->send(); + + return $response; + } + } + + /** + * Returns the base URL of the SRU service + * @return string + */ + public function getBaseUrl() + { + return $this->baseUrl; + } + + /** + * Sets the base URL of the SRU service + * @param string $baseUrl + */ + public function setBaseUrl($baseUrl) + { + $this->baseUrl = $baseUrl; + } + + /** + * Returns the default record schema + * + * @return string + */ + public function getDefaultRecordSchema() + { + return $this->defaultRecordSchema; + } + + /** + * Sets the default record schema for searchRetrieve requests + * + * @param string $defaultRecordSchema + */ + public function setDefaultRecordSchema($defaultRecordSchema) + { + $this->defaultRecordSchema = $defaultRecordSchema; + } + + /** + * Returns the default maximum number of records to return in a searchRetrieve request + * @return int + */ + public function getDefaultMaximumRecords() + { + return $this->defaultMaximumRecords; + } + + /** + * Sets the default maximum number of records to return in a searchRetrieve request + * @param int $defaultMaximumRecords + */ + public function setDefaultMaximumRecords($defaultMaximumRecords) + { + $this->defaultMaximumRecords = $defaultMaximumRecords; + } + + /** + * Returns the HTTP method client will use with SRU service by default + * + * @return string + */ + public function getDefaultHttpMethod() + { + return $this->defaultHttpMethod; + } + + /** + * Sets the HTTP method the client will use with the SRU service by default + * @param string $defaultHttpMethod + */ + public function setDefaultHttpMethod($defaultHttpMethod) + { + $this->defaultHttpMethod = $defaultHttpMethod; + } + + /** + * Lazy loader for the GuzzleClient + * @return \Guzzle\Http\Client + */ + protected function getHttpClient() + { + if (!$this->httpClient) + { + $this->httpClient = new \Guzzle\Http\Client(); + } + return $this->httpClient; + } + + /** + * @return string + */ + public function getDefaultSRUVersion() + { + return $this->defaultSRUVersion; + } + + /** + * @param string $defaultSRUVersion + */ + public function setDefaultSRUVersion($defaultSRUVersion) + { + $this->defaultSRUVersion = $defaultSRUVersion; + } + +} + +?> \ No newline at end of file diff --git a/src/SRU/Record.php b/src/SRU/Record.php new file mode 100644 index 0000000..88d9702 --- /dev/null +++ b/src/SRU/Record.php @@ -0,0 +1,72 @@ +node = $node; + $this->doc = $doc; + $this->xpath = new \DOMXPath($this->doc); + $this->xpath->registerNamespace("zs", "http://www.loc.gov/zing/srw/"); + } + + public function packing() + { + if(!$this->recordPacking) { + $nodes = $this->xpath->query("./zs:recordPacking", $this->node); + foreach($nodes as $node) { + $this->recordPacking = $node->nodeValue; + } + } + return($this->recordPacking); + } + + public function schema() + { + if(!$this->recordSchema) { + $nodes = $this->xpath->query("./zs:recordSchema", $this->node); + foreach($nodes as $node) { + $this->recordSchema = $node->nodeValue; + } + } + return($this->recordSchema); + } + + public function position() + { + if(!$this->recordPosition) { + $nodes = $this->xpath->query("./zs:recordPosition", $this->node); + foreach($nodes as $node) { + $this->recordPosition = $node->nodeValue; + } + } + return($this->recordPosition); + } + + public function data($raw=false) + { + if(!$this->recordData) { + $nodes = $this->xpath->query("./zs:recordData", $this->node); + foreach($nodes as $node) { + $this->recordData = $node->firstChild; + } + } + if($raw && $this->packing() == "xml") { + $data = $this->doc->saveXML($this->recordData); + } else { + $data = $this->recordData; + } + + return($data); + } +} +?> \ No newline at end of file diff --git a/src/SRU/ScanResponse.php b/src/SRU/ScanResponse.php new file mode 100644 index 0000000..7b2b15c --- /dev/null +++ b/src/SRU/ScanResponse.php @@ -0,0 +1,21 @@ +doc = new \DOMDocument(); + $this->doc->loadXML($xml); + } elseif (is_a($xml, '\DOMDocument')) + { + $this->doc = $xml; + } else { + throw new \InvalidArgumentException('Argument must be an XML string or DOMDocument object'); + } + } +} diff --git a/src/SRU/SearchRetrieveResponse.php b/src/SRU/SearchRetrieveResponse.php new file mode 100644 index 0000000..f44be9c --- /dev/null +++ b/src/SRU/SearchRetrieveResponse.php @@ -0,0 +1,97 @@ +doc = new \DOMDocument(); + $this->doc->loadXML($xml); + } elseif (is_a($xml, '\DOMDocument')) + { + $this->doc = $xml; + } else { + throw new \InvalidArgumentException('Argument must be an XML string or DOMDocument object'); + } + + $this->xpath = new \DOMXPath($this->doc); + $this->xpath->registerNamespace("zs","http://www.loc.gov/zing/srw/"); + } + + /** + * @return int + */ + public function numberOfRecords() + { + if(!$this->numberOfRecords) { + $nodes = $this->xpath->query("/zs:searchRetrieveResponse/zs:numberOfRecords"); + foreach($nodes as $node) { + $this->numberOfRecords = (int) $node->nodeValue; + } + } + return($this->numberOfRecords); + } + + /** + * @return int + */ + public function nextRecordPosition() + { + if(!$this->nextRecordPosition) { + $nodes = $this->xpath->query("/zs:searchRetrieveResponse/zs:nextRecordPosition"); + foreach($nodes as $node) { + $this->nextRecordPosition = (int) $node->nodeValue; + } + } + return($this->nextRecordPosition); + } + + /** + * @return Record[] + */ + public function getRecords() + { + if(!$this->records) + { + $this->addRecords(); + } + return($this->records); + } + + protected function addRecords() + { + + $this->records = array(); + $nodes = $this->xpath->query("/zs:searchRetrieveResponse/zs:records/zs:record"); + foreach($nodes as $node) { + array_push($this->records, new Record($this->doc, $node)); + } + } +} +?> \ No newline at end of file