Passed
Push — main ( 6731d6...4efee0 )
by Dan Michael O.
11:38
created

Response::asXml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Scriptotek\Sru;
4
5
use Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement;
6
7
/**
8
 * Generic SRU response
9
 */
10
class Response implements ResponseInterface
11
{
12
    public static array $nsPrefixes = array(
13
        'srw' => 'http://www.loc.gov/zing/srw/',
14
        'exp' => 'http://explain.z3950.org/dtd/2.0/',
15
        'd' => 'http://www.loc.gov/zing/srw/diagnostic/',
16
        'marc' => 'http://www.loc.gov/MARC21/slim',
17
    );
18
19
    public static array $errorMessages = array(
20
        'info:srw/diagnostic/1/1' => 'General system error',
21
        'info:srw/diagnostic/1/2' => 'System temporarily unavailable',
22
        'info:srw/diagnostic/1/3' => 'Authentication error',
23
        'info:srw/diagnostic/1/4' => 'Unsupported operation',
24
        'info:srw/diagnostic/1/5' => 'Unsupported version',
25
        'info:srw/diagnostic/1/6' => 'Unsupported parameter value',
26
        'info:srw/diagnostic/1/7' => 'Mandatory parameter not supplied',
27
        'info:srw/diagnostic/1/8' => 'Unsupported parameter',
28
        'info:srw/diagnostic/1/10' => 'Query syntax error',
29
        'info:srw/diagnostic/1/12' => 'Too many characters in query',
30
        'info:srw/diagnostic/1/13' => 'Invalid or unsupported use of parentheses',
31
        'info:srw/diagnostic/1/14' => 'Invalid or unsupported use of quotes',
32
        'info:srw/diagnostic/1/15' => 'Unsupported context set',
33
        'info:srw/diagnostic/1/16' => 'Unsupported index',
34
        'info:srw/diagnostic/1/18' => 'Unsupported combination of indexes',
35
        'info:srw/diagnostic/1/19' => 'Unsupported relation',
36
        'info:srw/diagnostic/1/20' => 'Unsupported relation modifier',
37
        'info:srw/diagnostic/1/21' => 'Unsupported combination of relation modifers',
38
        'info:srw/diagnostic/1/22' => 'Unsupported combination of relation and index',
39
        'info:srw/diagnostic/1/23' => 'Too many characters in term',
40
        'info:srw/diagnostic/1/24' => 'Unsupported combination of relation and term',
41
        'info:srw/diagnostic/1/26' => 'Non special character escaped in term',
42
        'info:srw/diagnostic/1/27' => 'Empty term unsupported',
43
        'info:srw/diagnostic/1/28' => 'Masking character not supported',
44
        'info:srw/diagnostic/1/29' => 'Masked words too short',
45
        'info:srw/diagnostic/1/30' => 'Too many masking characters in term',
46
        'info:srw/diagnostic/1/31' => 'Anchoring character not supported',
47
        'info:srw/diagnostic/1/32' => 'Anchoring character in unsupported position',
48
        'info:srw/diagnostic/1/33' => 'Combination of proximity/adjacency and masking characters not supported',
49
        'info:srw/diagnostic/1/34' => 'Combination of proximity/adjacency and anchoring characters not supported',
50
        'info:srw/diagnostic/1/35' => 'Term contains only stopwords',
51
        'info:srw/diagnostic/1/36' => 'Term in invalid format for index or relatio',
52
        'info:srw/diagnostic/1/37' => 'Unsupported boolean operator',
53
        'info:srw/diagnostic/1/38' => 'Too many boolean operators in query',
54
        'info:srw/diagnostic/1/39' => 'Proximity not supported',
55
        'info:srw/diagnostic/1/40' => 'Unsupported proximity relation',
56
        'info:srw/diagnostic/1/41' => 'Unsupported proximity distance',
57
        'info:srw/diagnostic/1/42' => 'Unsupported proximity unit',
58
        'info:srw/diagnostic/1/43' => 'Unsupported proximity ordering',
59
        'info:srw/diagnostic/1/44' => 'Unsupported combination of proximity modifiers',
60
        'info:srw/diagnostic/1/46' => 'Unsupported boolean modifier',
61
        'info:srw/diagnostic/1/47' => 'Cannot process query; reason unknown',
62
        'info:srw/diagnostic/1/48' => 'Query feature unsupported',
63
        'info:srw/diagnostic/1/49' => 'Masking character in unsupported position',
64
        'info:srw/diagnostic/1/50' => 'Result sets not supported',
65
        'info:srw/diagnostic/1/51' => 'Result set does not exist',
66
        'info:srw/diagnostic/1/52' => 'Result set temporarily unavailable',
67
        'info:srw/diagnostic/1/53' => 'Result sets only supported for retrieval',
68
        'info:srw/diagnostic/1/55' => 'Combination of result sets with search terms not supported',
69
        'info:srw/diagnostic/1/58' => 'Result set created with unpredictable partial results available',
70
        'info:srw/diagnostic/1/59' => 'Result set created with valid partial results available',
71
        'info:srw/diagnostic/1/60' => 'Result set not created: too many matching records',
72
        'info:srw/diagnostic/1/61' => 'First record position out of range',
73
        'info:srw/diagnostic/1/64' => 'Record temporarily unavailable',
74
        'info:srw/diagnostic/1/65' => 'Record does not exist',
75
        'info:srw/diagnostic/1/66' => 'Unknown schema for retrieval',
76
        'info:srw/diagnostic/1/67' => 'Record not available in this schema',
77
        'info:srw/diagnostic/1/68' => 'Not authorised to send record',
78
        'info:srw/diagnostic/1/69' => 'Not authorised to send record in this schema',
79
        'info:srw/diagnostic/1/70' => 'Record too large to send',
80
        'info:srw/diagnostic/1/71' => 'Unsupported record packing',
81
        'info:srw/diagnostic/1/72' => 'XPath retrieval unsupported',
82
        'info:srw/diagnostic/1/73' => 'XPath expression contains unsupported feature',
83
        'info:srw/diagnostic/1/74' => 'Unable to evaluate XPath expression',
84
        'info:srw/diagnostic/1/80' => 'Sort not supported',
85
        'info:srw/diagnostic/1/82' => 'Unsupported sort sequence',
86
        'info:srw/diagnostic/1/83' => 'Too many records to sort',
87
        'info:srw/diagnostic/1/84' => 'Too many sort keys to sort',
88
        'info:srw/diagnostic/1/86' => 'Cannot sort: incompatible record formats',
89
        'info:srw/diagnostic/1/87' => 'Unsupported schema for sort',
90
        'info:srw/diagnostic/1/88' => 'Unsupported path for sort',
91
        'info:srw/diagnostic/1/89' => 'Path unsupported for schema',
92
        'info:srw/diagnostic/1/90' => 'Unsupported direction',
93
        'info:srw/diagnostic/1/91' => 'Unsupported case',
94
        'info:srw/diagnostic/1/92' => 'Unsupported missing value action',
95
        'info:srw/diagnostic/1/93' => 'Sort ended due to missing value',
96
        'info:srw/diagnostic/1/94' => 'Sort spec included both in query and protocol: query prevails',
97
        'info:srw/diagnostic/1/95' => 'Sort spec included both in query and protocol: protocol prevails',
98
        'info:srw/diagnostic/1/96' => 'Sort spec included both in query and protocol: error',
99
        'info:srw/diagnostic/1/110' => 'Stylesheets not supported',
100
        'info:srw/diagnostic/1/120' => 'Response position out of range',
101
        'info:srw/diagnostic/1/130' => 'Too many terms matched by masked query term',
102
    );
103
104
    /** @var string Raw XML response */
105
    protected string $rawResponse = '';
106
107
    /** @var QuiteSimpleXMLElement|null XML response */
108
    protected ?QuiteSimpleXMLElement $response = null;
109
110
    /** @var Client|null Reference to SRU client object */
111
    protected ?Client $client = null;
112
113
    /** @var string|null SRU protocol version */
114
    public ?string $version = null;
115
116
    /**
117
     * Create a new response
118
     *
119
     * @param string|null $text Raw XML response
120
     * @param Client|null $client SRU client reference (optional)
121
     * @param string|null $url
122
     */
123
    public function __construct(string $text = null, Client &$client = null, string $url = null)
124
    {
125
        $this->client = $client;
126
127
        if (!is_null($text)) {
128
            $this->initializeFromText($text, $url);
129
        }
130
    }
131
132
    protected function initializeFromText($text, $url)
133
    {
134
        // Fix missing namespace in Alma records:
135
        $text = str_replace('<record xmlns="">', '<record xmlns="http://www.loc.gov/MARC21/slim">', $text);
136
137
        $this->rawResponse = $text;
138
139
        // Throws Danmichaelo\QuiteSimpleXMLElement\InvalidXMLException on invalid xml
140
        $this->response = QuiteSimpleXMLElement::make($text, self::$nsPrefixes);
141
142
        $this->version = $this->response->text('/srw:*/srw:version');
143
144
        $this->handleDiagnostic($url, $this->response->first('/srw:*/srw:diagnostics/d:diagnostic'));
145
    }
146
147
    protected function handleDiagnostic($url, QuiteSimpleXMLElement $node = null)
148
    {
149
        if (is_null($node)) {
150
            return;
151
        }
152
153
        // Only the 'uri' field is required, 'message' and 'details' are optional
154
        $uri = $node->text('d:uri');
155
        if (strlen($uri)) {
156
            $msg = $node->text('d:message');
157
            $details = $node->text('d:details');
158
            if (empty($msg)) {
159
                $msg = self::$errorMessages[$uri] ?? 'Unknown error';
160
            }
161
            if (!empty($details)) {
162
                $msg .= ' (' . $details . ')';
163
            }
164
            throw new Exceptions\SruErrorException($msg, $uri, $url);
165
        }
166
    }
167
168
    /**
169
     * Get the raw xml response
170
     *
171
     * @return string
172
     */
173
    public function asXml(): string
174
    {
175
        return $this->rawResponse;
176
    }
177
}
178