Skip to content

Commit 5132304

Browse files
committed
Complete response object, and add next() method to get next records in set
1 parent b3e2708 commit 5132304

File tree

6 files changed

+234
-21
lines changed

6 files changed

+234
-21
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ $client = new SruClient($url, array(
3939
'user-agent' => 'OpenKat/0.1'
4040
);
4141

42+
$records = array();
4243
$response = $client->search('dc.title="Hello world"');
44+
while ($response && count($response->records) != 0) {
45+
$records[] = array_merge($records, $response->records);
46+
$response = $response->next();
47+
}
48+
```
4349

4450
### To generate documentation
4551

src/Client.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,6 @@ public function __construct($url, $options = null, $httpClient = null)
5252
? $options['schema']
5353
: 'marcxml';
5454

55-
$this->namespaces = isset($options['namespaces'])
56-
? $options['namespaces']
57-
: array(
58-
'srw' => 'http://www.loc.gov/zing/srw/',
59-
'marc' => 'http://www.loc.gov/MARC21/slim',
60-
'd' => 'http://www.loc.gov/zing/srw/diagnostic/'
61-
);
62-
6355
$this->version = isset($options['version'])
6456
? $options['version']
6557
: '1.1';
@@ -134,7 +126,7 @@ public function search($cql, $start = 1, $count = 10) {
134126
$res = $this->httpClient->get($url, $options)->send();
135127
$body = $res->getBody(true);
136128

137-
return new Response($body, $this->namespaces);
129+
return new Response($body, $this);
138130

139131
}
140132

src/Record.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php namespace Scriptotek\Sru;
2+
3+
use Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement;
4+
5+
/**
6+
* Single record from a SRU response
7+
*/
8+
class Record {
9+
10+
/** @var int */
11+
public $position;
12+
13+
/** @var string */
14+
public $packing;
15+
16+
/** @var string */
17+
public $schema;
18+
19+
/** @var QuiteSimpleXMLElement */
20+
public $data;
21+
22+
/**
23+
* Create a new record
24+
*
25+
* @param Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement $doc
26+
*/
27+
public function __construct($doc)
28+
{
29+
$this->position = intval($doc->text('./srw:recordPosition'));
30+
$this->packing = $doc->text('./srw:recordPacking');
31+
$this->schema = $doc->text('./srw:recordSchema');
32+
$this->data = $doc->first('./srw:recordData');
33+
}
34+
35+
}

src/Response.php

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,37 @@
77
*/
88
class Response {
99

10-
/** @var Record[] */
10+
/** @var string Raw XML response */
11+
protected $rawResponse;
12+
13+
/** @var Client Reference to SRU client object */
14+
protected $client;
15+
16+
/** @var Record[] Array of records */
1117
public $records;
1218

13-
/** @var string */
19+
/** @var string Error message */
1420
public $error;
1521

16-
/** @var string */
17-
protected $rawResponse;
22+
/** @var string SRU protocol version */
23+
public $version;
24+
25+
/** @var int Total number of records in the result set */
26+
public $numberOfRecords;
27+
28+
/** @var int Position of next record in the result set, or null if no such record exist */
29+
public $nextRecordPosition;
30+
31+
/** @var string The CQL query used to generate the response */
32+
public $query;
1833

1934
/**
2035
* Create a new response
2136
*
22-
* @param string $text
37+
* @param string $text Raw XML response
38+
* @param Client $client SRU client reference (optional)
2339
*/
24-
public function __construct($text)
40+
public function __construct($text, &$client = null)
2541
{
2642
$this->rawResponse = $text;
2743
try {
@@ -34,16 +50,25 @@ public function __construct($text)
3450
'srw' => 'http://www.loc.gov/zing/srw/',
3551
'd' => 'http://www.loc.gov/zing/srw/diagnostic/'
3652
));
37-
53+
54+
$this->version = $doc->text('/srw:searchRetrieveResponse/srw:version');
55+
$this->numberOfRecords = (int) $doc->text('/srw:searchRetrieveResponse/srw:numberOfRecords');
56+
$this->nextRecordPosition = (int) $doc->text('/srw:searchRetrieveResponse/srw:nextRecordPosition') ?: null;
57+
3858
$this->records = array();
3959
foreach ($doc->xpath('/srw:searchRetrieveResponse/srw:records/srw:record') as $record) {
40-
$this->records[] = $record;
60+
$this->records[] = new Record($record);
4161
}
4262

63+
$this->client = $client;
64+
65+
// The server may echo the request back to the client along with the response
66+
$this->query = $doc->text('/srw:searchRetrieveResponse/srw:echoedSearchRetrieveRequest/srw:query') ?: null;
67+
4368
}
4469

4570
/**
46-
* Return the raw xml response
71+
* Get the raw xml response
4772
*
4873
* @return string
4974
*/
@@ -52,9 +77,23 @@ public function asXml()
5277
return $this->rawResponse;
5378
}
5479

80+
/**
81+
* Request next batch of records in the result set, or return null if we're at the end of the set
82+
*
83+
* @return Response
84+
*/
5585
public function next()
5686
{
57-
# code...
87+
if (is_null($this->client)) {
88+
throw new \Exception('No client reference passed to response');
89+
}
90+
if (is_null($this->query)) {
91+
throw new \Exception('No query available');
92+
}
93+
if (is_null($this->nextRecordPosition)) {
94+
return null;
95+
}
96+
return $this->client->search($this->query, $this->nextRecordPosition, count($this->records));
5897
}
5998

6099
}

tests/ClientTest.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,97 @@ public function testSearchWithAuth()
6363
$sru->search('test');
6464
}
6565

66+
public function testNext()
67+
{
68+
$cql = 'dc.title="Joda jada isjda"';
69+
70+
$request = m::mock();
71+
$request->shouldReceive('send')
72+
->once()
73+
->andReturn(new HttpResponse(200, null, '<?xml version="1.0" encoding="UTF-8" ?>
74+
<srw:searchRetrieveResponse
75+
xmlns:srw="http://www.loc.gov/zing/srw/"
76+
xmlns:xcql="http://www.loc.gov/zing/cql/xcql/"
77+
>
78+
<srw:version>1.1</srw:version>
79+
<srw:numberOfRecords>3</srw:numberOfRecords>
80+
<srw:records>
81+
<srw:record>
82+
<srw:recordSchema>marcxchange</srw:recordSchema>
83+
<srw:recordPacking>xml</srw:recordPacking>
84+
<srw:recordPosition>1</srw:recordPosition>
85+
<srw:recordData>Record 1</srw:recordData>
86+
</srw:record>
87+
<srw:record>
88+
<srw:recordSchema>marcxchange</srw:recordSchema>
89+
<srw:recordPacking>xml</srw:recordPacking>
90+
<srw:recordPosition>2</srw:recordPosition>
91+
<srw:recordData>Record 2</srw:recordData>
92+
</srw:record>
93+
</srw:records>
94+
<srw:nextRecordPosition>3</srw:nextRecordPosition>
95+
<srw:echoedSearchRetrieveRequest>
96+
<srw:operation>searchRetrieve</srw:operation>
97+
<srw:version>1.1</srw:version>
98+
<srw:query>' . $cql . '</srw:query>
99+
<srw:startRecord>1</srw:startRecord>
100+
<srw:maximumRecords>2</srw:maximumRecords>
101+
<srw:recordSchema>marcxchange</srw:recordSchema>
102+
</srw:echoedSearchRetrieveRequest>
103+
<srw:extraResponseData>
104+
<responseDate>2014-03-28T12:09:50Z</responseDate>
105+
</srw:extraResponseData>
106+
</srw:searchRetrieveResponse>
107+
'));
108+
109+
$http = m::mock();
110+
$http->shouldReceive('get')
111+
->once()
112+
->andReturn($request);
113+
114+
$sru = new Client($this->url, null, $http);
115+
$response = $sru->search($cql);
116+
$this->assertCount(2, $response->records);
117+
118+
$request->shouldReceive('send')
119+
->once()
120+
->andReturn(new HttpResponse(200, null, '<?xml version="1.0" encoding="UTF-8" ?>
121+
<srw:searchRetrieveResponse
122+
xmlns:srw="http://www.loc.gov/zing/srw/"
123+
xmlns:xcql="http://www.loc.gov/zing/cql/xcql/"
124+
>
125+
<srw:version>1.1</srw:version>
126+
<srw:numberOfRecords>3</srw:numberOfRecords>
127+
<srw:records>
128+
<srw:record>
129+
<srw:recordSchema>marcxchange</srw:recordSchema>
130+
<srw:recordPacking>xml</srw:recordPacking>
131+
<srw:recordPosition>3</srw:recordPosition>
132+
<srw:recordData>Record 3</srw:recordData>
133+
</srw:record>
134+
</srw:records>
135+
<srw:echoedSearchRetrieveRequest>
136+
<srw:operation>searchRetrieve</srw:operation>
137+
<srw:version>1.1</srw:version>
138+
<srw:query>' . $cql . '</srw:query>
139+
<srw:startRecord>3</srw:startRecord>
140+
<srw:maximumRecords>2</srw:maximumRecords>
141+
<srw:recordSchema>marcxchange</srw:recordSchema>
142+
</srw:echoedSearchRetrieveRequest>
143+
<srw:extraResponseData>
144+
<responseDate>2014-03-28T12:09:50Z</responseDate>
145+
</srw:extraResponseData>
146+
</srw:searchRetrieveResponse>
147+
'));
148+
149+
$response = $response->next();
150+
$this->assertCount(1, $response->records);
151+
152+
$response = $response->next();
153+
$this->assertNull($response);
154+
155+
156+
}
157+
66158
}
67159

tests/ResponseTest.php

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,49 @@
55

66
class ResponseTest extends TestCase {
77

8-
public function testParse()
8+
public function testSingleRecordResult()
9+
{
10+
$res = new Response('<?xml version="1.0" encoding="UTF-8" ?>
11+
<srw:searchRetrieveResponse
12+
xmlns:srw="http://www.loc.gov/zing/srw/"
13+
xmlns:xcql="http://www.loc.gov/zing/cql/xcql/"
14+
>
15+
<srw:version>1.1</srw:version>
16+
<srw:numberOfRecords>1</srw:numberOfRecords>
17+
<srw:records>
18+
<srw:record>
19+
<srw:recordSchema>marcxchange</srw:recordSchema>
20+
<srw:recordPacking>xml</srw:recordPacking>
21+
<srw:recordPosition>1</srw:recordPosition>
22+
<srw:recordData>Record 1</srw:recordData>
23+
</srw:record>
24+
</srw:records>
25+
<srw:echoedSearchRetrieveRequest>
26+
<srw:operation>searchRetrieve</srw:operation>
27+
<srw:version>1.1</srw:version>
28+
<srw:query>bs.avdelingsamling = &quot;urealastr&quot; AND bs.lokal-klass = &quot;k C11?&quot;</srw:query>
29+
<srw:startRecord>1</srw:startRecord>
30+
<srw:maximumRecords>2</srw:maximumRecords>
31+
<srw:recordSchema>marcxchange</srw:recordSchema>
32+
</srw:echoedSearchRetrieveRequest>
33+
<srw:extraResponseData>
34+
<responseDate>2014-03-28T12:09:50Z</responseDate>
35+
</srw:extraResponseData>
36+
</srw:searchRetrieveResponse>');
37+
38+
$this->assertNull($res->error);
39+
$this->assertEquals('1.1', $res->version);
40+
$this->assertEquals(1, $res->numberOfRecords);
41+
$this->assertNull($res->nextRecordPosition);
42+
43+
$this->assertCount(1, $res->records);
44+
$this->assertEquals(1, $res->records[0]->position);
45+
$this->assertEquals('marcxchange', $res->records[0]->schema);
46+
$this->assertEquals('xml', $res->records[0]->packing);
47+
$this->assertEquals('Record 1', $res->records[0]->data);
48+
}
49+
50+
public function testMultipleRecordsResult()
951
{
1052
$res = new Response('<?xml version="1.0" encoding="UTF-8" ?>
1153
<srw:searchRetrieveResponse
@@ -42,9 +84,16 @@ public function testParse()
4284
</srw:extraResponseData>
4385
</srw:searchRetrieveResponse>');
4486

45-
$this->assertCount(2, $res->records);
4687
$this->assertNull($res->error);
88+
$this->assertEquals('1.1', $res->version);
89+
$this->assertEquals(303, $res->numberOfRecords);
90+
$this->assertEquals(3, $res->nextRecordPosition);
4791

92+
$this->assertCount(2, $res->records);
93+
$this->assertEquals(1, $res->records[0]->position);
94+
$this->assertEquals('marcxchange', $res->records[0]->schema);
95+
$this->assertEquals('xml', $res->records[0]->packing);
96+
$this->assertEquals('Record 1', $res->records[0]->data);
4897
}
4998

5099
}

0 commit comments

Comments
 (0)